import { router, useForm } from '@inertiajs/react';
import {
    AlertTriangle,
    Download,
    Eye,
    EyeOff,
    FileText,
    Lock,
    Pencil,
    Plus,
    Trash2,
} from 'lucide-react';
import { useMemo, useState } from 'react';
import type { FormEvent } from 'react';
import EmployeeController from '@/actions/App/Http/Controllers/Admin/EmployeeController';
import { ConfirmDialog } from '@/components/confirm-dialog';
import InputError from '@/components/input-error';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectGroup,
    SelectItem,
    SelectLabel,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { formatDate } from '@/lib/utils';

export type DocumentTypeOption = {
    value: string;
    label: string;
    group: string;
    group_label: string;
    expects_expiry: boolean;
    can_apply_to_profile: boolean;
};

export type EmployeeDocumentData = {
    id: number;
    type: string;
    type_label: string;
    group: string;
    group_label: string;
    title: string;
    document_number: string | null;
    issued_on: string | null;
    expires_on: string | null;
    expiry_status: 'expired' | 'expiring' | null;
    original_name: string;
    mime_type: string | null;
    is_image: boolean;
    is_confidential: boolean;
    can_apply_to_profile: boolean;
    uploaded_by: { id: number; name: string } | null;
    created_at: string | null;
};

export type DocumentChecklist = {
    items: Array<{
        key: string;
        label: string;
        required: boolean;
        status: 'present' | 'expired' | 'missing';
    }>;
    required_total: number;
    required_present: number;
    required_missing: number;
    required_expired: number;
};

const GROUP_ORDER = [
    'identity',
    'civil',
    'social',
    'foreign',
    'hr',
    'other',
] as const;

function emptyForm(documentTypes: DocumentTypeOption[]) {
    const first = documentTypes[0];

    return {
        type: first?.value ?? 'other',
        title: first?.label ?? '',
        document_number: '',
        issued_on: '',
        expires_on: '',
        apply_to_profile: false,
        is_confidential: false,
        file: null as File | null,
    };
}

function typeOption(
    documentTypes: DocumentTypeOption[],
    value: string,
): DocumentTypeOption | undefined {
    return documentTypes.find((type) => type.value === value);
}

export function DocumentScanLinks({
    employeeId,
    documents,
    types,
}: {
    employeeId: number;
    documents: EmployeeDocumentData[];
    types: string[];
}) {
    const matches = documents.filter((document) =>
        types.includes(document.type),
    );

    if (matches.length === 0) {
        return null;
    }

    return (
        <span className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-xs font-normal">
            {matches.map((document) => (
                <a
                    key={document.id}
                    href={EmployeeController.previewDocument.url({
                        employee: employeeId,
                        document: document.id,
                    })}
                    target="_blank"
                    rel="noreferrer"
                    className="text-muted-foreground underline-offset-2 hover:underline"
                >
                    Voir le scan
                    {matches.length > 1 ? ` (${document.type_label})` : ''}
                </a>
            ))}
        </span>
    );
}

export function EmployeeDocumentsSection({
    employeeId,
    documents,
    documentTypes,
    checklist,
    documentAlert,
    canUpdate,
    canViewConfidentialDocuments = false,
    confidentialDocumentsHidden = 0,
}: {
    employeeId: number;
    documents: EmployeeDocumentData[];
    documentTypes: DocumentTypeOption[];
    checklist: DocumentChecklist;
    documentAlert: 'expired' | 'expiring' | 'incomplete' | null;
    canUpdate: boolean;
    canViewConfidentialDocuments?: boolean;
    confidentialDocumentsHidden?: number;
}) {
    const [formOpen, setFormOpen] = useState(false);
    const [editingId, setEditingId] = useState<number | null>(null);
    const [preview, setPreview] = useState<EmployeeDocumentData | null>(null);
    const docForm = useForm(emptyForm(documentTypes));
    const selectedType = typeOption(documentTypes, docForm.data.type);

    const groupedTypes = useMemo(() => {
        const byGroup = new Map<string, DocumentTypeOption[]>();

        for (const type of documentTypes) {
            const list = byGroup.get(type.group) ?? [];
            list.push(type);
            byGroup.set(type.group, list);
        }

        return GROUP_ORDER.filter((group) => byGroup.has(group)).map(
            (group) => ({
                group,
                label: byGroup.get(group)?.[0]?.group_label ?? group,
                types: byGroup.get(group) ?? [],
            }),
        );
    }, [documentTypes]);

    const groupedDocuments = useMemo(() => {
        const byGroup = new Map<string, EmployeeDocumentData[]>();

        for (const document of documents) {
            const list = byGroup.get(document.group) ?? [];
            list.push(document);
            byGroup.set(document.group, list);
        }

        return GROUP_ORDER.filter((group) => byGroup.has(group)).map(
            (group) => ({
                group,
                label: byGroup.get(group)?.[0]?.group_label ?? group,
                documents: byGroup.get(group) ?? [],
            }),
        );
    }, [documents]);

    const requiredItems = checklist.items.filter((item) => item.required);
    const recommendedItems = checklist.items.filter((item) => !item.required);

    function openCreate() {
        setEditingId(null);
        docForm.reset();
        docForm.setData(emptyForm(documentTypes));
        setFormOpen(true);
        docForm.clearErrors();
    }

    function openEdit(document: EmployeeDocumentData) {
        setEditingId(document.id);
        docForm.setData({
            type: document.type,
            title: document.title,
            document_number: document.document_number ?? '',
            issued_on: document.issued_on ?? '',
            expires_on: document.expires_on ?? '',
            apply_to_profile: false,
            is_confidential: document.is_confidential,
            file: null,
        });
        docForm.clearErrors();
        setFormOpen(true);
    }

    function closeForm() {
        setFormOpen(false);
        setEditingId(null);
        docForm.reset();
        docForm.setData(emptyForm(documentTypes));
    }

    function changeType(value: string) {
        const previousLabel = typeOption(
            documentTypes,
            docForm.data.type,
        )?.label;
        const nextLabel = typeOption(documentTypes, value)?.label ?? '';

        docForm.setData({
            ...docForm.data,
            type: value,
            title:
                docForm.data.title === '' ||
                docForm.data.title === previousLabel
                    ? nextLabel
                    : docForm.data.title,
        });
    }

    function submitDocument(event: FormEvent) {
        event.preventDefault();

        docForm.transform((data) => {
            const payload: Record<string, unknown> = {
                type: data.type,
                title: data.title,
                document_number: data.document_number || null,
                issued_on: data.issued_on || null,
                expires_on: data.expires_on || null,
                apply_to_profile: data.apply_to_profile,
            };

            if (canViewConfidentialDocuments) {
                payload.is_confidential = data.is_confidential;
            }

            if (data.file) {
                payload.file = data.file;
            }

            return payload;
        });

        const options = {
            forceFormData: true,
            preserveScroll: true,
            onSuccess: () => closeForm(),
        };

        if (editingId) {
            docForm.put(
                EmployeeController.updateDocument.url({
                    employee: employeeId,
                    document: editingId,
                }),
                options,
            );

            return;
        }

        docForm.post(EmployeeController.storeDocument.url(employeeId), options);
    }

    return (
        <section className="space-y-6 border-t border-border pt-10">
            <div className="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
                <div className="space-y-1.5">
                    <p className="text-xs font-medium tracking-[0.14em] text-muted-foreground uppercase">
                        Coffre-fort
                    </p>
                    <h2 className="text-lg font-semibold tracking-tight">
                        Documents administratifs
                    </h2>
                    <p className="max-w-xl text-sm leading-relaxed text-muted-foreground">
                        Dossier d’embauche ivoirien — pièces d’identité,
                        protection sociale et RH. Les contrats restent à part.
                    </p>
                </div>
                <div className="flex flex-wrap gap-2">
                    {canUpdate && (
                        <Button
                            type="button"
                            variant="outline"
                            size="sm"
                            onClick={openCreate}
                        >
                            <Plus />
                            Ajouter
                        </Button>
                    )}
                    <Button type="button" variant="outline" size="sm" asChild>
                        <a
                            href={EmployeeController.downloadWorkAttestation.url(
                                employeeId,
                            )}
                        >
                            <FileText />
                            Générer l'attestation de travail
                        </a>
                    </Button>
                </div>
            </div>

            {confidentialDocumentsHidden > 0 && (
                <Alert>
                    <EyeOff />
                    <AlertTitle>Accès restreint</AlertTitle>
                    <AlertDescription>
                        {confidentialDocumentsHidden === 1
                            ? "1 document confidentiel n'est pas affiché (accès restreint)."
                            : `${confidentialDocumentsHidden} documents confidentiels ne sont pas affichés (accès restreint).`}
                    </AlertDescription>
                </Alert>
            )}

            {documentAlert && (
                <Alert
                    variant={
                        documentAlert === 'expired' ? 'destructive' : 'default'
                    }
                >
                    <AlertTriangle />
                    <AlertTitle>
                        {documentAlert === 'expired' && 'Document expiré'}
                        {documentAlert === 'expiring' &&
                            'Échéance dans les 60 jours'}
                        {documentAlert === 'incomplete' && 'Dossier incomplet'}
                    </AlertTitle>
                    <AlertDescription>
                        {documentAlert === 'incomplete'
                            ? `${checklist.required_missing} pièce${checklist.required_missing > 1 ? 's' : ''} obligatoire${checklist.required_missing > 1 ? 's' : ''} manquante${checklist.required_missing > 1 ? 's' : ''}.`
                            : 'Vérifiez les dates d’expiration des pièces du dossier.'}
                    </AlertDescription>
                </Alert>
            )}

            <div className="grid gap-6 lg:grid-cols-2">
                <ChecklistList
                    title="Obligatoire"
                    items={requiredItems}
                    summary={`${checklist.required_present}/${checklist.required_total}`}
                />
                <ChecklistList title="Recommandé" items={recommendedItems} />
            </div>

            {formOpen && canUpdate && (
                <form
                    onSubmit={submitDocument}
                    className="grid gap-4 border border-border p-4 md:grid-cols-3"
                >
                    <div className="grid gap-2">
                        <Label>Type</Label>
                        <Select
                            value={docForm.data.type}
                            onValueChange={changeType}
                        >
                            <SelectTrigger>
                                <SelectValue />
                            </SelectTrigger>
                            <SelectContent>
                                {groupedTypes.map((group) => (
                                    <SelectGroup key={group.group}>
                                        <SelectLabel>{group.label}</SelectLabel>
                                        {group.types.map((type) => (
                                            <SelectItem
                                                key={type.value}
                                                value={type.value}
                                            >
                                                {type.label}
                                            </SelectItem>
                                        ))}
                                    </SelectGroup>
                                ))}
                            </SelectContent>
                        </Select>
                    </div>
                    <div className="grid gap-2">
                        <Label>Titre</Label>
                        <Input
                            value={docForm.data.title}
                            onChange={(e) =>
                                docForm.setData('title', e.target.value)
                            }
                        />
                        <InputError message={docForm.errors.title} />
                    </div>
                    <div className="grid gap-2">
                        <Label>Numéro</Label>
                        <Input
                            value={docForm.data.document_number}
                            onChange={(e) =>
                                docForm.setData(
                                    'document_number',
                                    e.target.value,
                                )
                            }
                        />
                        <InputError message={docForm.errors.document_number} />
                    </div>
                    <div className="grid gap-2">
                        <Label>Délivrance</Label>
                        <Input
                            type="date"
                            value={docForm.data.issued_on}
                            onChange={(e) =>
                                docForm.setData('issued_on', e.target.value)
                            }
                        />
                        <InputError message={docForm.errors.issued_on} />
                    </div>
                    <div className="grid gap-2">
                        <Label>
                            Expiration
                            {selectedType?.expects_expiry
                                ? ' (recommandée)'
                                : ''}
                        </Label>
                        <Input
                            type="date"
                            value={docForm.data.expires_on}
                            onChange={(e) =>
                                docForm.setData('expires_on', e.target.value)
                            }
                        />
                        <InputError message={docForm.errors.expires_on} />
                    </div>
                    <div className="grid gap-2">
                        <Label>Fichier {editingId ? '(optionnel)' : ''}</Label>
                        <Input
                            type="file"
                            accept=".pdf,.jpg,.jpeg,.png"
                            onChange={(e) =>
                                docForm.setData(
                                    'file',
                                    e.target.files?.[0] ?? null,
                                )
                            }
                        />
                        <p className="text-xs text-muted-foreground">
                            PDF, JPG ou PNG — 10 Mo max.
                        </p>
                        <InputError message={docForm.errors.file} />
                    </div>
                    {selectedType?.can_apply_to_profile && (
                        <div className="flex items-start gap-2 md:col-span-3">
                            <Checkbox
                                id="apply_to_profile"
                                checked={docForm.data.apply_to_profile}
                                onCheckedChange={(checked) =>
                                    docForm.setData(
                                        'apply_to_profile',
                                        checked === true,
                                    )
                                }
                            />
                            <Label
                                htmlFor="apply_to_profile"
                                className="leading-snug font-normal"
                            >
                                Reporter n° et dates sur la fiche
                                {selectedType.group === 'identity'
                                    ? ' (remplace la pièce d’identité principale)'
                                    : ''}
                            </Label>
                        </div>
                    )}
                    {canViewConfidentialDocuments && (
                        <div className="flex items-start gap-2 md:col-span-3">
                            <Checkbox
                                id="is_confidential"
                                checked={docForm.data.is_confidential}
                                onCheckedChange={(checked) =>
                                    docForm.setData(
                                        'is_confidential',
                                        checked === true,
                                    )
                                }
                            />
                            <Label
                                htmlFor="is_confidential"
                                className="leading-snug font-normal"
                            >
                                Document confidentiel — accès limité aux
                                titulaires de la permission dédiée
                            </Label>
                        </div>
                    )}
                    <div className="flex gap-2 md:col-span-3">
                        <Button type="submit" disabled={docForm.processing}>
                            Enregistrer
                        </Button>
                        <Button
                            type="button"
                            variant="ghost"
                            onClick={closeForm}
                        >
                            Fermer
                        </Button>
                    </div>
                </form>
            )}

            {documents.length === 0 ? (
                <p className="text-sm text-muted-foreground">
                    Aucun document pour le moment.
                </p>
            ) : (
                <div className="space-y-8">
                    {groupedDocuments.map((group) => (
                        <div key={group.group} className="space-y-2">
                            <p className="text-xs font-medium tracking-[0.14em] text-muted-foreground uppercase">
                                {group.label}
                            </p>
                            <ul className="divide-y divide-border border-y">
                                {group.documents.map((document) => (
                                    <li
                                        key={document.id}
                                        className="flex items-center justify-between gap-4 py-3.5"
                                    >
                                        <div className="min-w-0">
                                            <p className="truncate text-sm font-medium tracking-tight">
                                                {document.title}
                                            </p>
                                            <p className="text-xs text-muted-foreground">
                                                {document.type_label}
                                                {document.document_number
                                                    ? ` · n° ${document.document_number}`
                                                    : ''}
                                                {document.expires_on
                                                    ? ` · exp. ${formatDate(document.expires_on)}`
                                                    : document.created_at
                                                      ? ` · ${formatDate(document.created_at)}`
                                                      : ''}
                                            </p>
                                        </div>
                                        <div className="flex shrink-0 items-center gap-1">
                                            {document.is_confidential && (
                                                <Badge variant="outline">
                                                    <Lock />
                                                    Confidentiel
                                                </Badge>
                                            )}
                                            {document.expiry_status ===
                                                'expired' && (
                                                <Badge variant="destructive">
                                                    Expiré
                                                </Badge>
                                            )}
                                            {document.expiry_status ===
                                                'expiring' && (
                                                <Badge variant="secondary">
                                                    Échéance
                                                </Badge>
                                            )}
                                            <Button
                                                variant="ghost"
                                                size="icon"
                                                onClick={() =>
                                                    setPreview(document)
                                                }
                                            >
                                                <Eye />
                                            </Button>
                                            <Button
                                                variant="ghost"
                                                size="icon"
                                                asChild
                                            >
                                                <a
                                                    href={EmployeeController.downloadDocument.url(
                                                        {
                                                            employee:
                                                                employeeId,
                                                            document:
                                                                document.id,
                                                        },
                                                    )}
                                                >
                                                    <Download />
                                                </a>
                                            </Button>
                                            {canUpdate && (
                                                <>
                                                    <Button
                                                        variant="ghost"
                                                        size="icon"
                                                        onClick={() =>
                                                            openEdit(document)
                                                        }
                                                    >
                                                        <Pencil />
                                                    </Button>
                                                    <ConfirmDialog
                                                        trigger={
                                                            <Button
                                                                variant="ghost"
                                                                size="icon"
                                                            >
                                                                <Trash2 />
                                                            </Button>
                                                        }
                                                        title="Supprimer ce document ?"
                                                        confirmLabel="Supprimer"
                                                        onConfirm={() =>
                                                            router.delete(
                                                                EmployeeController.destroyDocument.url(
                                                                    {
                                                                        employee:
                                                                            employeeId,
                                                                        document:
                                                                            document.id,
                                                                    },
                                                                ),
                                                                {
                                                                    preserveScroll: true,
                                                                },
                                                            )
                                                        }
                                                    />
                                                </>
                                            )}
                                        </div>
                                    </li>
                                ))}
                            </ul>
                        </div>
                    ))}
                </div>
            )}

            <Dialog
                open={preview !== null}
                onOpenChange={(open) => {
                    if (!open) {
                        setPreview(null);
                    }
                }}
            >
                <DialogContent className="max-h-[90vh] overflow-hidden sm:max-w-4xl">
                    <DialogHeader>
                        <DialogTitle>{preview?.title}</DialogTitle>
                        <DialogDescription>
                            {preview?.type_label}
                            {preview?.original_name
                                ? ` · ${preview.original_name}`
                                : ''}
                        </DialogDescription>
                    </DialogHeader>
                    {preview && (
                        <div className="h-[70vh] overflow-auto bg-muted/30">
                            {preview.is_image ? (
                                <img
                                    src={EmployeeController.previewDocument.url(
                                        {
                                            employee: employeeId,
                                            document: preview.id,
                                        },
                                    )}
                                    alt={preview.title}
                                    className="mx-auto max-h-full max-w-full object-contain"
                                />
                            ) : (
                                <iframe
                                    title={preview.title}
                                    src={EmployeeController.previewDocument.url(
                                        {
                                            employee: employeeId,
                                            document: preview.id,
                                        },
                                    )}
                                    className="h-full w-full border-0"
                                />
                            )}
                        </div>
                    )}
                </DialogContent>
            </Dialog>
        </section>
    );
}

function ChecklistList({
    title,
    items,
    summary,
}: {
    title: string;
    items: DocumentChecklist['items'];
    summary?: string;
}) {
    if (items.length === 0) {
        return null;
    }

    return (
        <div className="space-y-3">
            <div className="flex items-baseline justify-between gap-2">
                <p className="text-xs font-medium tracking-[0.14em] text-muted-foreground uppercase">
                    {title}
                </p>
                {summary && (
                    <p className="text-xs text-muted-foreground tabular-nums">
                        {summary}
                    </p>
                )}
            </div>
            <ul className="space-y-1.5">
                {items.map((item) => (
                    <li
                        key={item.key}
                        className="flex items-center justify-between gap-3 text-sm"
                    >
                        <span>{item.label}</span>
                        <ChecklistStatus status={item.status} />
                    </li>
                ))}
            </ul>
        </div>
    );
}

function ChecklistStatus({
    status,
}: {
    status: 'present' | 'expired' | 'missing';
}) {
    if (status === 'present') {
        return <Badge variant="secondary">Présent</Badge>;
    }

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

    return <Badge variant="outline">Manquant</Badge>;
}
