import { useCallback, useEffect, useState } from 'react';

export interface UseCommandPaletteOptions {
  /** Default hotkey: Cmd-K / Ctrl-K. Pass `null` to disable. */
  hotkey?: { key: string; meta?: boolean; ctrl?: boolean; shift?: boolean } | null;
  /** Initial open state. */
  defaultOpen?: boolean;
}

export interface UseCommandPaletteHelpers {
  open: boolean;
  show: () => void;
  hide: () => void;
  toggle: () => void;
}

/**
 * Manages open/closed state for `<CommandPalette>` and (optionally)
 * binds a global hotkey. Drop it next to your app shell:
 *
 * ```tsx
 * const cmdk = useCommandPalette();
 * return (
 *   <>
 *     <YourApp />
 *     <CommandPalette open={cmdk.open} onClose={cmdk.hide} />
 *   </>
 * );
 * ```
 *
 * The default hotkey (`Cmd-K` / `Ctrl-K`) is suppressed inside text
 * inputs unless the user explicitly holds the modifier.
 */
export function useCommandPalette(
  options: UseCommandPaletteOptions = {}
): UseCommandPaletteHelpers {
  const { hotkey = { key: 'k', meta: true, ctrl: true }, defaultOpen = false } = options;

  const [open, setOpen] = useState(defaultOpen);
  const show = useCallback(() => setOpen(true), []);
  const hide = useCallback(() => setOpen(false), []);
  const toggle = useCallback(() => setOpen(o => !o), []);

  useEffect(() => {
    if (!hotkey) return;
    const handler = (e: KeyboardEvent) => {
      // Some keydown events (autofill, IME/composition, certain extensions) arrive
      // with an undefined `key`; guard so we never crash on `.toLowerCase()`.
      if (!e.key || !hotkey.key) return;
      if (e.key.toLowerCase() !== hotkey.key.toLowerCase()) return;
      const wantMeta = hotkey.meta ?? false;
      const wantCtrl = hotkey.ctrl ?? false;
      const wantShift = hotkey.shift ?? false;
      // Match if EITHER meta or ctrl is held when both are flagged (Mac/Win parity).
      const modOk =
        wantMeta || wantCtrl
          ? (wantMeta && e.metaKey) || (wantCtrl && e.ctrlKey)
          : !e.metaKey && !e.ctrlKey;
      const shiftOk = wantShift ? e.shiftKey : true;
      if (modOk && shiftOk) {
        e.preventDefault();
        setOpen(o => !o);
      }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [hotkey]);

  return { open, show, hide, toggle };
}
