import { useEffect, useMemo, useRef, useState } from "react";
import { navItems, type View } from "../App";
import { ArrowRight } from "lucide-react";

interface CommandPaletteProps {
  open: boolean;
  onClose: () => void;
  onSelect: (view: View) => void;
}

interface PaletteItem {
  id: string;
  label: string;
  hint?: string;
  view: View;
}

// ponytail: command palette is just nav items + the dashboard. A separate
// index of generated NPCs/items/quests would need persistence first, which
// is P1; ship the jump-to-tool now and extend later.
function buildItems(): PaletteItem[] {
  const items: PaletteItem[] = [
    { id: "dashboard", label: "Dashboard", hint: "Home", view: "dashboard" },
    ...navItems.map((n) => ({
      id: n.view,
      label: n.label,
      hint: n.shortcut ?? (n.group === "session" ? "Session" : "World"),
      view: n.view,
    })),
    { id: "settings", label: "Settings", hint: "⌘,", view: "settings" },
  ];
  return items;
}

export function CommandPalette({ open, onClose, onSelect }: CommandPaletteProps) {
  const [query, setQuery] = useState("");
  const [activeIdx, setActiveIdx] = useState(0);
  const inputRef = useRef<HTMLInputElement>(null);

  const items = useMemo(() => buildItems(), []);

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return items;
    return items.filter((it) => it.label.toLowerCase().includes(q));
  }, [items, query]);

  // Focus input + reset on open.
  useEffect(() => {
    if (open) {
      setQuery("");
      setActiveIdx(0);
      // requestAnimationFrame avoids the focus racing the open transition.
      requestAnimationFrame(() => inputRef.current?.focus());
    }
  }, [open]);

  // Keep the active row in view as the user arrows around.
  useEffect(() => {
    if (activeIdx >= filtered.length) setActiveIdx(0);
  }, [filtered.length, activeIdx]);

  if (!open) return null;

  function onKeyDown(e: React.KeyboardEvent) {
    if (e.key === "ArrowDown") {
      e.preventDefault();
      setActiveIdx((i) => (filtered.length === 0 ? 0 : (i + 1) % filtered.length));
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setActiveIdx((i) =>
        filtered.length === 0 ? 0 : (i - 1 + filtered.length) % filtered.length,
      );
    } else if (e.key === "Enter") {
      e.preventDefault();
      const item = filtered[activeIdx];
      if (item) onSelect(item.view);
    } else if (e.key === "Escape") {
      e.preventDefault();
      onClose();
    }
  }

  return (
    <div
      className="fixed inset-0 z-40 flex items-start justify-center pt-24 px-4"
      onClick={onClose}
      role="dialog"
      aria-modal="true"
      aria-label="Command palette"
    >
      <div className="absolute inset-0 bg-black/40" aria-hidden="true" />
      <div
        className="relative w-full max-w-md glass-card p-2 shadow-2xl"
        onClick={(e) => e.stopPropagation()}
      >
        <input
          ref={inputRef}
          value={query}
          onChange={(e) => {
            setQuery(e.target.value);
            setActiveIdx(0);
          }}
          onKeyDown={onKeyDown}
          placeholder="Jump anywhere…"
          aria-label="Search tools"
          className="w-full bg-transparent px-3 py-2 text-sm text-[var(--color-text-primary)] placeholder-[var(--color-text-dim)] focus:outline-none"
        />
        <div className="border-t border-[var(--color-border-subtle)] mt-1 max-h-72 overflow-y-auto">
          {filtered.length === 0 && (
            <div className="px-3 py-4 text-xs text-[var(--color-text-dim)]">No matches.</div>
          )}
          {filtered.map((it, i) => (
            <button
              key={it.id}
              onClick={() => onSelect(it.view)}
              onMouseEnter={() => setActiveIdx(i)}
              className={`w-full flex items-center justify-between gap-2 px-3 py-2 text-left text-sm rounded cursor-pointer transition-colors ${
                i === activeIdx
                  ? "bg-[var(--color-bg-card)] text-[var(--color-gold-bright)]"
                  : "text-[var(--color-text-primary)]"
              }`}
            >
              <span>{it.label}</span>
              <span className="flex items-center gap-1.5">
                {it.hint && (
                  <kbd className="px-1.5 py-0.5 rounded border border-[var(--color-border-subtle)] bg-[var(--color-bg-deep)] text-[10px] font-mono text-[var(--color-text-dim)]">
                    {it.hint}
                  </kbd>
                )}
                <ArrowRight
                  size={12}
                  className={
                    i === activeIdx ? "text-[var(--color-gold-bright)]" : "text-[var(--color-text-dim)]"
                  }
                />
              </span>
            </button>
          ))}
        </div>
        <div className="flex items-center justify-between px-3 pt-2 text-[10px] text-[var(--color-text-dim)]">
          <span>↑↓ navigate · ↵ open</span>
          <span>esc to close</span>
        </div>
      </div>
    </div>
  );
}
