import { Head, router } from '@inertiajs/react';
import { createColumnHelper } from '@tanstack/react-table';
import type {
    ColumnDef,
    PaginationState,
    SortingState,
} from '@tanstack/react-table';
import { Pencil, Plus, Trash2 } from 'lucide-react';
import { useEffect, useMemo, useRef, useState } from 'react';
import LeaveTypeController from '@/actions/App/Http/Controllers/Admin/LeaveTypeController';
import { ConfirmDialog } from '@/components/confirm-dialog';
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 { formatDate } from '@/lib/utils';
import { dashboard } from '@/routes';
import { index } from '@/routes/admin/leave-types';
import type { Paginated } from '@/types';
import {
    LeaveTypeFormModal,
    type LeaveTypeFormValues,
} from './leave-type-form-modal';

type AdminLeaveType = LeaveTypeFormValues & {
    leave_requests_count: number;
    created_at: string | null;
};

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

const columnHelper = createColumnHelper<AdminLeaveType>();

function visitLeaveTypes(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 LeaveTypesIndex({
    leaveTypes,
    filters,
    can,
}: {
    leaveTypes: Paginated<AdminLeaveType>;
    filters: Filters;
    can: { create: boolean; update: boolean; delete: 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: leaveTypes.current_page - 1,
        pageSize: leaveTypes.per_page,
    });
    const [modalOpen, setModalOpen] = useState(false);
    const [editing, setEditing] = useState<LeaveTypeFormValues | null>(null);

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

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

    useEffect(() => {
        // eslint-disable-next-line react-hooks/set-state-in-effect -- sync from props
        setSearch(filters.search);
        setSorting([{ id: filters.sort, desc: filters.direction === 'desc' }]);
        setPagination({
            pageIndex: leaveTypes.current_page - 1,
            pageSize: leaveTypes.per_page,
        });
    }, [filters, leaveTypes.current_page, leaveTypes.per_page]);

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

            return;
        }

        const timeout = window.setTimeout(() => {
            const sort = sorting[0];
            visitLeaveTypes({
                search,
                sort: sort?.id ?? 'name',
                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(() => {
        const cols: ColumnDef<AdminLeaveType, any>[] = [
            columnHelper.accessor('code', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Code" />
                ),
                cell: (info) => (
                    <span className="font-mono text-sm">
                        {info.getValue()}
                    </span>
                ),
            }),
            columnHelper.accessor('name', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Nom" />
                ),
            }),
            columnHelper.accessor('deducts_balance', {
                header: 'Solde',
                enableSorting: false,
                cell: (info) =>
                    info.getValue() ? (
                        <Badge variant="secondary">Décompte un solde</Badge>
                    ) : (
                        <Badge variant="outline">Sans solde</Badge>
                    ),
            }),
            columnHelper.accessor('leave_requests_count', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Demandes" />
                ),
                enableSorting: false,
                cell: (info) => (
                    <span className="tabular-nums">{info.getValue()}</span>
                ),
            }),
            columnHelper.accessor('is_active', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Statut" />
                ),
                cell: (info) =>
                    info.getValue() ? (
                        <Badge variant="secondary">Actif</Badge>
                    ) : (
                        <Badge variant="outline">Inactif</Badge>
                    ),
            }),
            columnHelper.accessor('created_at', {
                header: ({ column }) => (
                    <DataTableColumnHeader column={column} title="Créé le" />
                ),
                cell: (info) => formatDate(info.getValue()),
            }),
        ];

        if (can.update || can.delete) {
            cols.push(
                columnHelper.display({
                    id: 'actions',
                    header: () => <span className="sr-only">Actions</span>,
                    cell: ({ row }) => (
                        <div className="flex justify-end gap-1">
                            {can.update && (
                                <Button
                                    type="button"
                                    variant="ghost"
                                    size="icon"
                                    onClick={() => {
                                        setEditing(row.original);
                                        setModalOpen(true);
                                    }}
                                >
                                    <Pencil />
                                </Button>
                            )}
                            {can.delete && (
                                <ConfirmDialog
                                    trigger={
                                        <Button
                                            type="button"
                                            variant="ghost"
                                            size="icon"
                                        >
                                            <Trash2 />
                                        </Button>
                                    }
                                    title="Supprimer ce type de congé ?"
                                    description="Impossible s'il est encore utilisé par des demandes ou des soldes."
                                    confirmLabel="Supprimer"
                                    onConfirm={() =>
                                        router.delete(
                                            LeaveTypeController.destroy.url(
                                                row.original.id,
                                            ),
                                            { preserveScroll: true },
                                        )
                                    }
                                />
                            )}
                        </div>
                    ),
                }),
            );
        }

        return cols;
    }, [can.update, can.delete]);

    return (
        <>
            <Head title="Types de congés" />
            <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="Types de congés"
                        description="Congés payés, RTT, maladie… et s'ils décomptent un solde"
                    />
                    {can.create && (
                        <Button
                            type="button"
                            onClick={() => {
                                setEditing(null);
                                setModalOpen(true);
                            }}
                        >
                            <Plus />
                            Nouveau
                        </Button>
                    )}
                </div>

                <DataTable
                    id="admin-leave-types"
                    columns={columns}
                    data={leaveTypes.data}
                    getRowId={(row) => String(row.id)}
                    isLoading={isLoading}
                    searchValue={search}
                    onSearchChange={setSearch}
                    searchPlaceholder="Rechercher…"
                    emptyMessage="Aucun type de congé."
                    sorting={sorting}
                    onSortingChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(sorting)
                                : updater;
                        setSorting(next);
                        const sort = next[0];
                        visitLeaveTypes({
                            search,
                            sort: sort?.id ?? 'name',
                            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;
                        const pageChanged =
                            next.pageIndex !== pagination.pageIndex;
                        const sizeChanged =
                            next.pageSize !== pagination.pageSize;
                        setPagination(next);

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

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

            <LeaveTypeFormModal
                open={modalOpen}
                onOpenChange={setModalOpen}
                leaveType={editing}
            />
        </>
    );
}

LeaveTypesIndex.layout = {
    breadcrumbs: [
        { title: 'Tableau de bord', href: dashboard() },
        { title: 'Types de congés', href: index() },
    ],
};
