import { useDebounce } from '@/hooks/useDebounce';
import { useTheme } from '@/hooks/useTheme';
import { PageProps } from '@/types';
import { Dialog, DialogPanel } from '@headlessui/react';
import { router, usePage } from '@inertiajs/react';
import { Command } from 'cmdk';
import { CalendarClock, CornerDownLeft, Flame, Gamepad2, GitCompare, Home, Library, LogOut, Monitor, Moon, Newspaper, Search, Shield, Sun, User } from 'lucide-react';
import { useEffect, useState } from 'react';

type Hit = { title: string; slug: string; year: number | null; cover: string | null; genres: string[]; rating: number };

export default function SearchCommand({ open, onOpenChange }: { open: boolean; onOpenChange: (o: boolean) => void }) {
    const { auth } = usePage<PageProps>().props;
    const { setTheme } = useTheme();
    const [q, setQ] = useState('');
    const [hits, setHits] = useState<Hit[]>([]);
    const [loading, setLoading] = useState(false);
    const dq = useDebounce(q.trim(), 200);

    useEffect(() => {
        const onKey = (e: KeyboardEvent) => {
            if ((e.key === 'k' && (e.metaKey || e.ctrlKey)) || (e.key === '/' && !/input|textarea|select/i.test((e.target as HTMLElement)?.tagName ?? ''))) {
                e.preventDefault();
                onOpenChange(true);
            }
        };
        window.addEventListener('keydown', onKey);
        return () => window.removeEventListener('keydown', onKey);
    }, [onOpenChange]);

    useEffect(() => {
        if (dq.length < 2) { setHits([]); setLoading(false); return; }
        const ctrl = new AbortController();
        setLoading(true);
        fetch(route('search', { q: dq }), { signal: ctrl.signal, headers: { Accept: 'application/json' } })
            .then((r) => (r.ok ? r.json() : { data: [] }))
            .then((j) => { setHits(j.data); setLoading(false); })
            .catch((e) => e.name !== 'AbortError' && setLoading(false));
        return () => ctrl.abort();
    }, [dq]);

    const go = (url: string) => { onOpenChange(false); setQ(''); router.visit(url); };
    const run = (fn: () => void) => { onOpenChange(false); setQ(''); fn(); };

    type Cmd = { id: string; label: string; icon: typeof Home; group: 'Navigate' | 'Preferences'; keywords?: string; run: () => void };
    const commands: Cmd[] = [
        { id: 'home', label: 'Home', icon: Home, group: 'Navigate', run: () => go(route('home')) },
        { id: 'browse', label: 'Browse all games', icon: Gamepad2, group: 'Navigate', keywords: 'catalog games', run: () => go(route('catalog')) },
        { id: 'trending', label: 'Trending games', icon: Flame, group: 'Navigate', keywords: 'popular hot', run: () => go(route('catalog', { sort: 'popular' })) },
        { id: 'upcoming', label: 'Upcoming releases', icon: CalendarClock, group: 'Navigate', keywords: 'new soon', run: () => go(`${route('home')}#upcoming`) },
        { id: 'compare', label: 'Compare games', icon: GitCompare, group: 'Navigate', run: () => go(route('compare')) },
        ...(auth.user ? [
            { id: 'library', label: 'My library', icon: Library, group: 'Navigate' as const, keywords: 'wishlist played playing', run: () => go(route('library')) },
            { id: 'feed', label: 'Activity feed', icon: Newspaper, group: 'Navigate' as const, keywords: 'friends following', run: () => go(route('feed')) },
            { id: 'profile', label: 'Profile & settings', icon: User, group: 'Navigate' as const, keywords: 'account avatar', run: () => go(route('profile.edit')) },
            ...(auth.user.is_admin ? [{ id: 'admin', label: 'Admin panel', icon: Shield, group: 'Navigate' as const, run: () => go(route('admin.dashboard')) }] : []),
        ] : [
            { id: 'login', label: 'Log in', icon: User, group: 'Navigate' as const, run: () => go(route('login')) },
        ]),
        { id: 'theme-system', label: 'Theme: match system', icon: Monitor, group: 'Preferences', keywords: 'appearance auto', run: () => run(() => setTheme('system')) },
        { id: 'theme-light', label: 'Theme: light', icon: Sun, group: 'Preferences', keywords: 'appearance', run: () => run(() => setTheme('light')) },
        { id: 'theme-dark', label: 'Theme: dark', icon: Moon, group: 'Preferences', keywords: 'appearance', run: () => run(() => setTheme('dark')) },
        ...(auth.user ? [{ id: 'logout', label: 'Log out', icon: LogOut, group: 'Preferences' as const, run: () => run(() => router.post(route('logout'))) }] : []),
    ];
    const needle = q.trim().toLowerCase();
    const visible = needle ? commands.filter((c) => `${c.label} ${c.keywords ?? ''}`.toLowerCase().includes(needle)) : commands;
    const groups = (['Navigate', 'Preferences'] as const).map((g) => [g, visible.filter((c) => c.group === g)] as const).filter(([, l]) => l.length);
    const item = 'flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2 text-sm aria-selected:bg-accent';

    return (
        <Dialog open={open} onClose={() => onOpenChange(false)} className="relative z-[70]">
            <div className="fixed inset-0 bg-black/60 backdrop-blur-sm" aria-hidden />
            <div className="fixed inset-0 flex items-start justify-center p-4 pt-[12vh]">
                <DialogPanel className="glass w-full max-w-xl overflow-hidden rounded-2xl border border-border shadow-lift">
                    <Command shouldFilter={false} label="Search games" loop>
                        <div className="flex items-center gap-3 border-b border-border px-4">
                            <Search className="size-4 text-muted-foreground" />
                            <Command.Input value={q} onValueChange={setQ} placeholder="Search games…" className="h-14 flex-1 bg-transparent text-[15px] outline-none placeholder:text-muted-foreground/70" />
                            <kbd className="rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground">ESC</kbd>
                        </div>
                        <Command.List className="max-h-[50vh] overflow-y-auto p-2">
                            {dq.length >= 2 && !loading && hits.length === 0 && groups.length === 0 && <Command.Empty className="px-3 py-10 text-center text-sm text-muted-foreground">No games found for “{dq}”.</Command.Empty>}
                            {loading && <div className="px-3 py-6 text-center text-sm text-muted-foreground">Searching…</div>}
                            {hits.length > 0 && (
                                <Command.Group heading="Games" className="[&_[cmdk-group-heading]]:text-overline [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-2">
                                    {hits.map((h) => (
                                        <Command.Item key={h.slug} value={h.slug} onSelect={() => go(route('games.show', h.slug))} className={item}>
                                            <div className="size-10 shrink-0 overflow-hidden rounded-md bg-muted">{h.cover && <img src={h.cover} alt="" className="size-full object-cover" />}</div>
                                            <div className="min-w-0 flex-1">
                                                <p className="truncate font-medium">{h.title}</p>
                                                <p className="text-caption truncate">{[h.genres.join(' · '), h.year].filter(Boolean).join(' · ')}</p>
                                            </div>
                                            <CornerDownLeft className="size-3.5 text-muted-foreground" />
                                        </Command.Item>
                                    ))}
                                </Command.Group>
                            )}
                            {dq.length >= 2 && (
                                <Command.Group>
                                    <Command.Item value="__all" onSelect={() => go(route('catalog', { q: dq }))} className={item}>
                                        <Search className="size-4 text-muted-foreground" /> See all results for “{dq}”
                                    </Command.Item>
                                </Command.Group>
                            )}
                            {groups.map(([g, list]) => (
                                <Command.Group key={g} heading={g} className="[&_[cmdk-group-heading]]:text-overline [&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-2">
                                    {list.map((c) => (
                                        <Command.Item key={c.id} value={c.id} onSelect={c.run} className={item}><c.icon className="size-4 text-muted-foreground" />{c.label}</Command.Item>
                                    ))}
                                </Command.Group>
                            ))}
                        </Command.List>
                    </Command>
                </DialogPanel>
            </div>
        </Dialog>
    );
}
