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 {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { useCan } from '@/hooks/use-can';
import { formatCurrency, formatDate } from '@/lib/utils';
import { dashboard } from '@/routes';
import { create, index, show } from '@/routes/admin/expense-reports';
import type { Paginated } from '@/types';
import { ExpenseStatusBadge } from './status-badge';

type AdminExpenseReport = {
    id: number;
    code: string;
    title: string;
    user: { id: number; name: string } | null;
    status: string;
    status_label: string;
    total_amount: string | number;
    submitted_at: string | null;
    created_at: string | null;
};

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

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

const columnHelper = createColumnHelper<AdminExpenseReport>();

function visitReports(params: {
    search: string;
    sort: string;
    direction: 'asc' | 'desc';
    page: number;
    per_page: number;
    status: string | null;
}) {
    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,
            status: params.status ?? undefined,
        },
        {
            preserveState: true,
            replace: true,
            preserveScroll: true,
        },
    );
}

export default function ExpenseReportsIndex({
    reports,
    statuses,
    canViewAll,
    filters,
}: {
    reports: Paginated<AdminExpenseReport>;
    statuses: StatusOption[];
    canViewAll: boolean;
    filters: Filters;
}) {
    const canCreate = useCan('expenses.create');
    const isFirstSearchEffect = useRef(true);
    const [isLoading, setIsLoading] = useState(false);

    const [search, setSearch] = useState(filters.search);
    const [status, setStatus] = useState<string>(filters.status ?? 'all');
    const [sorting, setSorting] = useState<SortingState>([
        { id: filters.sort, desc: filters.direction === 'desc' },
    ]);
    const [pagination, setPagination] = useState<PaginationState>({
        pageIndex: reports.current_page - 1,
        pageSize: reports.per_page,
    });

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

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

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

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

            return;
        }

        const timeout = window.setTimeout(() => {
            const sort = sorting[0];
            visitReports({
                search,
                sort: sort?.id ?? 'created_at',
                direction: sort?.desc === false ? 'asc' : 'desc',
                page: 1,
                per_page: pagination.pageSize,
                status: status === 'all' ? null : status,
            });
        }, 300);

        return () => window.clearTimeout(timeout);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [search]);

    const columns = useMemo(() => {
        const cols: ColumnDef<AdminExpenseReport>[] = [
            columnHelper.accessor('code', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Code" />
                ),
                meta: { label: 'Code' },
                cell: (info) => (
                    <span className="font-mono text-sm">{info.getValue()}</span>
                ),
            }) as ColumnDef<AdminExpenseReport>,
            columnHelper.accessor('title', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Objet" />
                ),
                meta: { label: 'Objet' },
                cell: (info) => (
                    <span className="font-medium">{info.getValue()}</span>
                ),
            }) as ColumnDef<AdminExpenseReport>,
        ];

        if (canViewAll) {
            cols.push(
                columnHelper.accessor('user', {
                    header: 'Collaborateur',
                    enableSorting: false,
                    meta: { label: 'Collaborateur' },
                    cell: (info) => (
                        <span className="text-muted-foreground">
                            {info.getValue()?.name ?? '—'}
                        </span>
                    ),
                }) as ColumnDef<AdminExpenseReport>,
            );
        }

        cols.push(
            columnHelper.accessor('status', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Statut" />
                ),
                meta: { label: 'Statut' },
                cell: ({ row }) => (
                    <ExpenseStatusBadge
                        status={row.original.status}
                        label={row.original.status_label}
                    />
                ),
            }) as ColumnDef<AdminExpenseReport>,
            columnHelper.accessor('total_amount', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Total" />
                ),
                meta: { label: 'Total' },
                cell: (info) => (
                    <span className="tabular-nums">
                        {formatCurrency(info.getValue())}
                    </span>
                ),
            }) as ColumnDef<AdminExpenseReport>,
            columnHelper.accessor('submitted_at', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Soumise le" />
                ),
                meta: { label: 'Soumise le' },
                cell: (info) => (
                    <span className="text-muted-foreground">
                        {formatDate(info.getValue())}
                    </span>
                ),
            }) as ColumnDef<AdminExpenseReport>,
            columnHelper.display({
                id: 'actions',
                enableSorting: false,
                enableHiding: false,
                header: () => <div className="text-right">Actions</div>,
                cell: ({ row }) => (
                    <div className="flex justify-end gap-2">
                        <Button variant="outline" size="sm" asChild>
                            <Link href={show(row.original.code)}>
                                <Eye />
                                Voir
                            </Link>
                        </Button>
                    </div>
                ),
            }) as ColumnDef<AdminExpenseReport>,
        );

        return cols;
    }, [canViewAll]);

    return (
        <>
            <Head title="Notes de frais" />

            <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="Notes de frais"
                        description={
                            canViewAll
                                ? 'Suivi et validation des notes de frais'
                                : 'Vos notes de frais'
                        }
                    />
                    {canCreate && (
                        <Button asChild>
                            <Link href={create()}>
                                <Plus />
                                Nouvelle note
                            </Link>
                        </Button>
                    )}
                </div>

                <DataTable
                    id="admin-expense-reports"
                    columns={columns}
                    data={reports.data}
                    getRowId={(row) => String(row.id)}
                    isLoading={isLoading}
                    searchValue={search}
                    onSearchChange={setSearch}
                    searchPlaceholder="Rechercher par code ou objet…"
                    emptyMessage="Aucune note de frais."
                    toolbarLeft={
                        <Select
                            value={status}
                            onValueChange={(value) => {
                                setStatus(value);
                                const sort = sorting[0];
                                visitReports({
                                    search,
                                    sort: sort?.id ?? 'created_at',
                                    direction:
                                        sort?.desc === false ? 'asc' : 'desc',
                                    page: 1,
                                    per_page: pagination.pageSize,
                                    status: value === 'all' ? null : value,
                                });
                            }}
                        >
                            <SelectTrigger className="w-[180px]">
                                <SelectValue placeholder="Statut" />
                            </SelectTrigger>
                            <SelectContent>
                                <SelectItem value="all">
                                    Tous les statuts
                                </SelectItem>
                                {statuses.map((option) => (
                                    <SelectItem
                                        key={option.value}
                                        value={option.value}
                                    >
                                        {option.label}
                                    </SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                    }
                    sorting={sorting}
                    onSortingChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(sorting)
                                : updater;
                        setSorting(next);

                        const sort = next[0];
                        visitReports({
                            search,
                            sort: sort?.id ?? 'created_at',
                            direction: sort?.desc === false ? 'asc' : 'desc',
                            page: 1,
                            per_page: pagination.pageSize,
                            status: status === 'all' ? null : status,
                        });
                    }}
                    manualSorting
                    pagination={pagination}
                    onPaginationChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(pagination)
                                : updater;
                        const pageChanged =
                            next.pageIndex !== pagination.pageIndex;
                        const sizeChanged =
                            next.pageSize !== pagination.pageSize;

                        setPagination(next);

                        if (!pageChanged && !sizeChanged) {
                            return;
                        }

                        const sort = sorting[0];
                        visitReports({
                            search,
                            sort: sort?.id ?? 'created_at',
                            direction: sort?.desc === false ? 'asc' : 'desc',
                            page: sizeChanged ? 1 : next.pageIndex + 1,
                            per_page: next.pageSize,
                            status: status === 'all' ? null : status,
                        });
                    }}
                    manualPagination
                    pageCount={reports.last_page}
                    totalRows={reports.total}
                />
            </div>
        </>
    );
}

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