import { SearchInput } from '@/Components/admin/fields';
import EmptyState from '@/Components/shared/EmptyState';
import Seo from '@/Components/shared/Seo';
import { Button } from '@/Components/ui/button';
import { useDebounce } from '@/hooks/useDebounce';
import PublicLayout from '@/Layouts/PublicLayout';
import { cn } from '@/lib/utils';
import { CompareGame } from '@/types/models';
import { Link, router } from '@inertiajs/react';
import { GitCompare, Plus, X } from 'lucide-react';
import { ReactNode, useEffect, useState } from 'react';

type Hit = { title: string; slug: string; year: number | null; cover: string | null };
type Row = { label: string; value: (g: CompareGame) => ReactNode; best?: (g: CompareGame) => number | null; higher?: boolean };

const fmtDate = (d: string | null) => (d ? new Date(`${d}T00:00:00Z`).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric', timeZone: 'UTC' }) : 'TBA');
const dash = <span className="text-muted-foreground">—</span>;

const ROWS: Row[] = [
    { label: 'Community rating', value: (g) => (g.rating_count ? <><b className="text-base">{g.rating_avg.toFixed(1)}</b><span className="text-caption"> · {g.rating_count} ratings</span></> : dash), best: (g) => (g.rating_count ? g.rating_avg : null) },
    { label: 'Metacritic', value: (g) => g.metacritic ?? dash, best: (g) => g.metacritic },
    { label: 'Wishlists', value: (g) => g.wishlist_count.toLocaleString(), best: (g) => g.wishlist_count },
    { label: 'Release date', value: (g) => fmtDate(g.release_date) },
    { label: 'Main story', value: (g) => (g.playtime_main ? `${g.playtime_main}h` : dash) },
    { label: 'Completionist', value: (g) => (g.playtime_complete ? `${g.playtime_complete}h` : dash) },
    { label: 'Genres', value: (g) => g.genres.join(', ') || dash },
    { label: 'Platforms', value: (g) => g.platforms.join(', ') || dash },
    { label: 'Developer', value: (g) => g.developer ?? dash },
    { label: 'Publisher', value: (g) => g.publisher ?? dash },
    { label: 'Age rating', value: (g) => g.age_rating ?? dash },
    { label: 'Min. memory', value: (g) => g.requirements?.memory ?? dash },
    { label: 'Min. graphics', value: (g) => g.requirements?.graphics ?? dash },
    { label: 'Min. storage', value: (g) => g.requirements?.storage ?? dash },
];

function Picker({ selected, disabled, onPick }: { selected: string[]; disabled: boolean; onPick: (slug: string) => void }) {
    const [q, setQ] = useState('');
    const dq = useDebounce(q.trim(), 200);
    const [hits, setHits] = useState<Hit[]>([]);

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

    return (
        <div className="relative max-w-md">
            <SearchInput value={q} onChange={setQ} placeholder={disabled ? 'Remove a game to add another' : 'Add a game to compare…'} />
            {dq.length >= 2 && !disabled && (
                <ul className="glass absolute z-30 mt-2 w-full overflow-hidden rounded-xl border border-border p-1 shadow-lift" role="listbox">
                    {hits.filter((h) => !selected.includes(h.slug)).map((h) => (
                        <li key={h.slug}>
                            <button onClick={() => { onPick(h.slug); setQ(''); setHits([]); }} className="flex w-full items-center gap-3 rounded-lg px-2.5 py-2 text-left text-sm hover:bg-accent">
                                <span className="size-9 shrink-0 overflow-hidden rounded bg-muted">{h.cover && <img src={h.cover} alt="" className="size-full object-cover" />}</span>
                                <span className="min-w-0 flex-1 truncate">{h.title}</span><span className="text-caption">{h.year}</span><Plus className="size-4 text-muted-foreground" />
                            </button>
                        </li>
                    ))}
                    {hits.length === 0 && <li className="px-3 py-4 text-center text-sm text-muted-foreground">No results.</li>}
                </ul>
            )}
        </div>
    );
}

export default function Compare({ games, max }: { games: CompareGame[]; max: number }) {
    const slugs = games.map((g) => g.slug);
    const go = (next: string[]) => router.get(route('compare'), next.length ? { games: next } : {}, { preserveState: true, preserveScroll: true, replace: true });

    return (
        <PublicLayout>
            <Seo title="Compare games" description="Compare games side by side: ratings, playtime, platforms and requirements." />
            <div className="space-y-6">
                <header className="flex flex-wrap items-end justify-between gap-3">
                    <div><h1 className="text-h1">Compare games</h1><p className="mt-1 text-sm text-muted-foreground">Up to {max} games, side by side. Best values are highlighted.</p></div>
                    {games.length > 0 && <Button variant="ghost" onClick={() => go([])}>Clear all</Button>}
                </header>

                <Picker selected={slugs} disabled={games.length >= max} onPick={(s) => go([...slugs, s])} />

                {games.length === 0 ? (
                    <EmptyState icon={GitCompare} title="Pick games to compare" description="Search above to add your first game. Share the URL to share the comparison." />
                ) : (
                    <div className="overflow-x-auto rounded-2xl border border-border bg-card/60 shadow-soft">
                        <table className="w-full min-w-[640px] border-collapse text-sm">
                            <thead>
                                <tr>
                                    <th className="sticky left-0 z-10 w-36 bg-card p-3 text-left align-bottom" />
                                    {games.map((g) => (
                                        <th key={g.slug} className="min-w-44 border-l border-border p-3 text-left align-top font-normal">
                                            <div className="relative">
                                                <button onClick={() => go(slugs.filter((s) => s !== g.slug))} aria-label={`Remove ${g.title}`} className="absolute -right-1 -top-1 z-10 rounded-full border border-border bg-card p-1 text-muted-foreground hover:text-foreground"><X className="size-3" /></button>
                                                <Link href={route('games.show', g.slug)} className="block">
                                                    <div className="aspect-[3/4] w-24 overflow-hidden rounded-lg border border-border bg-muted">{g.cover && <img src={g.cover} alt="" className="size-full object-cover" />}</div>
                                                    <p className="mt-2 font-medium leading-snug hover:underline">{g.title}</p>
                                                </Link>
                                            </div>
                                        </th>
                                    ))}
                                </tr>
                            </thead>
                            <tbody>
                                {ROWS.map((row) => {
                                    const vals = row.best ? games.map(row.best) : [];
                                    const top = vals.length > 1 ? Math.max(...vals.filter((v): v is number => v !== null), -Infinity) : -Infinity;
                                    return (
                                        <tr key={row.label} className="border-t border-border">
                                            <th scope="row" className="sticky left-0 z-10 bg-card p-3 text-left text-caption font-normal">{row.label}</th>
                                            {games.map((g, i) => (
                                                <td key={g.slug} className={cn('border-l border-border p-3 align-top', vals[i] !== undefined && vals[i] === top && 'bg-primary/10')}>{row.value(g)}</td>
                                            ))}
                                        </tr>
                                    );
                                })}
                            </tbody>
                        </table>
                    </div>
                )}
            </div>
        </PublicLayout>
    );
}
