import { Head, Link, router } from '@inertiajs/react';
import { createColumnHelper } from '@tanstack/react-table';
import type { ColumnDef, PaginationState, 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 { Button } from '@/components/ui/button';
import { dashboard } from '@/routes';
import { create, index, show } from '@/routes/admin/budgets';
import type { Paginated } from '@/types';
import { BudgetStatusBadge } from './status-badge';

type BudgetRow = {
    id: number;
    fiscal_year: number;
    label: string;
    status: string;
    department: { id: number; code: string; name: string };
    lines_count: number;
};

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

const columnHelper = createColumnHelper<BudgetRow>();

function visitBudgets(params: {
    search: string;
    sort: string;
    direction: 'asc' | 'desc';
    page: number;
    per_page: number;
}) {
    router.get(
        index.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,
        },
        { preserveState: true, replace: true, preserveScroll: true },
    );
}

export default function BudgetsIndex({
    budgets,
    filters,
    can,
}: {
    budgets: Paginated<BudgetRow>;
    filters: Filters;
    can: { create: boolean };
}) {
    const isFirstSearchEffect = useRef(true);
    const [isLoading, setIsLoading] = useState(false);
    const [search, setSearch] = useState(filters.search);
    const [sorting, setSorting] = useState<SortingState>([
        { id: filters.sort, desc: filters.direction === 'desc' },
    ]);
    const [pagination, setPagination] = useState<PaginationState>({
        pageIndex: budgets.current_page - 1,
        pageSize: budgets.per_page,
    });

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

    useEffect(() => {
        if (isFirstSearchEffect.current) {
            isFirstSearchEffect.current = false;
            return;
        }
        const timeout = window.setTimeout(() => {
            const sort = sorting[0];
            visitBudgets({
                search,
                sort: sort?.id ?? 'fiscal_year',
                direction: sort?.desc === false ? 'asc' : 'desc',
                page: 1,
                per_page: pagination.pageSize,
            });
        }, 300);
        return () => window.clearTimeout(timeout);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [search]);

    const columns = useMemo(
        () =>
            [
                columnHelper.accessor('fiscal_year', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Exercice" />
                    ),
                }),
                columnHelper.accessor('label', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Libellé" />
                    ),
                }),
                columnHelper.accessor('department', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Service" />
                    ),
                    cell: (info) => info.getValue().name,
                }),
                columnHelper.accessor('lines_count', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Lignes" />
                    ),
                }),
                columnHelper.accessor('status', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Statut" />
                    ),
                    cell: (info) => <BudgetStatusBadge status={info.getValue()} />,
                }),
                columnHelper.display({
                    id: 'actions',
                    cell: ({ row }) => (
                        <div className="flex justify-end">
                            <Button variant="ghost" size="icon" asChild>
                                <Link href={show.url(row.original.id)}>
                                    <Eye />
                                </Link>
                            </Button>
                        </div>
                    ),
                }),
            ] as ColumnDef<BudgetRow, any>[],
        [],
    );

    return (
        <>
            <Head title="Budgets" />
            <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-center sm:justify-between">
                    <Heading
                        title="Budgets"
                        description="Budgets prévisionnels par service et exercice"
                    />
                    {can.create && (
                        <Button asChild>
                            <Link href={create.url()}>
                                <Plus />
                                Nouveau budget
                            </Link>
                        </Button>
                    )}
                </div>

                <DataTable
                    id="admin-budgets"
                    columns={columns}
                    data={budgets.data}
                    getRowId={(row) => String(row.id)}
                    isLoading={isLoading}
                    searchValue={search}
                    onSearchChange={setSearch}
                    emptyMessage="Aucun budget."
                    sorting={sorting}
                    onSortingChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(sorting)
                                : updater;
                        setSorting(next);
                        const sort = next[0];
                        visitBudgets({
                            search,
                            sort: sort?.id ?? 'fiscal_year',
                            direction: sort?.desc === false ? 'asc' : 'desc',
                            page: 1,
                            per_page: pagination.pageSize,
                        });
                    }}
                    manualSorting
                    pagination={pagination}
                    onPaginationChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(pagination)
                                : updater;
                        setPagination(next);
                        const sort = sorting[0];
                        visitBudgets({
                            search,
                            sort: sort?.id ?? 'fiscal_year',
                            direction: sort?.desc === false ? 'asc' : 'desc',
                            page: next.pageIndex + 1,
                            per_page: next.pageSize,
                        });
                    }}
                    manualPagination
                    pageCount={budgets.last_page}
                />
            </div>
        </>
    );
}

BudgetsIndex.layout = {
    breadcrumbs: [
        { title: 'Tableau de bord', href: dashboard() },
        { title: 'Budgets', href: index() },
    ],
};
