import { router } from "@inertiajs/react";
import { ReactNode, useMemo, useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from "@/components/ui/select";

export interface DataTableColumn<T> {
    key: keyof T | string;
    label: string;
    sortable?: boolean;
    render?: (row: T) => ReactNode;
    className?: string;
}

export interface DataTableProps<T extends { id: number | string }> {
    rows: T[];
    columns: DataTableColumn<T>[];
    page: number;
    lastPage: number;
    total: number;
    from?: number | null;
    to?: number | null;
    query?: Record<string, string | number | null | undefined>;
    resource?: string;
    exportable?: boolean;
    selectable?: boolean;
    onBulkAction?: (ids: Array<number | string>, action: string) => void;
}

export function DataTable<T extends { id: number | string }>({
    rows,
    columns,
    page,
    lastPage,
    total,
    from,
    to,
    query = {},
    resource,
    exportable = false,
    selectable = false,
    onBulkAction,
}: DataTableProps<T>) {
    const [selected, setSelected] = useState<Array<number | string>>([]);
    const [search, setSearch] = useState(String(query.q ?? ""));
    const [sort, setSort] = useState(String(query.sort ?? ""));
    const [direction, setDirection] = useState(
        String(query.direction ?? "desc"),
    );
    const [action, setAction] = useState("");

    const allSelected =
        rows.length > 0 && rows.every((row) => selected.includes(row.id));
    const visiblePages = useMemo(() => {
        const start = Math.max(1, page - 2);
        const end = Math.min(lastPage, page + 2);
        return Array.from({ length: end - start + 1 }, (_, i) => start + i);
    }, [page, lastPage]);

    const visit = (next: Record<string, string | number>) =>
        router.get(
            window.location.pathname,
            { ...query, ...next },
            { preserveState: true, replace: true },
        );

    const toggleSort = (key: string) => {
        const nextDirection =
            sort === key && direction === "asc" ? "desc" : "asc";
        setSort(key);
        setDirection(nextDirection);
        visit({ sort: key, direction: nextDirection, page: 1 });
    };

    const submitSearch = (event: React.FormEvent) => {
        event.preventDefault();
        visit({ q: search, page: 1 });
    };

    const toggleAll = () =>
        setSelected(allSelected ? [] : rows.map((row) => row.id));
    const toggleRow = (id: number | string) =>
        setSelected((current) =>
            current.includes(id)
                ? current.filter((item) => item !== id)
                : [...current, id],
        );

    const runBulk = () => {
        if (action && selected.length && onBulkAction)
            onBulkAction(selected, action);
    };

    const exportUrl = resource
        ? `/crm/export/${resource}?${new URLSearchParams(
              Object.entries(query)
                  .filter(([, value]) => value !== undefined && value !== null)
                  .map(([key, value]) => [key, String(value)]),
          ).toString()}`
        : "#";

    return (
        <div className="space-y-3">
            <div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
                <form onSubmit={submitSearch} className="flex gap-2">
                    <Input
                        value={search}
                        onChange={(e) => setSearch(e.target.value)}
                        placeholder="Cari..."
                        className="w-64"
                    />
                    <Button type="submit">Cari</Button>
                </form>
                <div className="flex gap-2">
                    {selectable && onBulkAction && (
                        <>
                            <Select value={action} onValueChange={setAction}>
                                <SelectTrigger className="w-40">
                                    <SelectValue placeholder="Aksi massal" />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="activate">
                                        Aktifkan
                                    </SelectItem>
                                    <SelectItem value="deactivate">
                                        Nonaktifkan
                                    </SelectItem>
                                    <SelectItem value="delete">
                                        Hapus
                                    </SelectItem>
                                </SelectContent>
                            </Select>
                            <Button
                                variant="outline"
                                disabled={!selected.length || !action}
                                onClick={runBulk}
                            >
                                Terapkan ({selected.length})
                            </Button>
                        </>
                    )}
                    {exportable && resource && (
                        <Button variant="outline" asChild>
                            <a href={exportUrl}>Export CSV</a>
                        </Button>
                    )}
                </div>
            </div>

            <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-[0_1px_2px_rgba(15,23,42,.03),0_8px_30px_rgba(15,23,42,.04)]">
                <div className="overflow-x-auto">
                    <table className="w-full text-sm">
                        <thead className="bg-muted/50">
                            <tr>
                                {selectable && (
                                    <th className="w-10 p-3">
                                        <Checkbox
                                            checked={allSelected}
                                            onCheckedChange={toggleAll}
                                        />
                                    </th>
                                )}
                                {columns.map((column) => (
                                    <th
                                        key={String(column.key)}
                                        className={`p-3 text-left font-medium ${column.className ?? ""}`}
                                    >
                                        {column.sortable ? (
                                            <Button
                                                type="button"
                                                variant="ghost"
                                                size="sm"
                                                className="-ml-2 h-7 px-2 font-semibold"
                                                onClick={() =>
                                                    toggleSort(
                                                        String(column.key),
                                                    )
                                                }
                                            >
                                                {column.label}
                                                {sort === String(column.key)
                                                    ? ` ${direction === "asc" ? "↑" : "↓"}`
                                                    : ""}
                                            </Button>
                                        ) : (
                                            column.label
                                        )}
                                    </th>
                                ))}
                            </tr>
                        </thead>
                        <tbody>
                            {rows.map((row) => (
                                <tr key={row.id} className="border-t">
                                    {selectable && (
                                        <td className="p-3">
                                            <Checkbox
                                                checked={selected.includes(
                                                    row.id,
                                                )}
                                                onCheckedChange={() =>
                                                    toggleRow(row.id)
                                                }
                                            />
                                        </td>
                                    )}
                                    {columns.map((column) => (
                                        <td
                                            key={String(column.key)}
                                            className={`p-3 ${column.className ?? ""}`}
                                        >
                                            {column.render
                                                ? column.render(row)
                                                : String(
                                                      (
                                                          row as Record<
                                                              string,
                                                              unknown
                                                          >
                                                      )[String(column.key)] ??
                                                          "-",
                                                  )}
                                        </td>
                                    ))}
                                </tr>
                            ))}
                            {rows.length === 0 && (
                                <tr>
                                    <td
                                        colSpan={
                                            columns.length +
                                            (selectable ? 1 : 0)
                                        }
                                        className="p-10 text-center text-muted-foreground"
                                    >
                                        Tidak ada data.
                                    </td>
                                </tr>
                            )}
                        </tbody>
                    </table>
                </div>
            </div>

            <div className="flex flex-col gap-3 text-sm text-muted-foreground md:flex-row md:items-center md:justify-between">
                <div>
                    Menampilkan {from ?? 0}–{to ?? 0} dari {total} data
                </div>
                <div className="flex items-center gap-1">
                    <Button
                        variant="outline"
                        size="sm"
                        disabled={page <= 1}
                        onClick={() => visit({ page: page - 1 })}
                    >
                        Sebelumnya
                    </Button>
                    {visiblePages.map((item) => (
                        <Button
                            key={item}
                            variant={item === page ? "default" : "outline"}
                            size="sm"
                            onClick={() => visit({ page: item })}
                        >
                            {item}
                        </Button>
                    ))}
                    <Button
                        variant="outline"
                        size="sm"
                        disabled={page >= lastPage}
                        onClick={() => visit({ page: page + 1 })}
                    >
                        Berikutnya
                    </Button>
                </div>
            </div>
        </div>
    );
}
