import { useForm } from '@inertiajs/react';
import { Download, Plus } from 'lucide-react';
import { useMemo, useState } from 'react';
import type { FormEvent } from 'react';
import type {
    DepartmentOption,
    JobPositionOption,
    ManagerOption,
    SiteOption,
} from './employee-form';
import EmployeeController from '@/actions/App/Http/Controllers/Admin/EmployeeController';
import InputError from '@/components/input-error';
import { SearchableSelect } from '@/components/searchable-select';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { formatDate } from '@/lib/utils';

export type CareerEventTypeOption = {
    value: string;
    label: string;
    required_fields: string[];
};

export type ProfessionalCategoryOption = {
    value: string;
    label: string;
};

type NamedRef = { id: number; name: string };

export type EmployeeCareerEventData = {
    id: number;
    type: string;
    type_label: string;
    effective_date: string;
    old_job_title: string | null;
    new_job_title: string | null;
    old_job_position: NamedRef | null;
    new_job_position: NamedRef | null;
    old_department: NamedRef | null;
    new_department: NamedRef | null;
    old_site: NamedRef | null;
    new_site: NamedRef | null;
    old_manager: NamedRef | null;
    new_manager: NamedRef | null;
    old_professional_category: string | null;
    new_professional_category: string | null;
    old_professional_category_label: string | null;
    new_professional_category_label: string | null;
    old_classification: string | null;
    new_classification: string | null;
    note: string | null;
    is_system: boolean;
    has_decision: boolean;
    decision_original_name: string | null;
    created_by: NamedRef | null;
    created_at: string | null;
};

type Props = {
    employeeId: number;
    events: EmployeeCareerEventData[];
    careerEventTypes: CareerEventTypeOption[];
    professionalCategories: ProfessionalCategoryOption[];
    departments: DepartmentOption[];
    sites: SiteOption[];
    jobPositions: JobPositionOption[];
    managers: ManagerOption[];
    canUpdate: boolean;
};

function DiffLine({
    label,
    from,
    to,
}: {
    label: string;
    from: string | null;
    to: string | null;
}) {
    if (!to) {
        return null;
    }

    return (
        <p className="text-sm tracking-tight">
            {label} : {from || '—'} → {to}
        </p>
    );
}

export function EmployeeCareerEventsSection({
    employeeId,
    events,
    careerEventTypes,
    professionalCategories,
    departments,
    sites,
    jobPositions,
    managers,
    canUpdate,
}: Props) {
    const [open, setOpen] = useState(false);

    const form = useForm({
        type: careerEventTypes[0]?.value ?? 'promotion',
        effective_date: '',
        new_job_title: '',
        new_job_position_id: 'none',
        new_department_id: 'none',
        new_site_id: 'none',
        new_manager_id: 'none',
        new_professional_category: 'none',
        new_classification: '',
        note: '',
        decision: null as File | null,
    });

    const selectedType = careerEventTypes.find(
        (type) => type.value === form.data.type,
    );
    const requiredFields = selectedType?.required_fields ?? [];
    const isMutation = form.data.type === 'mutation';
    const showJob = isMutation || requiredFields.includes('job');
    const showDepartment =
        isMutation || requiredFields.includes('new_department_id');
    const showSite = isMutation || requiredFields.includes('new_site_id');
    const showManager =
        isMutation || requiredFields.includes('new_manager_id');
    const showClassification =
        isMutation ||
        requiredFields.includes('classification') ||
        form.data.type === 'promotion';
    const noteRequired = requiredFields.includes('note');

    const description = isMutation
        ? 'Renseignez au moins deux dimensions (poste, service, site, manager ou classification).'
        : noteRequired
          ? 'Une note est obligatoire pour ce type d’événement.'
          : 'Seuls les champs liés au type choisi sont appliqués sur la fiche.';

    const departmentOptions = useMemo(
        () =>
            departments.map((department) => ({
                value: String(department.id),
                label: department.name,
            })),
        [departments],
    );

    const siteOptions = useMemo(
        () =>
            sites.map((site) => ({
                value: String(site.id),
                label: site.name,
            })),
        [sites],
    );

    const jobPositionOptions = useMemo(
        () =>
            jobPositions.map((position) => ({
                value: String(position.id),
                label: position.name,
            })),
        [jobPositions],
    );

    const managerOptions = useMemo(
        () =>
            managers.map((manager) => ({
                value: String(manager.user_id),
                label: `${manager.full_name} (${manager.code})`,
            })),
        [managers],
    );

    const categoryOptions = useMemo(
        () =>
            professionalCategories.map((category) => ({
                value: category.value,
                label: category.label,
            })),
        [professionalCategories],
    );

    function closeDialog() {
        setOpen(false);
        form.reset();
        form.clearErrors();
    }

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

        form.transform((data) => ({
            type: data.type,
            effective_date: data.effective_date,
            new_job_title: data.new_job_title || null,
            new_job_position_id:
                data.new_job_position_id === 'none'
                    ? null
                    : Number(data.new_job_position_id),
            new_department_id:
                data.new_department_id === 'none'
                    ? null
                    : Number(data.new_department_id),
            new_site_id:
                data.new_site_id === 'none' ? null : Number(data.new_site_id),
            new_manager_id:
                data.new_manager_id === 'none'
                    ? null
                    : Number(data.new_manager_id),
            new_professional_category:
                data.new_professional_category === 'none'
                    ? null
                    : data.new_professional_category,
            new_classification: data.new_classification || null,
            note: data.note || null,
            decision: data.decision,
        }));

        form.post(EmployeeController.storeCareerEvent.url(employeeId), {
            forceFormData: true,
            preserveScroll: true,
            onSuccess: () => closeDialog(),
        });
    }

    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">
                        Parcours
                    </p>
                    <h2 className="text-lg font-semibold tracking-tight">
                        Historique de carrière
                    </h2>
                    <p className="max-w-xl text-sm leading-relaxed text-muted-foreground">
                        De l’embauche au départ : promotions, mutations,
                        reclassements et conversions de contrat.
                    </p>
                </div>
                {canUpdate && (
                    <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        onClick={() => setOpen(true)}
                    >
                        <Plus />
                        Ajouter
                    </Button>
                )}
            </div>

            <Dialog
                open={open && canUpdate}
                onOpenChange={(next) => {
                    if (!next) {
                        closeDialog();
                    }
                }}
            >
                <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-lg">
                    <DialogHeader>
                        <DialogTitle>Nouvel événement de carrière</DialogTitle>
                        <DialogDescription>{description}</DialogDescription>
                    </DialogHeader>

                    <form onSubmit={submit} className="space-y-4">
                        <div className="grid gap-4 sm:grid-cols-2">
                            <div className="grid gap-2">
                                <Label>Type</Label>
                                <Select
                                    value={form.data.type}
                                    onValueChange={(value) =>
                                        form.setData('type', value)
                                    }
                                >
                                    <SelectTrigger>
                                        <SelectValue />
                                    </SelectTrigger>
                                    <SelectContent>
                                        {careerEventTypes.map((type) => (
                                            <SelectItem
                                                key={type.value}
                                                value={type.value}
                                            >
                                                {type.label}
                                            </SelectItem>
                                        ))}
                                    </SelectContent>
                                </Select>
                                <InputError message={form.errors.type} />
                            </div>
                            <div className="grid gap-2">
                                <Label>Date d’effet</Label>
                                <Input
                                    type="date"
                                    value={form.data.effective_date}
                                    onChange={(e) =>
                                        form.setData(
                                            'effective_date',
                                            e.target.value,
                                        )
                                    }
                                />
                                <InputError
                                    message={form.errors.effective_date}
                                />
                            </div>
                        </div>

                        {showJob && (
                            <>
                                <div className="grid gap-2">
                                    <Label>Nouveau poste (référentiel)</Label>
                                    <SearchableSelect
                                        options={jobPositionOptions}
                                        value={form.data.new_job_position_id}
                                        onChange={(value) =>
                                            form.setData(
                                                'new_job_position_id',
                                                value,
                                            )
                                        }
                                        placeholder="Choisir un poste…"
                                        searchPlaceholder="Nom du poste…"
                                        noneLabel="Aucun changement"
                                    />
                                    <InputError
                                        message={
                                            form.errors.new_job_position_id
                                        }
                                    />
                                </div>
                                <div className="grid gap-2">
                                    <Label>Nouvel intitulé de poste</Label>
                                    <Input
                                        value={form.data.new_job_title}
                                        onChange={(e) =>
                                            form.setData(
                                                'new_job_title',
                                                e.target.value,
                                            )
                                        }
                                        placeholder="Ex. Lead développeur"
                                    />
                                    <InputError
                                        message={form.errors.new_job_title}
                                    />
                                </div>
                            </>
                        )}

                        {(showDepartment || showSite) && (
                            <div className="grid gap-4 sm:grid-cols-2">
                                {showDepartment && (
                                    <div className="grid gap-2">
                                        <Label>Nouveau département</Label>
                                        <SearchableSelect
                                            options={departmentOptions}
                                            value={form.data.new_department_id}
                                            onChange={(value) =>
                                                form.setData(
                                                    'new_department_id',
                                                    value,
                                                )
                                            }
                                            placeholder="Choisir un département…"
                                            searchPlaceholder="Nom du département…"
                                            noneLabel="Aucun changement"
                                        />
                                        <InputError
                                            message={
                                                form.errors.new_department_id
                                            }
                                        />
                                    </div>
                                )}
                                {showSite && (
                                    <div className="grid gap-2">
                                        <Label>Nouveau site</Label>
                                        <SearchableSelect
                                            options={siteOptions}
                                            value={form.data.new_site_id}
                                            onChange={(value) =>
                                                form.setData(
                                                    'new_site_id',
                                                    value,
                                                )
                                            }
                                            placeholder="Choisir un site…"
                                            searchPlaceholder="Nom du site…"
                                            noneLabel="Aucun changement"
                                        />
                                        <InputError
                                            message={form.errors.new_site_id}
                                        />
                                    </div>
                                )}
                            </div>
                        )}

                        {showManager && (
                            <div className="grid gap-2">
                                <Label>Nouveau manager</Label>
                                <SearchableSelect
                                    options={managerOptions}
                                    value={form.data.new_manager_id}
                                    onChange={(value) =>
                                        form.setData(
                                            'new_manager_id',
                                            value,
                                        )
                                    }
                                    placeholder="Rechercher un manager…"
                                    searchPlaceholder="Nom du manager…"
                                    noneLabel="Aucun changement"
                                />
                                <InputError
                                    message={form.errors.new_manager_id}
                                />
                            </div>
                        )}

                        {showClassification && (
                            <div className="grid gap-4 sm:grid-cols-2">
                                <div className="grid gap-2">
                                    <Label>Catégorie professionnelle</Label>
                                    <SearchableSelect
                                        options={categoryOptions}
                                        value={
                                            form.data.new_professional_category
                                        }
                                        onChange={(value) =>
                                            form.setData(
                                                'new_professional_category',
                                                value,
                                            )
                                        }
                                        placeholder="Choisir une catégorie…"
                                        searchPlaceholder="Catégorie…"
                                        noneLabel="Aucun changement"
                                    />
                                    <InputError
                                        message={
                                            form.errors
                                                .new_professional_category
                                        }
                                    />
                                </div>
                                <div className="grid gap-2">
                                    <Label>Classification</Label>
                                    <Input
                                        value={form.data.new_classification}
                                        onChange={(e) =>
                                            form.setData(
                                                'new_classification',
                                                e.target.value,
                                            )
                                        }
                                        placeholder="Ex. Cadre II B"
                                    />
                                    <InputError
                                        message={
                                            form.errors.new_classification
                                        }
                                    />
                                </div>
                            </div>
                        )}

                        <div className="grid gap-2">
                            <Label>
                                {noteRequired ? 'Note' : 'Note (optionnelle)'}
                            </Label>
                            <Textarea
                                value={form.data.note}
                                onChange={(e) =>
                                    form.setData('note', e.target.value)
                                }
                            />
                            <InputError message={form.errors.note} />
                        </div>

                        <div className="grid gap-2">
                            <Label>Pièce de décision (optionnelle)</Label>
                            <Input
                                type="file"
                                accept=".pdf,.jpg,.jpeg,.png"
                                onChange={(e) =>
                                    form.setData(
                                        'decision',
                                        e.target.files?.[0] ?? null,
                                    )
                                }
                            />
                            <p className="text-xs text-muted-foreground">
                                PDF, JPG ou PNG, 10 Mo maximum.
                            </p>
                            <InputError message={form.errors.decision} />
                        </div>

                        <DialogFooter>
                            <Button
                                type="button"
                                variant="ghost"
                                onClick={closeDialog}
                            >
                                Annuler
                            </Button>
                            <Button type="submit" disabled={form.processing}>
                                Enregistrer
                            </Button>
                        </DialogFooter>
                    </form>
                </DialogContent>
            </Dialog>

            {events.length === 0 ? (
                <p className="text-sm text-muted-foreground">
                    Aucun événement de carrière pour le moment.
                </p>
            ) : (
                <ol className="divide-y divide-border border-y">
                    {events.map((event) => (
                        <li key={event.id} className="space-y-2 py-4">
                            <div className="flex flex-wrap items-center gap-2">
                                <Badge
                                    variant="secondary"
                                    className="font-normal"
                                >
                                    {event.type_label}
                                </Badge>
                                {event.is_system && (
                                    <Badge
                                        variant="outline"
                                        className="font-normal"
                                    >
                                        Système
                                    </Badge>
                                )}
                                <span className="text-xs text-muted-foreground">
                                    {formatDate(event.effective_date)}
                                    {event.created_by?.name
                                        ? ` · ${event.created_by.name}`
                                        : ''}
                                </span>
                                {event.has_decision && (
                                    <Button
                                        type="button"
                                        variant="ghost"
                                        size="sm"
                                        className="h-7 px-2"
                                        asChild
                                    >
                                        <a
                                            href={EmployeeController.downloadCareerEventDecision.url(
                                                {
                                                    employee: employeeId,
                                                    careerEvent: event.id,
                                                },
                                            )}
                                        >
                                            <Download />
                                            {event.decision_original_name ||
                                                'Décision'}
                                        </a>
                                    </Button>
                                )}
                            </div>
                            <div className="space-y-1">
                                <DiffLine
                                    label="Poste"
                                    from={event.old_job_title}
                                    to={event.new_job_title}
                                />
                                <DiffLine
                                    label="Poste (référentiel)"
                                    from={
                                        event.old_job_position?.name ?? null
                                    }
                                    to={event.new_job_position?.name ?? null}
                                />
                                <DiffLine
                                    label="Service"
                                    from={event.old_department?.name ?? null}
                                    to={event.new_department?.name ?? null}
                                />
                                <DiffLine
                                    label="Site"
                                    from={event.old_site?.name ?? null}
                                    to={event.new_site?.name ?? null}
                                />
                                <DiffLine
                                    label="Manager"
                                    from={event.old_manager?.name ?? null}
                                    to={event.new_manager?.name ?? null}
                                />
                                <DiffLine
                                    label="Catégorie"
                                    from={
                                        event.old_professional_category_label
                                    }
                                    to={
                                        event.new_professional_category_label
                                    }
                                />
                                <DiffLine
                                    label="Classification"
                                    from={event.old_classification}
                                    to={event.new_classification}
                                />
                            </div>
                            {event.note && (
                                <p className="text-sm leading-relaxed text-muted-foreground">
                                    {event.note}
                                </p>
                            )}
                        </li>
                    ))}
                </ol>
            )}
        </section>
    );
}
