import { cn } from '@/lib/utils';
import { LPage } from '@/types/admin';
import { Link } from '@inertiajs/react';
import { Check, Minus } from 'lucide-react';
import { ReactNode, useEffect, useRef } from 'react';

export type Col<T> = { key: string; header: ReactNode; cell: (row: T) => ReactNode; className?: string };

function Box({ checked, indeterminate, onChange, label }: { checked: boolean; indeterminate?: boolean; onChange: () => void; label: string }) {
    return (
        <label className="relative inline-flex cursor-pointer items-center">
            <input type="checkbox" aria-label={label} checked={checked} onChange={onChange} className="peer sr-only" />
            <span className={cn('flex size-4 items-center justify-center rounded border border-input bg-card transition peer-focus-visible:ring-2 peer-focus-visible:ring-ring/60', (checked || indeterminate) && 'border-primary bg-primary text-primary-foreground')}>
                {indeterminate ? <Minus className="size-3" strokeWidth={3} /> : checked ? <Check className="size-3" strokeWidth={3} /> : null}
            </span>
        </label>
    );
}

export default function DataTable<T extends { id: number }>({ rows, columns, selected, onSelect, empty, rowClass }: { rows: T[]; columns: Col<T>[]; selected?: number[]; onSelect?: (ids: number[]) => void; empty: ReactNode; rowClass?: (r: T) => string | undefined }) {
    const selectable = !!onSelect;
    const ids = rows.map((r) => r.id);
    const sel = selected ?? [];
    const all = ids.length > 0 && ids.every((i) => sel.includes(i));
    const some = ids.some((i) => sel.includes(i));

    // selection never outlives the rows it refers to (page / filter change)
    const prev = useRef(ids.join());
    useEffect(() => {
        if (prev.current !== ids.join()) { prev.current = ids.join(); if (sel.length) onSelect?.([]); }
    }, [ids.join()]);

    if (!rows.length) return <div className="rounded-2xl border border-dashed border-border">{empty}</div>;

    return (
        <div className="overflow-x-auto rounded-2xl border border-border bg-card/60 shadow-soft">
            <table className="w-full min-w-[680px] text-sm">
                <thead>
                    <tr className="border-b border-border text-left">
                        {selectable && <th className="w-10 py-2.5 pl-4"><Box label="Select all" checked={all} indeterminate={!all && some} onChange={() => onSelect!(all ? [] : ids)} /></th>}
                        {columns.map((c) => <th key={c.key} className={cn('px-4 py-2.5 text-overline font-medium', c.className)}>{c.header}</th>)}
                    </tr>
                </thead>
                <tbody className="divide-y divide-border">
                    {rows.map((r) => {
                        const on = sel.includes(r.id);
                        return (
                            <tr key={r.id} className={cn('transition-colors hover:bg-accent/30', on && 'bg-primary/5', rowClass?.(r))}>
                                {selectable && <td className="py-3 pl-4"><Box label={`Select row ${r.id}`} checked={on} onChange={() => onSelect!(on ? sel.filter((i) => i !== r.id) : [...sel, r.id])} /></td>}
                                {columns.map((c) => <td key={c.key} className={cn('px-4 py-3 align-middle', c.className)}>{c.cell(r)}</td>)}
                            </tr>
                        );
                    })}
                </tbody>
            </table>
        </div>
    );
}

export function Pager({ page }: { page: LPage<unknown> }) {
    if (page.total === 0) return null;
    const link = (url: string | null, label: string) =>
        url ? <Link href={url} preserveScroll preserveState className="rounded-md border border-border px-3 py-1.5 transition hover:bg-accent">{label}</Link> : <span className="rounded-md border border-border px-3 py-1.5 text-muted-foreground/40">{label}</span>;
    return (
        <div className="mt-4 flex items-center justify-between text-sm text-muted-foreground">
            <span>{page.from}–{page.to} of {page.total.toLocaleString()}</span>
            <div className="flex items-center gap-2">{link(page.prev_page_url, 'Previous')}<span className="tabular-nums">{page.current_page} / {page.last_page}</span>{link(page.next_page_url, 'Next')}</div>
        </div>
    );
}
