import { Head, Link, router } from '@inertiajs/react';
import {
    createColumnHelper,
    type ColumnDef,
    type PaginationState,
    type SortingState,
} from '@tanstack/react-table';
import { Eye, Plus } from 'lucide-react';
import { useEffect, useMemo, useRef, useState } from 'react';
import {
    DataTable,
    DataTableColumnHeader,
} from '@/components/data-table';
import Heading from '@/components/heading';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { formatDate } from '@/lib/utils';
import { dashboard } from '@/routes';
import {
    create as createInventory,
    index as inventoriesIndex,
    show as inventoryShow,
} from '@/routes/admin/inventories';
import type { Paginated } from '@/types';

type WarehouseOption = { id: number; code: string; name: string };

type StatusOption = { value: string; label: string };

type InventoryRow = {
    id: number;
    code: string;
    status: string;
    status_label: string;
    counted_at: string | null;
    warehouse: WarehouseOption;
    creator: { id: number; name: string } | null;
    lines_count: number;
    variance_count: number;
};

type Filters = {
    search: string;
    sort: string;
    direction: 'asc' | 'desc';
    per_page: number;
    warehouse_id: number | null;
    status: string | null;
};

const columnHelper = createColumnHelper<InventoryRow>();

function statusVariant(
    status: string,
): 'default' | 'secondary' | 'outline' | 'destructive' {
    switch (status) {
        case 'adjusted':
            return 'default';
        case 'closed':
            return 'secondary';
        case 'draft':
            return 'outline';
        case 'cancelled':
            return 'outline';
        default:
            return 'outline';
    }
}

function visitInventories(params: {
    search: string;
    sort: string;
    direction: 'asc' | 'desc';
    page: number;
    per_page: number;
    warehouse_id: number | null;
    status: string | null;
}) {
    router.get(
        inventoriesIndex.url(),
        {
            search: params.search || undefined,
            sort: params.sort,
            direction: params.direction,
            page: params.page > 1 ? params.page : undefined,
            per_page: params.per_page !== 15 ? params.per_page : undefined,
            warehouse_id: params.warehouse_id ?? undefined,
            status: params.status ?? undefined,
        },
        {
            preserveState: true,
            replace: true,
            preserveScroll: true,
        },
    );
}

export default function InventoriesIndex({
    inventories,
    warehouses,
    statuses,
    filters,
    canCreate = false,
}: {
    inventories: Paginated<InventoryRow>;
    warehouses: WarehouseOption[];
    statuses: StatusOption[];
    filters: Filters;
    canCreate?: boolean;
}) {
    const isFirstSearchEffect = useRef(true);
    const [isLoading, setIsLoading] = useState(false);
    const [search, setSearch] = useState(filters.search);
    const [warehouseFilter, setWarehouseFilter] = useState<string>(
        filters.warehouse_id ? String(filters.warehouse_id) : 'all',
    );
    const [statusFilter, setStatusFilter] = useState<string>(
        filters.status ?? 'all',
    );
    const [sorting, setSorting] = useState<SortingState>([
        { id: filters.sort, desc: filters.direction === 'desc' },
    ]);
    const [pagination, setPagination] = useState<PaginationState>({
        pageIndex: inventories.current_page - 1,
        pageSize: inventories.per_page,
    });

    useEffect(() => {
        const removeStart = router.on('start', () => setIsLoading(true));
        const removeFinish = router.on('finish', () => setIsLoading(false));

        return () => {
            removeStart();
            removeFinish();
        };
    }, []);

    useEffect(() => {
        setSearch(filters.search);
        setWarehouseFilter(
            filters.warehouse_id ? String(filters.warehouse_id) : 'all',
        );
        setStatusFilter(filters.status ?? 'all');
        setSorting([
            { id: filters.sort, desc: filters.direction === 'desc' },
        ]);
        setPagination({
            pageIndex: inventories.current_page - 1,
            pageSize: inventories.per_page,
        });
    }, [filters, inventories.current_page, inventories.per_page]);

    useEffect(() => {
        if (isFirstSearchEffect.current) {
            isFirstSearchEffect.current = false;
            return;
        }

        const timeout = window.setTimeout(() => {
            visitInventories({
                search,
                sort: sorting[0]?.id ?? filters.sort,
                direction: sorting[0]?.desc ? 'desc' : 'asc',
                page: 1,
                per_page: pagination.pageSize,
                warehouse_id:
                    warehouseFilter === 'all'
                        ? null
                        : Number(warehouseFilter),
                status: statusFilter === 'all' ? null : statusFilter,
            });
        }, 300);

        return () => window.clearTimeout(timeout);
    }, [search]);

    const columns = useMemo<ColumnDef<InventoryRow, unknown>[]>(
        () => [
            columnHelper.accessor('code', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Inventaire" />
                ),
                meta: { label: 'Inventaire' },
                cell: (info) => (
                    <span className="font-mono text-sm font-medium">
                        {info.getValue()}
                    </span>
                ),
            }),
            columnHelper.accessor('counted_at', {
                header: ({ column }) => (
                    <DataTableColumnHeader
                        column={column}
                        title="Date d'inventaire"
                    />
                ),
                meta: { label: "Date d'inventaire" },
                cell: (info) => formatDate(info.getValue()),
            }),
            columnHelper.accessor((row) => row.warehouse.name, {
                id: 'warehouse',
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Entrepôt" />
                ),
                meta: { label: 'Entrepôt' },
                enableSorting: false,
                cell: (info) => (
                    <div className="flex flex-col gap-0.5">
                        <span className="text-sm font-medium">
                            {info.row.original.warehouse.name}
                        </span>
                        <span className="text-muted-foreground font-mono text-xs">
                            {info.row.original.warehouse.code}
                        </span>
                    </div>
                ),
            }),
            columnHelper.accessor('status', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Statut" />
                ),
                meta: { label: 'Statut' },
                cell: (info) => (
                    <Badge variant={statusVariant(info.getValue())}>
                        {info.row.original.status_label}
                    </Badge>
                ),
            }),
            columnHelper.accessor('lines_count', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Lignes" />
                ),
                meta: { label: 'Lignes' },
                enableSorting: false,
                cell: (info) => (
                    <span className="tabular-nums">{info.getValue()}</span>
                ),
            }),
            columnHelper.accessor('variance_count', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Écarts" />
                ),
                meta: { label: 'Écarts' },
                enableSorting: false,
                cell: (info) => {
                    const count = info.getValue<number>();

                    return count > 0 ? (
                        <Badge variant="secondary">{count}</Badge>
                    ) : (
                        <span className="text-muted-foreground tabular-nums">
                            0
                        </span>
                    );
                },
            }),
            columnHelper.accessor((row) => row.creator?.name ?? '', {
                id: 'creator',
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Créé par" />
                ),
                meta: { label: 'Créé par' },
                enableSorting: false,
                cell: (info) => info.row.original.creator?.name ?? '—',
            }),
            columnHelper.display({
                id: 'actions',
                enableSorting: false,
                enableHiding: false,
                header: () => <div className="text-right">Actions</div>,
                cell: ({ row }) => {
                    const inventory = row.original;

                    return (
                        <div className="flex justify-end">
                            <Button variant="outline" size="icon" asChild>
                                <Link
                                    href={inventoryShow.url(inventory.id)}
                                    aria-label={`Voir ${inventory.code}`}
                                >
                                    <Eye />
                                </Link>
                            </Button>
                        </div>
                    );
                },
            }),
        ],
        [],
    );

    return (
        <>
            <Head title="Inventaires physiques" />

            <div className="flex h-full flex-1 flex-col gap-6 p-4 md:p-6">
                <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
                    <Heading
                        title="Inventaire physique"
                        description="Comptages, écarts et ajustements de stock"
                    />
                    {canCreate && (
                        <Button asChild>
                            <Link href={createInventory.url()}>
                                <Plus />
                                Nouvel inventaire
                            </Link>
                        </Button>
                    )}
                </div>

                <div className="flex flex-wrap gap-3">
                    <Select
                        value={warehouseFilter}
                        onValueChange={(value) => {
                            setWarehouseFilter(value);
                            visitInventories({
                                search,
                                sort: sorting[0]?.id ?? filters.sort,
                                direction: sorting[0]?.desc ? 'desc' : 'asc',
                                page: 1,
                                per_page: pagination.pageSize,
                                warehouse_id:
                                    value === 'all' ? null : Number(value),
                                status:
                                    statusFilter === 'all'
                                        ? null
                                        : statusFilter,
                            });
                        }}
                    >
                        <SelectTrigger className="w-[220px]">
                            <SelectValue placeholder="Entrepôt" />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value="all">
                                Tous les entrepôts
                            </SelectItem>
                            {warehouses.map((warehouse) => (
                                <SelectItem
                                    key={warehouse.id}
                                    value={String(warehouse.id)}
                                >
                                    {warehouse.code} — {warehouse.name}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>

                    <Select
                        value={statusFilter}
                        onValueChange={(value) => {
                            setStatusFilter(value);
                            visitInventories({
                                search,
                                sort: sorting[0]?.id ?? filters.sort,
                                direction: sorting[0]?.desc ? 'desc' : 'asc',
                                page: 1,
                                per_page: pagination.pageSize,
                                warehouse_id:
                                    warehouseFilter === 'all'
                                        ? null
                                        : Number(warehouseFilter),
                                status: value === 'all' ? null : value,
                            });
                        }}
                    >
                        <SelectTrigger className="w-[180px]">
                            <SelectValue placeholder="Statut" />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value="all">Tous les statuts</SelectItem>
                            {statuses.map((status) => (
                                <SelectItem
                                    key={status.value}
                                    value={status.value}
                                >
                                    {status.label}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>
                </div>

                <DataTable
                    id="admin-inventories"
                    columns={columns}
                    data={inventories.data}
                    getRowId={(row) => String(row.id)}
                    searchValue={search}
                    onSearchChange={setSearch}
                    searchPlaceholder="Rechercher par code, entrepôt, produit…"
                    isLoading={isLoading}
                    sorting={sorting}
                    onSortingChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(sorting)
                                : updater;
                        setSorting(next);
                        visitInventories({
                            search,
                            sort: next[0]?.id ?? filters.sort,
                            direction: next[0]?.desc ? 'desc' : 'asc',
                            page: 1,
                            per_page: pagination.pageSize,
                            warehouse_id:
                                warehouseFilter === 'all'
                                    ? null
                                    : Number(warehouseFilter),
                            status:
                                statusFilter === 'all' ? null : statusFilter,
                        });
                    }}
                    manualSorting
                    pagination={pagination}
                    onPaginationChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(pagination)
                                : updater;
                        const sizeChanged =
                            next.pageSize !== pagination.pageSize;
                        setPagination(next);
                        visitInventories({
                            search,
                            sort: sorting[0]?.id ?? filters.sort,
                            direction: sorting[0]?.desc ? 'desc' : 'asc',
                            page: sizeChanged ? 1 : next.pageIndex + 1,
                            per_page: next.pageSize,
                            warehouse_id:
                                warehouseFilter === 'all'
                                    ? null
                                    : Number(warehouseFilter),
                            status:
                                statusFilter === 'all' ? null : statusFilter,
                        });
                    }}
                    manualPagination
                    pageCount={inventories.last_page}
                    totalRows={inventories.total}
                    emptyMessage="Aucun inventaire enregistré."
                />
            </div>
        </>
    );
}

InventoriesIndex.layout = {
    breadcrumbs: [
        { title: 'Tableau de bord', href: dashboard() },
        { title: 'Inventaire physique', href: '#' },
    ],
};
