import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { ColumnDef } from '@tanstack/react-table';
import { AlertTriangle, Lock, PencilIcon, Send, Trash2 } from 'lucide-react';
import type { TypePersonne } from '../retenue/types';
import { effetSuppression, type BlocSuppression } from './suppression';
import { dateNaissanceRequise, motifIndisponibiliteHorsDate, type FicheTej, type TejEcritureProp } from './tej';
import { TejEtatBadge } from './tej-etat-badge';

/**
 * Bénéficiaire tel que sérialisé par le contrôleur de l'écran /fournisseurs.
 *
 * L'écran montre TOUTES les fiches par défaut. Le filtre « Afficher » sépare
 * les deux moitiés : les fiches FOURNISSEUR, sans `user_id`, saisies sur cet
 * écran ; et celles adossées à un propriétaire du parc, dont l'IDENTITÉ se
 * saisit depuis /owners mais dont `activite` et `date_naissance` n'existent
 * qu'ici. Plus de taux par défaut — le taux se choisit ligne par ligne dans la
 * déclaration.
 */
export interface SupplierRow {
    id: number;
    raison_sociale: string;
    type_personne: TypePersonne;
    matricule_fiscal: string | null;
    cin: string | null;
    adresse: string | null;
    ville: string | null;
    code_postal: string | null;
    email: string | null;
    telephone: string | null;
    actif: boolean;
    note: string | null;
    identite_complete: boolean;

    /**
     * Date de naissance de la fiche. TEJ l'exige d'un tiers identifié par son
     * CIN, et de lui seul.
     *
     * SÉRIALISÉE depuis le 2026-08-12 (`aaaa-mm-jj`) — elle ne l'était pas
     * jusque-là, et c'est ce qui obligeait `supplier-dialog` à ne jamais
     * envoyer `date_naissance: null` : le champ s'ouvrait vide sur une fiche
     * qui en portait une, et un vide soumis l'aurait effacée. Cette précaution
     * reste en place tant que ce formulaire-là n'est pas repris ; le formulaire
     * propriétaire, lui, peut s'appuyer sur la valeur reçue.
     *
     * `aaaa-mm-jj`, horodatage ISO et `jj/mm/aaaa` sont tous acceptés en entrée
     * (voir `isoDateNaissance`).
     */
    date_naissance?: string | null;

    /**
     * Activité déclarée — le métier connu de la DGI. FACULTATIVE : le XSD la
     * donne `minOccurs="0"` et 39 des 45 personnes physiques du registre de TEJ
     * n'en portent aucune. Absente de `users`, donc cet écran est le seul
     * endroit où elle se saisit sur une fiche propriétaire.
     */
    activite?: string | null;

    /**
     * Le compte du manager dont la fiche tient son identité. `null` = tiers pur.
     *
     * Sa présence change ce que le formulaire autorise : raison sociale,
     * identifiants et adresse deviennent en lecture seule, parce que
     * `beneficiairePourProprietaire()` les réécrit depuis `users` à chaque
     * rafraîchissement. Les afficher éditables promettrait une saisie que le
     * prochain enregistrement de ligne écraserait.
     */
    proprietaire?: { id: number; nom: string } | null;

    /**
     * État TEJ de la fiche — voir le contrat détaillé dans `./tej.ts`.
     *
     * Marqué OPTIONNEL à dessein : la sérialisation vit dans un fichier PHP
     * écrit en parallèle de cet écran. Tant qu'elle n'est pas livrée, l'absence
     * du bloc doit rendre le bouton inerte et l'état illisible — pas produire
     * un envoi construit sur des `undefined`.
     */
    tej?: FicheTej;

    /**
     * De quoi ANNONCER l'effet d'une suppression — voir le contrat détaillé dans
     * `./suppression.ts`.
     *
     * OPTIONNEL pour la même raison que `tej` : le contrôleur qui le sérialise
     * est écrit en parallèle de cet écran. Son absence ÉTEINT le bouton
     * (`effetSuppression` rend alors 'inconnu') — c'est le défaut sûr : on
     * n'offre pas un effacement dont on ne sait pas annoncer l'effet.
     */
    suppression?: BlocSuppression;
}

// Le troisième paramètre est le repli affiché tant que les catalogues
// `lang/fr/fournisseurs.php` et `lang/en/fournisseurs.php` n'ont pas les clés `tej_…`.
type Translate = (namespace: string, key: string, fallback?: string) => string;

interface Handlers {
    t: Translate;
    onEdit: (supplier: SupplierRow) => void;
    onDelete: (supplier: SupplierRow) => void;
    /** Ouvre la confirmation d'envoi. Ne poste RIEN par lui-même. */
    onSendTej: (supplier: SupplierRow) => void;
    /** Droits du viewer — les routes sont gardées côté serveur, l'UI suit. */
    can: { update: boolean; delete: boolean; tej: boolean };
    /** Verrou serveur d'écriture vers TEJ, prop `tej` de la page. */
    ecriture: TejEcritureProp;
}

/**
 * Colonnes de la table des fournisseurs.
 *
 * Une identité fiscale incomplète (personne morale sans matricule, personne
 * physique sans CIN) est signalée ici : c'est ce qui bloquera la clôture de la
 * déclaration de retenue.
 */
export const getColumns = ({ t, onEdit, onDelete, onSendTej, can, ecriture }: Handlers): ColumnDef<SupplierRow>[] => [
    {
        accessorKey: 'raison_sociale',
        header: t('fournisseurs', 'raison_sociale'),
        cell: ({ row }) => (
            <div className="flex items-center gap-1.5">
                <span className="font-medium">{row.original.raison_sociale}</span>
                {/* D'OÙ la fiche tient son identité. Sans ce repère, deux
                    lignes visuellement identiques n'ouvrent pas le même
                    formulaire — l'une laisse corriger la raison sociale,
                    l'autre non — et rien à l'écran ne l'explique. */}
                {row.original.proprietaire != null && (
                    <Tooltip>
                        <TooltipTrigger asChild>
                            <Badge variant="outline" className="border-sky-300 bg-sky-50 text-[10px] font-normal text-sky-800">
                                {t('fournisseurs', 'proprietaire', 'Propriétaire')}
                            </Badge>
                        </TooltipTrigger>
                        <TooltipContent>{t('fournisseurs', 'identite_depuis_owners')}</TooltipContent>
                    </Tooltip>
                )}
                {!row.original.identite_complete && (
                    <Tooltip>
                        <TooltipTrigger asChild>
                            <span className="text-amber-600">
                                <AlertTriangle className="h-4 w-4" />
                            </span>
                        </TooltipTrigger>
                        <TooltipContent>{t('fournisseurs', 'fiscal_incomplete_hint')}</TooltipContent>
                    </Tooltip>
                )}
            </div>
        ),
    },
    {
        accessorKey: 'type_personne',
        header: t('fournisseurs', 'type_personne'),
        cell: ({ row }) => (
            <span className="text-xs">
                {row.original.type_personne === 'morale' ? t('fournisseurs', 'type_morale') : t('fournisseurs', 'type_physique')}
            </span>
        ),
    },
    {
        accessorKey: 'matricule_fiscal',
        header: t('fournisseurs', 'matricule_fiscal'),
        cell: ({ row }) => <span className="tabular-nums">{row.original.matricule_fiscal ?? '—'}</span>,
    },
    {
        accessorKey: 'cin',
        header: t('fournisseurs', 'cin'),
        cell: ({ row }) => <span className="tabular-nums">{row.original.cin ?? '—'}</span>,
    },
    {
        accessorKey: 'telephone',
        header: t('fournisseurs', 'telephone'),
        cell: ({ row }) => (
            <div className="flex flex-col text-xs leading-tight">
                <span>{row.original.telephone ?? '—'}</span>
                {row.original.email && <span className="text-muted-foreground">{row.original.email}</span>}
            </div>
        ),
    },
    {
        accessorKey: 'actif',
        header: t('fournisseurs', 'actif'),
        cell: ({ row }) =>
            row.original.actif ? (
                <Badge variant="outline" className="border-emerald-300 bg-emerald-50 text-emerald-800">
                    {t('fournisseurs', 'actif')}
                </Badge>
            ) : (
                <Badge variant="outline">{t('fournisseurs', 'inactif')}</Badge>
            ),
    },
    {
        id: 'tej',
        header: t('fournisseurs', 'tej', 'TEJ'),
        cell: ({ row }) => <TejEtatBadge fiche={row.original.tej} />,
    },
    {
        id: 'actions',
        header: t('fournisseurs', 'actions'),
        cell: ({ row }) => (
            <div className="flex items-center justify-end gap-1">
                {can.tej && <TejSendButton supplier={row.original} onSendTej={onSendTej} ecriture={ecriture} t={t} />}
                {can.update && (
                    <Button
                        type="button"
                        variant="ghost"
                        size="icon"
                        className="h-8 w-8"
                        onClick={() => onEdit(row.original)}
                        aria-label={t('fournisseurs', 'edit')}
                    >
                        <PencilIcon className="h-3.5 w-3.5" />
                    </Button>
                )}
                {/* LE BOUTON N'APPARAÎT QUE SI LA SUPPRESSION EST DÉFINITIVE.
                    C'est-à-dire : aucune ligne de retenue ne cite la fiche.
                    Dès qu'une seule la cite, le serveur ne l'efface pas — il la
                    masque — et proposer « Supprimer » pour obtenir un masquage
                    est un bouton qui ne fait pas ce qu'il dit. Une fiche qu'on
                    ne veut plus voir se décoche par « Actif », dans son
                    formulaire.

                    Le cas 'inconnu' (bloc absent, déploiement partiel) éteint
                    aussi le bouton : c'est le défaut sûr.

                    ⚠️ La condition ne regarde PLUS le type de fiche. Une fiche
                    propriétaire se supprime comme une autre : sans ligne qui la
                    cite, il n'y a rien à orpheliner, et
                    `beneficiairePourProprietaire()` la recréera à la demande. */}
                {can.delete && effetSuppression(row.original.suppression) === 'definitive' && (
                    <Button
                        type="button"
                        variant="ghost"
                        size="icon"
                        className="text-destructive h-8 w-8"
                        onClick={() => onDelete(row.original)}
                        aria-label={t('fournisseurs', 'delete')}
                    >
                        <Trash2 className="h-3.5 w-3.5" />
                    </Button>
                )}
            </div>
        ),
    },
];

/**
 * Déclencheur de l'envoi vers TEJ — il OUVRE la confirmation, il ne poste rien.
 *
 * Indisponible, il reste VISIBLE et devient un cadenas : le verrou d'écriture
 * du serveur, une identité fiscale incomplète ou un état TEJ non fourni sont
 * des informations utiles à l'utilisateur, alors que masquer le bouton ne lui
 * apprendrait rien. Le motif exact est dans l'infobulle.
 *
 * Le bouton désactivé porte `pointer-events: none` (variante `Button`) : sans
 * l'enveloppe `<span>`, il n'émettrait aucun survol et l'infobulle — donc le
 * motif — resterait inatteignable exactement dans le cas où elle sert.
 *
 * Une fiche CIN à qui il ne manque QUE la date de naissance n'est pas bloquée
 * ici : c'est le dialogue qui la recueille, et l'éteindre laissait l'utilisateur
 * devant un motif qu'aucun écran ne lui permettait de lever.
 */
function TejSendButton({
    supplier,
    onSendTej,
    ecriture,
    t,
}: {
    supplier: SupplierRow;
    onSendTej: (supplier: SupplierRow) => void;
    ecriture: TejEcritureProp;
    t: Translate;
}) {
    const motif = motifIndisponibiliteHorsDate(supplier.tej, ecriture, t);
    const libelle = dateNaissanceRequise(supplier.tej)
        ? t('fournisseurs', 'tej_send_avec_date', 'Envoyer vers TEJ — la date de naissance sera demandée')
        : t('fournisseurs', 'tej_send', 'Envoyer vers TEJ');

    return (
        <Tooltip>
            <TooltipTrigger asChild>
                <span className="inline-flex">
                    <Button
                        type="button"
                        variant="ghost"
                        size="icon"
                        className="h-8 w-8"
                        disabled={motif !== null}
                        onClick={() => onSendTej(supplier)}
                        aria-label={libelle}
                    >
                        {motif !== null ? <Lock className="h-3.5 w-3.5" /> : <Send className="h-3.5 w-3.5" />}
                    </Button>
                </span>
            </TooltipTrigger>
            <TooltipContent>{motif ?? libelle}</TooltipContent>
        </Tooltip>
    );
}
