import InputError from '@/components/input-error';
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 axios from 'axios';
import { Building2, Search, User, UserRound } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import type { ClientType, FactureForm, IdentifiantType, SuggestionClient } from '../types';

type ChampsClient = Pick<
    FactureForm,
    'client_type' | 'client_ref_id' | 'client_nom' | 'client_adresse' | 'client_matricule_fiscal' | 'client_identifiant_type' | 'client_email'
>;

/** Libellé imprimé devant l'identifiant, et exemple de saisie. */
const IDENTIFIANTS: Record<IdentifiantType, { libelle: string; exemple: string }> = {
    mf: { libelle: 'MF', exemple: '1234567A/P/M/000' },
    cin: { libelle: 'CIN', exemple: '01234567' },
    passeport: { libelle: 'Passeport', exemple: 'X1234567' },
    // Personne physique sans identifiant : rien ne s'imprime (code de la TVA, art. 18 § II).
    aucun: { libelle: 'Particulier', exemple: '' },
};

interface Props {
    valeur: ChampsClient;
    onChange: (champs: Partial<ChampsClient>) => void;
    erreurs: Partial<Record<keyof ChampsClient, string>>;
    disabled?: boolean;
}

const ICONES: Record<ClientType, typeof User> = {
    proprietaire: Building2,
    client: UserRound,
    libre: User,
};

/**
 * Destinataire de la facture. On cherche parmi les clients déjà facturés, les
 * propriétaires et les voyageurs ; choisir une suggestion recopie son identité
 * dans les champs, qui restent modifiables — la facture garde une COPIE figée,
 * elle ne suit pas la fiche d'origine.
 *
 * Liste de suggestions en simple bloc positionné, pas en Popover : elle vit
 * dans une page qui défile, et les popovers Radix y ont déjà posé problème
 * sous Safari.
 */
export function ClientField({ valeur, onChange, erreurs, disabled }: Props) {
    const { t } = useTranslation();
    const [recherche, setRecherche] = useState('');
    const [suggestions, setSuggestions] = useState<SuggestionClient[]>([]);
    const [ouvert, setOuvert] = useState(false);
    const requete = useRef(0);

    useEffect(() => {
        if (recherche.trim().length < 2) {
            setSuggestions([]);
            return;
        }
        const numero = ++requete.current;
        const minuteur = window.setTimeout(() => {
            axios
                .get<SuggestionClient[]>(route('factures.clients'), { params: { q: recherche } })
                .then((r) => {
                    if (numero === requete.current) setSuggestions(r.data);
                })
                .catch(() => {
                    if (numero === requete.current) setSuggestions([]);
                });
        }, 250);
        return () => window.clearTimeout(minuteur);
    }, [recherche]);

    const choisir = (s: SuggestionClient) => {
        onChange({
            client_type: s.type,
            client_ref_id: s.id,
            client_nom: s.nom,
            client_adresse: s.adresse,
            client_matricule_fiscal: s.matricule_fiscal,
            client_identifiant_type: s.identifiant_type ?? 'mf',
            client_email: s.email,
        });
        setRecherche('');
        setOuvert(false);
    };

    return (
        <div className="grid gap-3">
            {!disabled && (
                <div className="relative">
                    <Search className="pointer-events-none absolute top-1/2 left-2.5 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                    <Input
                        value={recherche}
                        onChange={(e) => {
                            setRecherche(e.target.value);
                            setOuvert(true);
                        }}
                        onFocus={() => setOuvert(true)}
                        onBlur={() => window.setTimeout(() => setOuvert(false), 150)}
                        onKeyDown={(e) => {
                            if (e.key === 'Escape') setOuvert(false);
                            if (e.key === 'Enter' && suggestions[0]) {
                                e.preventDefault();
                                choisir(suggestions[0]);
                            }
                        }}
                        placeholder={t('factures', 'editeur.client_recherche', 'Chercher un propriétaire, un voyageur, une société déjà facturée…')}
                        className="pl-8"
                        aria-label={t('factures', 'editeur.client_recherche_label', 'Chercher un client')}
                    />
                    {ouvert && suggestions.length > 0 && (
                        <ul className="absolute z-50 mt-1 max-h-72 w-full overflow-auto rounded-md border bg-popover p-1 shadow-lg" role="listbox">
                            {suggestions.map((s, i) => {
                                const Icone = ICONES[s.type] ?? User;
                                return (
                                    <li key={`${s.type}-${s.id ?? s.nom}-${i}`}>
                                        <button
                                            type="button"
                                            role="option"
                                            aria-selected={false}
                                            onMouseDown={(e) => e.preventDefault()}
                                            onClick={() => choisir(s)}
                                            className="flex w-full items-start gap-2 rounded-sm px-2 py-1.5 text-left hover:bg-accent"
                                        >
                                            <Icone className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
                                            <span className="min-w-0 flex-1">
                                                <span className="block truncate text-sm font-medium">{s.nom}</span>
                                                <span className="block truncate text-xs text-muted-foreground">
                                                    {[s.detail, s.matricule_fiscal, s.email].filter(Boolean).join(' · ')}
                                                </span>
                                            </span>
                                        </button>
                                    </li>
                                );
                            })}
                        </ul>
                    )}
                    {ouvert && recherche.trim().length >= 2 && suggestions.length === 0 && (
                        <p className="mt-1 text-xs text-muted-foreground">
                            {t('factures', 'editeur.client_aucun', 'Aucune fiche trouvée — saisissez le client directement ci-dessous.')}
                        </p>
                    )}
                </div>
            )}

            <div className="grid gap-3 sm:grid-cols-2">
                <div className="grid gap-1.5 sm:col-span-2">
                    <Label htmlFor="client_nom">{t('factures', 'editeur.client_nom', 'Nom ou raison sociale')}</Label>
                    <Input
                        id="client_nom"
                        value={valeur.client_nom}
                        disabled={disabled}
                        onChange={(e) => onChange({ client_nom: e.target.value, client_type: valeur.client_type ?? 'libre' })}
                        placeholder="KASBAHOST"
                    />
                    <InputError message={erreurs.client_nom} />
                </div>
                <div className="grid gap-1.5 sm:col-span-2">
                    <Label htmlFor="client_adresse">{t('factures', 'editeur.client_adresse', 'Adresse')}</Label>
                    <Textarea
                        id="client_adresse"
                        rows={2}
                        value={valeur.client_adresse ?? ''}
                        disabled={disabled}
                        onChange={(e) => onChange({ client_adresse: e.target.value || null })}
                        placeholder={'Rue du Lac Léman\n1053 Tunis'}
                    />
                    <InputError message={erreurs.client_adresse} />
                </div>
                <div className="grid gap-1.5">
                    <Label htmlFor="client_mf">{t('factures', 'editeur.client_identifiant', 'Identifiant')}</Label>
                    <div className="flex gap-2">
                        <Select
                            value={valeur.client_identifiant_type ?? 'mf'}
                            disabled={disabled}
                            onValueChange={(v) =>
                                // « Particulier » n'imprime rien : la valeur restée dans le champ part avec lui.
                                onChange(v === 'aucun' ? { client_identifiant_type: 'aucun', client_matricule_fiscal: null } : { client_identifiant_type: v as IdentifiantType })
                            }
                        >
                            <SelectTrigger className="w-32 shrink-0" aria-label={t('factures', 'editeur.client_identifiant_type', "Nature de l'identifiant")}>
                                <SelectValue />
                            </SelectTrigger>
                            <SelectContent>
                                {(Object.keys(IDENTIFIANTS) as IdentifiantType[]).map((cle) => (
                                    <SelectItem key={cle} value={cle}>
                                        {cle === 'aucun' ? t('factures', 'editeur.identifiant_aucun', 'Particulier') : IDENTIFIANTS[cle].libelle}
                                    </SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                        <Input
                            id="client_mf"
                            value={valeur.client_matricule_fiscal ?? ''}
                            disabled={disabled || valeur.client_identifiant_type === 'aucun'}
                            onChange={(e) => onChange({ client_matricule_fiscal: e.target.value || null })}
                            placeholder={
                                valeur.client_identifiant_type === 'aucun'
                                    ? t('factures', 'editeur.identifiant_aucun_aide', 'Sans identifiant — personne physique')
                                    : IDENTIFIANTS[valeur.client_identifiant_type ?? 'mf'].exemple
                            }
                        />
                    </div>
                    <InputError message={erreurs.client_matricule_fiscal} />
                </div>
                <div className="grid gap-1.5">
                    <Label htmlFor="client_email">{t('factures', 'editeur.client_email', 'E-mail')}</Label>
                    <Input
                        id="client_email"
                        type="email"
                        value={valeur.client_email ?? ''}
                        disabled={disabled}
                        onChange={(e) => onChange({ client_email: e.target.value || null })}
                        placeholder="comptabilite@societe.tn"
                    />
                    <InputError message={erreurs.client_email} />
                </div>
            </div>
        </div>
    );
}
