import type { Accessor, JSX } from "solid-js";
import { createContext, useContext } from "solid-js";
import type { ListNavigationState } from "../../primitives/create-list-navigation";

/** Internal context shared between all ContextMenu sub-components. */
export interface InternalContextMenuContextValue {
  isOpen: Accessor<boolean>;
  open: () => void;
  close: () => void;
  navigation: ListNavigationState;
  contentRef: Accessor<HTMLElement | null>;
  setContentRef: (el: HTMLElement | null) => void;
  contentId: string;
  floatingStyle: Accessor<JSX.CSSProperties>;
  /** Update the virtual anchor position from pointer coordinates. */
  setAnchorPosition: (x: number, y: number) => void;
  /** Called when a regular menu item is activated. Closes the menu. */
  onItemActivate: (value: string) => void;
  /** Register an item's onSelect callback. */
  registerItemHandler: (value: string, handler: () => void) => void;
  /** Unregister an item's onSelect callback. */
  unregisterItemHandler: (value: string) => void;
}

const InternalContextMenuContext = createContext<InternalContextMenuContextValue>();

/**
 * Returns the internal ContextMenu context. Throws if used outside ContextMenu.
 */
export function useInternalContextMenuContext(): InternalContextMenuContextValue {
  const ctx = useContext(InternalContextMenuContext);
  if (!ctx) {
    throw new Error(
      "[PettyUI] ContextMenu parts must be used inside <ContextMenu>.\n" +
        "  Fix: <ContextMenu items={[...]}>\n" +
        "         <ContextMenu.Trigger>...</ContextMenu.Trigger>\n" +
        "         <ContextMenu.Content>\n" +
        '           <ContextMenu.Item value="a">A</ContextMenu.Item>\n' +
        "         </ContextMenu.Content>\n" +
        "       </ContextMenu>",
    );
  }
  return ctx;
}

export const InternalContextMenuContextProvider = InternalContextMenuContext.Provider;

/** Public context exposed via ContextMenu.useContext(). */
export interface ContextMenuContextValue {
  /** Whether the context menu is open. */
  open: Accessor<boolean>;
}

const ContextMenuPublicContext = createContext<ContextMenuContextValue>();

/**
 * Returns the public ContextMenu context. Throws if used outside ContextMenu.
 */
export function useContextMenuContext(): ContextMenuContextValue {
  const ctx = useContext(ContextMenuPublicContext);
  if (!ctx) {
    throw new Error("[PettyUI] ContextMenu.useContext() called outside of <ContextMenu>.");
  }
  return ctx;
}

export const ContextMenuPublicContextProvider = ContextMenuPublicContext.Provider;
