import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import { useNavigate } from '@tanstack/react-router';
import type { LucideIcon } from 'lucide-react';
import {
  Search,
  Music,
  Disc3,
  Users,
  Tag,
  Zap,
  Compass,
  Settings,
  ShieldAlert,
  Terminal,
  Home,
  ArrowRight,
} from 'lucide-react';

interface CommandItem {
  id: string;
  label: string;
  description?: string;
  icon: LucideIcon;
  action: () => void;
  keywords?: string[];
}

const NAV_COMMANDS: CommandItem[] = [
  { id: 'nav-home', label: 'Home', icon: Home, action: () => {}, keywords: ['dashboard', 'start'] },
  { id: 'nav-tracks', label: 'Songs', description: 'Browse all tracks', icon: Music, action: () => {}, keywords: ['tracks', 'music', 'songs'] },
  { id: 'nav-albums', label: 'Albums', icon: Disc3, action: () => {}, keywords: ['albums', 'records'] },
  { id: 'nav-artists', label: 'Artists', icon: Users, action: () => {}, keywords: ['artists', 'bands'] },
  { id: 'nav-genres', label: 'Genres', icon: Tag, action: () => {}, keywords: ['genres', 'tags', 'categories'] },
  { id: 'nav-vibe', label: 'Vibe', description: 'Endless recommendations', icon: Zap, action: () => {}, keywords: ['vibe', 'recommendations', 'radio'] },
  { id: 'nav-recommendations', label: 'Found', description: 'Discovered tracks and their fate', icon: Compass, action: () => {}, keywords: ['found', 'discovery', 'recommendations', 'probation', 'new releases'] },
  { id: 'nav-quarantine', label: 'Quarantine', icon: ShieldAlert, action: () => {}, keywords: ['quarantine', 'disliked', 'trash'] },
  { id: 'nav-jobs', label: 'Jobs', description: 'Background tasks', icon: Terminal, action: () => {}, keywords: ['jobs', 'tasks', 'queue'] },
  { id: 'nav-settings', label: 'Settings', icon: Settings, action: () => {}, keywords: ['settings', 'preferences', 'config'] },
];

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

export function CommandPalette({ open, onClose }: CommandPaletteProps) {
  const navigate = useNavigate();
  const inputRef = useRef<HTMLInputElement>(null);
  const listRef = useRef<HTMLDivElement>(null);
  const [query, setQuery] = useState('');
  const [selectedIndex, setSelectedIndex] = useState(0);

  // Bind navigation to each command action
  const commands = useMemo(
    () =>
      NAV_COMMANDS.map((cmd) => ({
        ...cmd,
        action: () => {
          const pathMap: Record<string, string> = {
            'nav-home': '/',
            'nav-tracks': '/tracks',
            'nav-albums': '/albums',
            'nav-artists': '/artists',
            'nav-genres': '/genres',
            'nav-vibe': '/vibe',
            'nav-recommendations': '/recommendations',
            'nav-quarantine': '/quarantine',
            'nav-jobs': '/jobs',
            'nav-settings': '/settings',
          };
          const path = pathMap[cmd.id] ?? '/';
          void navigate({ to: path as any });
          onClose();
        },
      })),
    [navigate, onClose],
  );

  const filtered = useMemo(() => {
    const q = query.toLowerCase().trim();
    if (!q) return commands;
    return commands.filter(
      (cmd) =>
        cmd.label.toLowerCase().includes(q) ||
        cmd.keywords?.some((kw) => kw.includes(q)) ||
        cmd.description?.toLowerCase().includes(q),
    );
  }, [query, commands]);

  // Reset search when opened
  useEffect(() => {
    if (open) {
      setQuery('');
      setSelectedIndex(0);
      setTimeout(() => inputRef.current?.focus(), 50);
    }
  }, [open]);

  // Scroll selected item into view
  useEffect(() => {
    if (!listRef.current) return;
    const el = listRef.current.children[selectedIndex] as HTMLElement | undefined;
    el?.scrollIntoView({ block: 'nearest' });
  }, [selectedIndex]);

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      switch (e.key) {
        case 'ArrowDown':
          e.preventDefault();
          setSelectedIndex((i) => Math.min(i + 1, filtered.length - 1));
          break;
        case 'ArrowUp':
          e.preventDefault();
          setSelectedIndex((i) => Math.max(i - 1, 0));
          break;
        case 'Enter':
          e.preventDefault();
          if (filtered[selectedIndex]) {
            filtered[selectedIndex].action();
          }
          break;
        case 'Escape':
          e.preventDefault();
          onClose();
          break;
      }
    },
    [filtered, selectedIndex, onClose],
  );

  if (!open) return null;

  return (
    <>
      {/* Backdrop */}
      <div
        className="fixed inset-0 z-40 bg-black/50"
        onClick={onClose}
        aria-hidden="true"
      />
      {/* Dialog */}
      {/* Centred with margins, not a translate: animate-rise sets its own
          transform and would drop a -translate-x-1/2 on the same element. */}
      <div className="fixed inset-x-4 top-[15vh] z-50 mx-auto max-w-lg animate-rise">
        <div className="overflow-hidden rounded-lg border border-border bg-bg1 shadow-2xl shadow-black/60">
          {/* Search input */}
          <div className="flex items-center gap-3 border-b border-border px-4 py-3">
            <Search size={16} className="text-muted flex-none" />
            <input
              ref={inputRef}
              type="text"
              value={query}
              onChange={(e) => {
                setQuery(e.target.value);
                setSelectedIndex(0);
              }}
              onKeyDown={handleKeyDown}
              placeholder="Search pages, commands…"
              className="flex-1 bg-transparent text-sm text-text placeholder:text-muted outline-none"
            />
            <kbd className="flex-none rounded border border-border bg-surface0 px-1.5 py-0.5 text-[11px] font-medium text-muted">
              Esc
            </kbd>
          </div>

          {/* Results */}
          <div ref={listRef} className="max-h-72 overflow-y-auto py-1.5" role="listbox">
            {filtered.length === 0 ? (
              <div className="px-4 py-6 text-center text-sm text-muted">
                No matching pages
              </div>
            ) : (
              filtered.map((cmd, i) => (
                <button
                  key={cmd.id}
                  onClick={cmd.action}
                  role="option"
                  aria-selected={i === selectedIndex}
                  className={`flex w-full items-center gap-3 px-4 py-2.5 text-left text-sm transition-colors ${
                    i === selectedIndex
                      ? 'bg-accent/10 text-accent'
                      : 'text-text hover:bg-surface0'
                  }`}
                >
                  <cmd.icon
                    size={16}
                    className={
                      i === selectedIndex ? 'text-accent' : 'text-muted'
                    }
                  />
                  <div className="min-w-0 flex-1">
                    <div className="truncate font-medium">{cmd.label}</div>
                    {cmd.description && (
                      <div className="truncate text-xs text-muted">
                        {cmd.description}
                      </div>
                    )}
                  </div>
                  <ArrowRight
                    size={14}
                    className={
                      i === selectedIndex ? 'text-accent' : 'text-muted/0'
                    }
                  />
                </button>
              ))
            )}
          </div>

          {/* Footer hint */}
          <div className="border-t border-border px-4 py-2 text-[11px] text-muted flex items-center gap-3">
            <span>
              <kbd className="rounded border border-border bg-surface0 px-1 font-medium">↑↓</kbd> Navigate
            </span>
            <span>
              <kbd className="rounded border border-border bg-surface0 px-1 font-medium">↵</kbd> Open
            </span>
          </div>
        </div>
      </div>
    </>
  );
}
