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 Combobox sub-components. */
export interface InternalComboboxContextValue {
  isOpen: Accessor<boolean>;
  open: () => void;
  close: () => void;
  toggle: () => void;
  navigation: ListNavigationState;
  inputRef: Accessor<HTMLInputElement | null>;
  setInputRef: (el: HTMLInputElement | null) => void;
  contentRef: Accessor<HTMLElement | null>;
  setContentRef: (el: HTMLElement | null) => void;
  selectedValue: Accessor<string | undefined>;
  onSelect: (value: string) => void;
  disabled: Accessor<boolean>;
  required: Accessor<boolean>;
  name: Accessor<string | undefined>;
  contentId: string;
  inputId: string;
  items: Accessor<string[]>;
  inputValue: Accessor<string>;
  setInputValue: (value: string) => void;
  onInputChange: ((value: string) => void) | undefined;
  allowCustomValue: Accessor<boolean>;
  onCustomValue: (value: string) => void;
  floatingStyle: Accessor<JSX.CSSProperties>;
}

const InternalComboboxContext = createContext<InternalComboboxContextValue>();

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

export const InternalComboboxContextProvider = InternalComboboxContext.Provider;

/** Public context exposed via Combobox.useContext(). */
export interface ComboboxContextValue {
  /** Currently selected value. */
  value: Accessor<string | undefined>;
  /** Whether the combobox dropdown is open. */
  open: Accessor<boolean>;
  /** Current input text. */
  inputValue: Accessor<string>;
}

const ComboboxContext = createContext<ComboboxContextValue>();

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

export const ComboboxContextProvider = ComboboxContext.Provider;
