import { Head, Link, router } from '@inertiajs/react';
import { createColumnHelper } from '@tanstack/react-table';
import type {
    ColumnDef,
    PaginationState,
    SortingState,
} from '@tanstack/react-table';
import { Eye, FileText, Pencil, Plus, Trash2 } from 'lucide-react';
import { useEffect, useMemo, useRef, useState } from 'react';
import EmployeeController from '@/actions/App/Http/Controllers/Admin/EmployeeController';
import { AnimatedAction } from '@/components/animated-action';
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 {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { useCan, useHasRole } from '@/hooks/use-can';
import { dashboard } from '@/routes';
import { create, index, show } from '@/routes/admin/employees';
import type { Paginated } from '@/types';

type AdminEmployee = {
    id: number;
    code: string;
    first_name: string;
    last_name: string;
    full_name: string;
    email: string | null;
    phone: string | null;
    personal_email: string | null;
    job_title: string | null;
    department: string | null;
    contract_type: string;
    contract_type_label: string;
    is_active: boolean;
    employment_status: 'active' | 'inactive' | 'departed';
    employment_status_label: string;
    terminated_at: string | null;
    document_alert: 'expired' | 'expiring' | 'incomplete' | null;
    manager: { id: number; name: string } | null;
    created_at: string | null;
};

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

type DepartmentOption = { id: number; code: string; name: string };
type ContractTypeOption = { value: string; label: string };

const columnHelper = createColumnHelper<AdminEmployee>();

function visitEmployees(params: {
    search: string;
    department_id: string;
    job_title: string;
    status: string;
    contract_type: string;
    document_alert: string;
    sort: string;
    direction: 'asc' | 'desc';
    page: number;
    per_page: number;
}) {
    router.get(
        index.url(),
        {
            search: params.search || undefined,
            department_id:
                params.department_id && params.department_id !== 'all'
                    ? params.department_id
                    : undefined,
            job_title: params.job_title || undefined,
            status: params.status || undefined,
            contract_type:
                params.contract_type && params.contract_type !== 'all'
                    ? params.contract_type
                    : undefined,
            document_alert:
                params.document_alert && params.document_alert !== 'all'
                    ? params.document_alert
                    : 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 EmployeesIndex({
    employees,
    filters,
    departments = [],
    contractTypes = [],
}: {
    employees: Paginated<AdminEmployee>;
    filters: Filters;
    departments?: DepartmentOption[];
    contractTypes?: ContractTypeOption[];
}) {
    const canCreate = useCan('employees.create');
    const canUpdate = useCan('employees.update');
    const canDelete = useCan('employees.delete') || useHasRole('super-admin');
    const isFirstSearchEffect = useRef(true);
    const [isLoading, setIsLoading] = useState(false);
    const [search, setSearch] = useState(filters.search);
    const [departmentId, setDepartmentId] = useState(
        filters.department_id ? String(filters.department_id) : 'all',
    );
    const [status, setStatus] = useState(filters.status || 'all');
    const [contractType, setContractType] = useState(
        filters.contract_type || 'all',
    );
    const [documentAlert, setDocumentAlert] = useState(
        filters.document_alert || 'all',
    );
    const [sorting, setSorting] = useState<SortingState>([
        { id: filters.sort, desc: filters.direction === 'desc' },
    ]);
    const [pagination, setPagination] = useState<PaginationState>({
        pageIndex: employees.current_page - 1,
        pageSize: employees.per_page,
    });

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

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

    useEffect(() => {
        setSearch(filters.search);
        setDepartmentId(
            filters.department_id ? String(filters.department_id) : 'all',
        );
        setStatus(filters.status || 'all');
        setContractType(filters.contract_type || 'all');
        setDocumentAlert(filters.document_alert || 'all');
        setSorting([{ id: filters.sort, desc: filters.direction === 'desc' }]);
        setPagination({
            pageIndex: employees.current_page - 1,
            pageSize: employees.per_page,
        });
    }, [filters, employees.current_page, employees.per_page]);

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

            return;
        }

        const timeout = window.setTimeout(() => {
            const sort = sorting[0];
            visitEmployees({
                search,
                department_id: departmentId,
                job_title: filters.job_title,
                status: status === 'all' ? '' : status,
                contract_type: contractType,
                document_alert: documentAlert,
                sort: sort?.id ?? 'created_at',
                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, departmentId, status, contractType, documentAlert]);

    const columns = useMemo(
        () =>
            [
                columnHelper.accessor('full_name', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Nom" />
                    ),
                    cell: (info) => (
                        <Link
                            href={show(info.row.original.id)}
                            className="font-medium hover:underline"
                        >
                            {info.getValue()}
                        </Link>
                    ),
                }),
                columnHelper.accessor('job_title', {
                    header: 'Poste',
                    enableSorting: false,
                    cell: (info) => info.getValue() || '—',
                }),
                columnHelper.accessor('department', {
                    header: 'Service',
                    enableSorting: false,
                    cell: (info) => info.getValue() || '—',
                }),
                columnHelper.accessor('contract_type_label', {
                    header: 'Contrat',
                    enableSorting: false,
                    cell: (info) => info.getValue() || '—',
                }),
                columnHelper.display({
                    id: 'contact',
                    header: 'Contact personnel',
                    enableSorting: false,
                    cell: ({ row }) => {
                        const phone = row.original.phone;
                        const personalEmail = row.original.personal_email;

                        if (!phone && !personalEmail) {
                            return '—';
                        }

                        return (
                            <div className="space-y-0.5 text-sm">
                                {phone && (
                                    <p className="tabular-nums">{phone}</p>
                                )}
                                {personalEmail && (
                                    <p className="text-muted-foreground">
                                        {personalEmail}
                                    </p>
                                )}
                            </div>
                        );
                    },
                }),
                columnHelper.accessor('employment_status_label', {
                    id: 'is_active',
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Statut" />
                    ),
                    cell: ({ row }) => (
                        <Badge
                            variant={
                                row.original.employment_status === 'active'
                                    ? 'secondary'
                                    : 'outline'
                            }
                        >
                            {row.original.employment_status === 'departed' &&
                            row.original.terminated_at
                                ? `Parti`
                                : row.original.employment_status_label}
                        </Badge>
                    ),
                }),
                columnHelper.display({
                    id: 'document_alert',
                    header: 'Dossier',
                    enableSorting: false,
                    cell: ({ row }) => {
                        const alert = row.original.document_alert;

                        if (alert === 'expired') {
                            return <Badge variant="destructive">Expiré</Badge>;
                        }

                        if (alert === 'expiring') {
                            return <Badge variant="secondary">Échéance</Badge>;
                        }

                        if (alert === 'incomplete') {
                            return <Badge variant="outline">Incomplet</Badge>;
                        }

                        return <span className="text-muted-foreground">—</span>;
                    },
                }),
                columnHelper.display({
                    id: 'actions',
                    header: '',
                    cell: ({ row }) => (
                        <div className="flex justify-end gap-1">
                            <AnimatedAction title="Voir le profil" asChild>
                                <Link href={show(row.original.id)}>
                                    <Eye className="size-4" />
                                    <span className="sr-only">Voir</span>
                                </Link>
                            </AnimatedAction>
                            <AnimatedAction title="Fiche PDF" asChild>
                                <a
                                    href={EmployeeController.downloadProfile.url(
                                        row.original.id,
                                    )}
                                >
                                    <FileText className="size-4" />
                                    <span className="sr-only">PDF</span>
                                </a>
                            </AnimatedAction>
                            {canUpdate && (
                                <AnimatedAction
                                    title="Modifier"
                                    onClick={() =>
                                        router.get(
                                            EmployeeController.edit.url(
                                                row.original.id,
                                            ),
                                        )
                                    }
                                >
                                    <Pencil className="size-4" />
                                    <span className="sr-only">Modifier</span>
                                </AnimatedAction>
                            )}
                            {canDelete && (
                                <ConfirmDialog
                                    trigger={
                                        <AnimatedAction title="Supprimer" className="hover:text-destructive hover:bg-destructive/10">
                                            <Trash2 className="size-4" />
                                            <span className="sr-only">Supprimer</span>
                                        </AnimatedAction>
                                    }
                                    title="Supprimer ce collaborateur ?"
                                    description="Cette action archive le collaborateur."
                                    confirmLabel="Supprimer"
                                    onConfirm={() =>
                                        router.delete(
                                            EmployeeController.destroy.url(
                                                row.original.id,
                                            ),
                                        )
                                    }
                                />
                            )}
                        </div>
                    ),
                }),
            ] as ColumnDef<AdminEmployee>[],
        [canDelete, canUpdate],
    );

    return (
        <>
            <Head title="Collaborateurs" />
            <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="Collaborateurs"
                        description="Annuaire et dossiers RH"
                    />
                    {canCreate && (
                        <Button asChild>
                            <Link href={create()}>
                                <Plus />
                                Nouveau
                            </Link>
                        </Button>
                    )}
                </div>

                <DataTable
                    id="admin-employees"
                    columns={columns}
                    data={employees.data}
                    getRowId={(row) => String(row.id)}
                    isLoading={isLoading}
                    searchValue={search}
                    onSearchChange={setSearch}
                    searchPlaceholder="Rechercher…"
                    emptyMessage="Aucun collaborateur."
                    toolbarLeft={
                        <div className="flex flex-wrap gap-2">
                            <Select
                                value={departmentId}
                                onValueChange={setDepartmentId}
                            >
                                <SelectTrigger className="w-[200px]">
                                    <SelectValue placeholder="Service" />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="all">
                                        Tous les services
                                    </SelectItem>
                                    {departments.map((department) => (
                                        <SelectItem
                                            key={department.id}
                                            value={String(department.id)}
                                        >
                                            {department.name}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            <Select
                                value={contractType}
                                onValueChange={setContractType}
                            >
                                <SelectTrigger className="w-[160px]">
                                    <SelectValue placeholder="Contrat" />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="all">
                                        Tous les contrats
                                    </SelectItem>
                                    {contractTypes.map((type) => (
                                        <SelectItem
                                            key={type.value}
                                            value={type.value}
                                        >
                                            {type.label}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            <Select value={status} onValueChange={setStatus}>
                                <SelectTrigger className="w-[160px]">
                                    <SelectValue placeholder="Statut" />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="all">Tous</SelectItem>
                                    <SelectItem value="active">
                                        Actifs
                                    </SelectItem>
                                    <SelectItem value="inactive">
                                        Inactifs
                                    </SelectItem>
                                    <SelectItem value="departed">
                                        Partis
                                    </SelectItem>
                                </SelectContent>
                            </Select>
                            <Select
                                value={documentAlert}
                                onValueChange={setDocumentAlert}
                            >
                                <SelectTrigger className="w-[180px]">
                                    <SelectValue placeholder="Dossier" />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="all">
                                        Tous les dossiers
                                    </SelectItem>
                                    <SelectItem value="expired">
                                        Pièces expirées
                                    </SelectItem>
                                    <SelectItem value="expiring">
                                        Échéance 60 jours
                                    </SelectItem>
                                    <SelectItem value="incomplete">
                                        Dossiers incomplets
                                    </SelectItem>
                                </SelectContent>
                            </Select>
                        </div>
                    }
                    sorting={sorting}
                    onSortingChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(sorting)
                                : updater;
                        setSorting(next);
                        const sort = next[0];
                        visitEmployees({
                            search,
                            department_id: departmentId,
                            job_title: filters.job_title,
                            status: status === 'all' ? '' : status,
                            contract_type: contractType,
                            document_alert: documentAlert,
                            sort: sort?.id ?? 'created_at',
                            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];
                        visitEmployees({
                            search,
                            department_id: departmentId,
                            job_title: filters.job_title,
                            status: status === 'all' ? '' : status,
                            contract_type: contractType,
                            document_alert: documentAlert,
                            sort: sort?.id ?? 'created_at',
                            direction: sort?.desc === false ? 'asc' : 'desc',
                            page: sizeChanged ? 1 : next.pageIndex + 1,
                            per_page: next.pageSize,
                        });
                    }}
                    manualPagination
                    pageCount={employees.last_page}
                    totalRows={employees.total}
                />
            </div>
        </>
    );
}

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