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 DropdownMenu sub-components. */
export interface InternalDropdownMenuContextValue {
  isOpen: Accessor<boolean>;
  open: () => void;
  close: () => void;
  toggle: () => void;
  navigation: ListNavigationState;
  triggerRef: Accessor<HTMLElement | null>;
  setTriggerRef: (el: HTMLElement | null) => void;
  contentRef: Accessor<HTMLElement | null>;
  setContentRef: (el: HTMLElement | null) => void;
  contentId: string;
  triggerId: string;
  floatingStyle: Accessor<JSX.CSSProperties>;
  /** Called when a regular menu item is activated. Closes the menu. */
  onItemActivate: (value: string) => void;
  /** Register a menu item value and optional onSelect handler. */
  registerItem: (value: string, handler?: (() => void) | undefined) => void;
  /** Unregister a menu item value. */
  unregisterItem: (value: string) => void;
}

const InternalDropdownMenuContext = createContext<InternalDropdownMenuContextValue>();

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

export const InternalDropdownMenuContextProvider = InternalDropdownMenuContext.Provider;

/** Context for DropdownMenu RadioGroup. */
export interface DropdownMenuRadioGroupContextValue {
  value: Accessor<string | undefined>;
  onValueChange: ((value: string) => void) | undefined;
}

const DropdownMenuRadioGroupContext = createContext<DropdownMenuRadioGroupContextValue>();

/**
 * Returns the DropdownMenu RadioGroup context. Throws if used outside RadioGroup.
 */
export function useDropdownMenuRadioGroupContext(): DropdownMenuRadioGroupContextValue {
  const ctx = useContext(DropdownMenuRadioGroupContext);
  if (!ctx) {
    throw new Error(
      "[PettyUI] DropdownMenu.RadioItem must be used inside <DropdownMenu.RadioGroup>.",
    );
  }
  return ctx;
}

export const DropdownMenuRadioGroupContextProvider = DropdownMenuRadioGroupContext.Provider;

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

const DropdownMenuPublicContext = createContext<DropdownMenuContextValue>();

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

export const DropdownMenuPublicContextProvider = DropdownMenuPublicContext.Provider;
