import ConfirmDialog from '@/Components/admin/ConfirmDialog';
import DataTable, { Col, Pager } from '@/Components/admin/DataTable';
import { SearchInput } from '@/Components/admin/fields';
import { PageHeader } from '@/Components/admin/primitives';
import { useAdminList } from '@/Components/admin/useAdminList';
import Modal from '@/Components/Modal';
import EmptyState from '@/Components/shared/EmptyState';
import { Button } from '@/Components/ui/button';
import { Field, Input, Textarea } from '@/Components/ui/field';
import AdminLayout from '@/Layouts/AdminLayout';
import { LPage } from '@/types/admin';
import { Head, router, useForm } from '@inertiajs/react';
import { Layers, Pencil, Plus, Trash2 } from 'lucide-react';
import { FormEventHandler, useState } from 'react';

type Item = { id: number; name: string; slug: string; counts: Record<string, number>; [k: string]: unknown };
type FieldDef = [string, string, 'text' | 'textarea' | 'number'];
type Props = { term: string; label: string; singular: string; fields: FieldDef[]; items: LPage<Item>; q: string };

function TermForm({ term, singular, fields, item, onClose }: { term: string; singular: string; fields: FieldDef[]; item: Item | null; onClose: () => void }) {
    const init: Record<string, string> = { slug: item?.slug ?? '' };
    fields.forEach(([k]) => (init[k] = item?.[k] === null || item?.[k] === undefined ? '' : String(item[k])));
    const { data, setData, post, put, processing, errors } = useForm(init);
    const err = errors as Record<string, string>;

    const submit: FormEventHandler = (e) => {
        e.preventDefault();
        const opts = { preserveScroll: true, onSuccess: onClose };
        item ? put(route('admin.terms.update', [term, item.id]), opts) : post(route('admin.terms.store', term), opts);
    };

    return (
        <form onSubmit={submit} className="space-y-4 p-6" noValidate>
            <h2 className="text-h3">{item ? `Edit ${singular}` : `New ${singular}`}</h2>
            {fields.map(([k, label, type], i) => (
                <Field key={k} label={label} htmlFor={`f-${k}`} error={err[k]}>
                    {type === 'textarea'
                        ? <Textarea id={`f-${k}`} rows={3} value={data[k]} onChange={(e) => setData(k, e.target.value)} />
                        : <Input id={`f-${k}`} type={type} autoFocus={i === 0} value={data[k]} onChange={(e) => setData(k, e.target.value)} aria-invalid={!!err[k]} />}
                </Field>
            ))}
            <Field label="Slug" htmlFor="f-slug" error={err.slug} hint="Leave blank to generate from the name."><Input id="f-slug" value={data.slug} onChange={(e) => setData('slug', e.target.value)} placeholder="auto-generated" /></Field>
            <div className="flex justify-end gap-2 pt-2">
                <Button type="button" variant="secondary" onClick={onClose}>Cancel</Button>
                <Button type="submit" loading={processing}>{item ? 'Save' : 'Create'}</Button>
            </div>
        </form>
    );
}

export default function Index({ term, label, singular, fields, items, q: initialQ }: Props) {
    const { q, setQ } = useAdminList('admin.terms.index', { q: initialQ || undefined }, { term });
    const [editing, setEditing] = useState<Item | null | 'new'>(null);
    const [deleting, setDeleting] = useState<Item | null>(null);

    const extra = fields.filter(([k]) => k !== 'name' && k !== 'description');
    const columns: Col<Item>[] = [
        { key: 'name', header: 'Name', cell: (i) => <div><p className="font-medium">{i.name}</p><p className="text-caption">/{i.slug}</p></div> },
        ...extra.map(([k, l]): Col<Item> => ({ key: k, header: l, className: 'text-muted-foreground', cell: (i) => String(i[k] ?? '—') })),
        { key: 'counts', header: 'Used by', className: 'whitespace-nowrap text-muted-foreground tabular-nums', cell: (i) => Object.entries(i.counts).map(([k, n]) => `${n} ${k === 'games' ? (n === 1 ? 'game' : 'games') : k}`).join(' · ') },
        { key: 'act', header: '', className: 'w-24 text-right', cell: (i) => (
            <div className="flex justify-end gap-0.5">
                <button onClick={() => setEditing(i)} aria-label={`Edit ${i.name}`} className="rounded-lg p-2 text-muted-foreground hover:bg-accent hover:text-foreground"><Pencil className="size-4" /></button>
                <button onClick={() => setDeleting(i)} aria-label={`Delete ${i.name}`} className="rounded-lg p-2 text-muted-foreground hover:bg-accent hover:text-destructive"><Trash2 className="size-4" /></button>
            </div>
        ) },
    ];

    return (
        <AdminLayout>
            <Head title={`${label} · Admin`} />
            <PageHeader title={label} description={`${items.total} total`} actions={<Button onClick={() => setEditing('new')}><Plus />New {singular}</Button>} />
            <div className="mb-4"><SearchInput value={q} onChange={setQ} placeholder={`Search ${label.toLowerCase()}…`} /></div>
            <DataTable rows={items.data} columns={columns} empty={<EmptyState icon={Layers} title={`No ${label.toLowerCase()} yet`} action={<Button onClick={() => setEditing('new')}><Plus />New {singular}</Button>} />} />
            <Pager page={items} />

            <Modal show={editing !== null} onClose={() => setEditing(null)} maxWidth="md">
                {editing !== null && <TermForm key={editing === 'new' ? 'new' : editing.id} term={term} singular={singular} fields={fields} item={editing === 'new' ? null : editing} onClose={() => setEditing(null)} />}
            </Modal>
            <ConfirmDialog open={!!deleting} danger title={`Delete “${deleting?.name}”?`} description={term === 'companies' ? 'Games using it will have the developer or publisher cleared.' : 'It will be removed from every game that uses it.'} confirmLabel="Delete" onClose={() => setDeleting(null)} onConfirm={() => router.delete(route('admin.terms.destroy', [term, deleting!.id]), { preserveScroll: true, onSuccess: () => setDeleting(null) })} />
        </AdminLayout>
    );
}
