import { FrDateInput } from '@/components/fr-date-input';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
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 { useTranslation } from '@/hooks/use-translation';
import { useForm } from '@inertiajs/react';
import * as React from 'react';
import type { SupplierRow } from './columns';
import { derniereDateNaissanceIso, estIdentifieeParCin, isoDateNaissance } from './tej';

interface Props {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    /** Fournisseur à modifier. Ce formulaire ne crée plus : jamais `null` ouvert. */
    supplier: SupplierRow;
}

/**
 * MODIFICATION d'un fournisseur tiers. Ce formulaire ne crée plus rien.
 *
 * ─────────────────────────────────────────────────────────────────────────────
 * IL A PERDU SA BRANCHE « CRÉATION AU CIN », LE 2026-08-17
 * ─────────────────────────────────────────────────────────────────────────────
 * Elle servait le cas « personne physique hors parc », retiré du dialogue de
 * choix : une personne physique qui reçoit une retenue est payée POUR UN BIEN,
 * donc c'est un propriétaire, donc son compte existe déjà. Voir l'en-tête de
 * `supplier-choice-dialog`.
 *
 * Ce qui reste est le formulaire complet de modification, inchangé depuis
 * toujours : le type de personne se choisit, les deux identifiants sont
 * saisissables. Les fiches en base portent toutes les combinaisons possibles —
 * dont des personnes physiques au matricule fiscal — et leur retirer un champ
 * les rendrait incorrigibles.
 *
 * Aucun taux par défaut : le taux se choisit ligne par ligne au moment de la
 * déclaration, et reste figé sur la ligne.
 *
 * ⚠️ CE FORMULAIRE N'ENVOIE RIEN À LA DGI, et depuis le 2026-08-24 c'est vrai de
 * la CRÉATION aussi : `BeneficiaireController::store()` ne tente plus aucun
 * envoi automatique. Le seul chemin de création qui reste ici est
 * `supplier-registre-dialog`, et il n'envoie pas davantage — sa dernière étape
 * ne fait que PROPOSER l'envoi manuel, jamais le déclencher elle-même.
 */
export function SupplierDialog({ open, onOpenChange, supplier }: Props) {
    const { t } = useTranslation();

    // Borne haute du calendrier : LA VEILLE. `BeneficiaireRequest` valide
    // `before:today`, qui refuse la date du jour — offrir aujourd'hui donnerait
    // un jour que le serveur rejette. Calculée une fois par montage.
    const maxDateNaissance = React.useMemo(() => derniereDateNaissanceIso(), []);

    // Type alias explicite : sans lui, `useForm` infère `actif: true` (type
    // littéral) et la case à cocher ne peut plus être décochée.
    type SupplierForm = {
        raison_sociale: string;
        type_personne: string;
        matricule_fiscal: string;
        cin: string;
        /** ISO `aaaa-mm-jj`, la forme qu'échange `FrDateInput`. */
        date_naissance: string;
        adresse: string;
        ville: string;
        code_postal: string;
        email: string;
        telephone: string;
        actif: boolean;
        note: string;
    };

    const form = useForm<SupplierForm>({
        raison_sociale: '',
        type_personne: 'physique',
        matricule_fiscal: '',
        cin: '',
        date_naissance: '',
        adresse: '',
        ville: '',
        code_postal: '',
        email: '',
        telephone: '',
        actif: true,
        note: '',
    });
    const { data, setData, processing, clearErrors } = form;
    const errors = form.errors as Record<string, string | undefined>;

    // Dialogue monté en permanence : ré-hydratation à chaque ouverture.
    React.useEffect(() => {
        if (!open) return;
        clearErrors();
        setData({
            raison_sociale: supplier?.raison_sociale ?? '',
            type_personne: supplier?.type_personne ?? 'physique',
            matricule_fiscal: supplier?.matricule_fiscal ?? '',
            cin: supplier?.cin ?? '',
            date_naissance: isoDateNaissance(supplier?.date_naissance),
            adresse: supplier?.adresse ?? '',
            ville: supplier?.ville ?? '',
            code_postal: supplier?.code_postal ?? '',
            email: supplier?.email ?? '',
            telephone: supplier?.telephone ?? '',
            actif: supplier?.actif ?? true,
            note: supplier?.note ?? '',
        });
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [open, supplier?.id]);

    const submit = (event: React.FormEvent) => {
        event.preventDefault();

        const optionnel = (value: string) => (value.trim() === '' ? null : value.trim());

        form.transform((current) => ({
            raison_sociale: current.raison_sociale.trim(),
            type_personne: current.type_personne,
            matricule_fiscal: optionnel(current.matricule_fiscal),
            cin: optionnel(current.cin),
            adresse: optionnel(current.adresse),
            ville: optionnel(current.ville),
            code_postal: optionnel(current.code_postal),
            email: optionnel(current.email),
            telephone: optionnel(current.telephone),
            actif: current.actif,
            note: optionnel(current.note),

            /*
             * La date de naissance est le SEUL champ envoyé par ABSENCE plutôt
             * que par `null`, et ce n'est pas un raffinement.
             *
             * Tous les autres champs font l'aller-retour : le contrôleur les
             * sérialise, le formulaire les repose, un vide soumis est donc un
             * vide voulu. `date_naissance` NON : un `null` soumis EFFACERAIT
             * une date fiscale que personne n'a demandé à retirer, et rien à
             * l'écran ne distingue « je la vide » de « je n'y ai pas touché ».
             * Clé absente = `fill()` n'y touche pas.
             *
             * Le corollaire assumé : on ne peut pas VIDER une date depuis cet
             * écran. Corriger une date fausse reste possible (on en saisit une
             * autre) ; la remettre à vide demandera la sérialisation côté
             * serveur, et ce cas n'existe pas dans la vraie vie.
             *
             * La condition sur le CIN reproduit celle du serveur : hors de ce
             * cas, le champ n'est pas affiché et son contenu résiduel n'a rien à
             * faire dans la requête.
             */
            ...(estIdentifieeParCin(current.matricule_fiscal, current.cin) && current.date_naissance !== ''
                ? { date_naissance: current.date_naissance }
                : {}),
        }));

        const options = { preserveScroll: true, onSuccess: () => onOpenChange(false) };

        form.patch(route('fournisseurs.update', { supplier: supplier.id }), options);
    };

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent
                className="max-h-[90vh] overflow-y-auto sm:max-w-xl"
                /* Saisie en cours : pas de fermeture sur clic à côté (cf. line-dialog). */
                onInteractOutside={(e) => e.preventDefault()}
            >
                <DialogHeader>
                    <DialogTitle>{t('fournisseurs', 'edit')}</DialogTitle>
                    <DialogDescription>{t('fournisseurs', 'fiscal_incomplete_hint')}</DialogDescription>
                </DialogHeader>

                <form onSubmit={submit} className="flex flex-col gap-4">
                    <div className="flex flex-col gap-1.5">
                        <Label htmlFor="supplier-raison">{t('fournisseurs', 'raison_sociale')}</Label>
                        <Input
                            id="supplier-raison"
                            aria-invalid={!!errors.raison_sociale}
                            value={data.raison_sociale}
                            onChange={(e) => setData('raison_sociale', e.target.value)}
                            maxLength={255}
                        />
                        <FieldError message={errors.raison_sociale} />
                    </div>

                    {/* Identité fiscale.

                        En MODIFICATION : les trois champs d'origine, inchangés.
                        Les fiches en base portent toutes les combinaisons — dont
                        des personnes physiques au matricule fiscal, qui partent
                        chez TEJ en `typeIdentifier` 1 — et leur retirer un champ
                        rendrait ces fiches incorrigibles.

                        En CRÉATION : le type vient du choix de l'étape 1 et ne
                        se rediscute pas ici. Il s'AFFICHE, comme `line-dialog`
                        affiche le type de bénéficiaire figé, et seul le CIN se
                        saisit. Rouvrir le matricule remélangerait les deux
                        parcours que le choix vient de séparer — et enverrait la
                        fiche chez TEJ sous un `typeIdentifier` que l'utilisateur
                        n'a pas demandé. */}
                    <div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
                        <div className="flex flex-col gap-1.5">
                            <Label>{t('fournisseurs', 'type_personne')}</Label>
                            <Select value={data.type_personne} onValueChange={(value) => setData('type_personne', value)}>
                                <SelectTrigger>
                                    <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="morale">{t('fournisseurs', 'type_morale')}</SelectItem>
                                    <SelectItem value="physique">{t('fournisseurs', 'type_physique')}</SelectItem>
                                </SelectContent>
                            </Select>
                            <FieldError message={errors.type_personne} />
                        </div>
                        <div className="flex flex-col gap-1.5">
                            <Label htmlFor="supplier-mf">{t('fournisseurs', 'matricule_fiscal')}</Label>
                            <Input
                                id="supplier-mf"
                                aria-invalid={!!errors.matricule_fiscal}
                                value={data.matricule_fiscal}
                                disabled={data.type_personne === 'physique'}
                                onChange={(e) => setData('matricule_fiscal', e.target.value)}
                                maxLength={40}
                                className="tabular-nums"
                            />
                            <FieldError message={errors.matricule_fiscal} />
                        </div>
                        <div className="flex flex-col gap-1.5">
                            <Label htmlFor="supplier-cin">{t('fournisseurs', 'cin')}</Label>
                            <Input
                                id="supplier-cin"
                                aria-invalid={!!errors.cin}
                                value={data.cin}
                                disabled={data.type_personne === 'morale'}
                                onChange={(e) => setData('cin', e.target.value)}
                                maxLength={20}
                                className="tabular-nums"
                            />
                            <FieldError message={errors.cin} />
                        </div>
                    </div>

                    {/* Date de naissance — CIN uniquement, et seulement quand le
                        CIN est bien ce qui identifie la fiche chez TEJ (aucun
                        matricule fiscal en face). TEJ l'exige pour ce type et
                        pour lui seul : elle départage deux homonymes dans le
                        registre de l'état civil (`validateMadania`).

                        ⚠️ Le calendrier s'ouvre dans un portail Radix, HORS du
                        dialogue. `FrDateInput` porte le `pointer-events-auto`
                        sans lequel il s'afficherait sans se laisser cliquer, et
                        le `onInteractOutside` neutralisé plus haut empêche le
                        choix d'une date de fermer ce formulaire en effaçant
                        toute la saisie (errors.md, 2026-08-04 — les deux défauts
                        se cumulaient, le premier masquant le second). */}
                    {estIdentifieeParCin(data.matricule_fiscal, data.cin) && (
                        <div className="flex flex-col gap-1.5 sm:max-w-xs">
                            <Label>{t('fournisseurs', 'date_naissance', 'Date de naissance')}</Label>
                            <FrDateInput
                                value={data.date_naissance}
                                onChange={(iso) => setData('date_naissance', iso)}
                                max={maxDateNaissance}
                                inputClassName="h-9"
                            />
                            <p className="text-muted-foreground text-xs">
                                {t(
                                    'fournisseurs',
                                    'date_naissance_hint_edit',
                                    "TEJ exige la date de naissance d'un tiers identifié par son CIN. Laissez vide pour conserver celle déjà enregistrée.",
                                )}
                            </p>
                            <FieldError message={errors.date_naissance} />
                        </div>
                    )}

                    <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                        <div className="flex flex-col gap-1.5">
                            <Label htmlFor="supplier-email">{t('fournisseurs', 'email')}</Label>
                            <Input
                                id="supplier-email"
                                aria-invalid={!!errors.email}
                                type="email"
                                value={data.email}
                                onChange={(e) => setData('email', e.target.value)}
                                maxLength={255}
                            />
                            <FieldError message={errors.email} />
                        </div>
                        <div className="flex flex-col gap-1.5">
                            <Label htmlFor="supplier-tel">{t('fournisseurs', 'telephone')}</Label>
                            <Input
                                id="supplier-tel"
                                aria-invalid={!!errors.telephone}
                                value={data.telephone}
                                onChange={(e) => setData('telephone', e.target.value)}
                                maxLength={40}
                            />
                            <FieldError message={errors.telephone} />
                        </div>
                    </div>

                    <div className="grid grid-cols-1 gap-3 sm:grid-cols-4">
                        <div className="flex flex-col gap-1.5 sm:col-span-2">
                            <Label htmlFor="supplier-adresse">{t('fournisseurs', 'adresse')}</Label>
                            <Input
                                id="supplier-adresse"
                                aria-invalid={!!errors.adresse}
                                value={data.adresse}
                                onChange={(e) => setData('adresse', e.target.value)}
                                maxLength={255}
                            />
                            <FieldError message={errors.adresse} />
                        </div>
                        <div className="flex flex-col gap-1.5">
                            <Label htmlFor="supplier-ville">{t('fournisseurs', 'ville')}</Label>
                            <Input
                                id="supplier-ville"
                                aria-invalid={!!errors.ville}
                                value={data.ville}
                                onChange={(e) => setData('ville', e.target.value)}
                                maxLength={100}
                            />
                            <FieldError message={errors.ville} />
                        </div>
                        <div className="flex flex-col gap-1.5">
                            <Label htmlFor="supplier-cp">{t('fournisseurs', 'code_postal')}</Label>
                            <Input
                                id="supplier-cp"
                                aria-invalid={!!errors.code_postal}
                                value={data.code_postal}
                                onChange={(e) => setData('code_postal', e.target.value)}
                                maxLength={20}
                                className="tabular-nums"
                            />
                            <FieldError message={errors.code_postal} />
                        </div>
                    </div>

                    <div className="flex items-center gap-2">
                        <Checkbox id="supplier-actif" checked={data.actif} onCheckedChange={(checked) => setData('actif', checked === true)} />
                        <Label htmlFor="supplier-actif">{t('fournisseurs', 'actif')}</Label>
                    </div>

                    <div className="flex flex-col gap-1.5">
                        <Label htmlFor="supplier-note">{t('fournisseurs', 'note')}</Label>
                        <Textarea id="supplier-note" value={data.note} onChange={(e) => setData('note', e.target.value)} rows={2} maxLength={1000} />
                        <FieldError message={errors.note} />
                    </div>

                    {/* Rien à annoncer : une modification n'a jamais rien envoyé
                        à la DGI, et ce formulaire ne crée plus. La mention
                        « envoyée au registre des tiers » vivait ici pour la seule
                        branche de création, retirée le 2026-08-17. */}

                    <DialogFooter>
                        <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                            {t('fournisseurs', 'cancel')}
                        </Button>
                        <Button type="submit" disabled={processing}>
                            {t('fournisseurs', 'save')}
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}

function FieldError({ message }: { message?: string }) {
    if (!message) return null;
    return <p className="text-destructive text-xs">{message}</p>;
}
