import { Button } from '@/components/ui/button';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
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 { ArrowLeftRight, ChevronDown, Link2, Plus, Trash2 } from 'lucide-react';
import { Fragment } from 'react';
import { useMediaQuery } from 'usehooks-ts';
import { decimales, fmtDate, fmtMontant, fmtNombre } from '../format';
import type { Devise, FactureOptions, LigneForm } from '../types';
import { NumberInput } from './number-input';

interface Props {
    lignes: LigneForm[];
    onChange: (lignes: LigneForm[]) => void;
    /** Total HT de chaque ligne, calculé par le serveur (null tant que l'aperçu charge). */
    totaux: number[] | null;
    devise: Devise;
    options: FactureOptions;
    erreurs: Record<string, string>;
    disabled?: boolean;
}

export function ligneVide(options: FactureOptions): LigneForm {
    return {
        reference: null,
        designation: '',
        quantite: 1,
        prix_unitaire_ht: 0,
        remise_pct: 0,
        taux_tva: options.tva_defaut,
        source_type: null,
        source_id: null,
    };
}

/**
 * Ids des champs d'une ligne — la fenêtre d'émission y amène le curseur
 * (« Chaque ligne doit avoir une désignation » → la première vide).
 */
export const idDesignation = (i: number) => `ligne-designation-${i}`;
export const idPrix = (i: number) => `ligne-pu-${i}`;
export const ID_AJOUTER_LIGNE = 'ligne-ajouter';

/** Un PU retouché ne s'explique plus par « montant × taux » : la conversion part avec (le serveur fait de même). */
const SANS_CONVERSION = { montant_origine: null, devise_origine: null, taux_change: null, taux_date: null } as const;

/** La ligne ouvre-t-elle un nouveau groupe (versement d'un relevé bancaire) ? */
const ouvreGroupe = (lignes: LigneForm[], i: number) => Boolean(lignes[i].groupe) && lignes[i].groupe !== lignes[i - 1]?.groupe;

/**
 * Les lignes de la facture. Le total de chaque ligne vient du serveur : ici on
 * ne multiplie rien, on saisit.
 *
 * Deux mises en page, UNE seule rendue à la fois (et non deux cachées en CSS) :
 * un tableau à partir de 768 px, des cartes en dessous. Rendre les deux
 * dupliquerait les ids des champs, et le curseur envoyé par la fenêtre
 * d'émission tomberait dans la version masquée.
 */
export function LinesEditor({ lignes, onChange, totaux, devise, options, erreurs, disabled }: Props) {
    const { t } = useTranslation();
    const bureau = useMediaQuery('(min-width: 768px)');
    const d = decimales(devise);

    const modifier = (index: number, champs: Partial<LigneForm>) => onChange(lignes.map((l, i) => (i === index ? { ...l, ...champs } : l)));
    const supprimer = (index: number) => onChange(lignes.filter((_, i) => i !== index));
    const ajouter = (ligne: LigneForm) => onChange([...lignes, ligne]);

    const erreurDe = (i: number) =>
        erreurs[`lignes.${i}.prix_unitaire_ht`] ??
        erreurs[`lignes.${i}.quantite`] ??
        erreurs[`lignes.${i}.remise_pct`] ??
        erreurs[`lignes.${i}.taux_tva`] ??
        erreurs[`lignes.${i}.designation`];

    const L = {
        reference: t('factures', 'editeur.col_reference', 'Réf.'),
        designation: t('factures', 'editeur.col_designation', 'Désignation'),
        quantite: t('factures', 'editeur.col_quantite', 'Qté'),
        pu: t('factures', 'editeur.col_pu', 'PU HT'),
        remise: t('factures', 'editeur.col_remise', 'Remise %'),
        tva: t('factures', 'editeur.col_tva', 'TVA'),
        total: t('factures', 'editeur.col_total', 'Total HT'),
        supprimer: t('factures', 'editeur.supprimer_ligne', 'Supprimer la ligne'),
    };

    const champs = (ligne: LigneForm, i: number) => ({
        reference: (
            <Input
                value={ligne.reference ?? ''}
                disabled={disabled}
                onChange={(e) => modifier(i, { reference: e.target.value || null })}
                className="font-mono text-xs"
                aria-label={L.reference}
            />
        ),
        designation: (
            <>
                <Textarea
                    id={idDesignation(i)}
                    value={ligne.designation}
                    disabled={disabled}
                    rows={Math.min(4, Math.max(1, Math.ceil(ligne.designation.length / 70)))}
                    onChange={(e) => modifier(i, { designation: e.target.value })}
                    className="min-h-9 resize-y text-sm"
                    aria-label={L.designation}
                />
                {ligne.montant_origine != null && ligne.taux_change != null && ligne.devise_origine && (
                    <span className="text-muted-foreground mt-1 flex items-center gap-1 text-[11px] tabular-nums">
                        <ArrowLeftRight className="h-3 w-3" />
                        {t('factures', 'editeur.conversion', '{montant} {devise} × {taux} (BCT {date})')
                            .replace('{montant}', fmtNombre(ligne.montant_origine, 2))
                            .replace('{devise}', ligne.devise_origine)
                            .replace('{taux}', fmtNombre(ligne.taux_change, 4))
                            .replace('{date}', fmtDate(ligne.taux_date))}
                    </span>
                )}
                {ligne.source_type && (
                    <span className="text-muted-foreground mt-1 inline-flex items-center gap-1 text-[11px]">
                        <Link2 className="h-3 w-3" />
                        {ligne.source_type === 'commission'
                            ? t('factures', 'editeur.source_commission', 'Commission de la réservation n° {id}').replace(
                                  '{id}',
                                  String(ligne.source_id),
                              )
                            : t('factures', 'editeur.source_reservation', 'Séjour de la réservation n° {id}').replace(
                                  '{id}',
                                  String(ligne.source_id),
                              )}
                    </span>
                )}
            </>
        ),
        quantite: (
            <NumberInput
                value={ligne.quantite}
                decimales={3}
                disabled={disabled}
                onChange={(v) => modifier(i, { quantite: v })}
                aria-label={L.quantite}
            />
        ),
        pu: (
            <NumberInput
                id={idPrix(i)}
                value={ligne.prix_unitaire_ht}
                decimales={Math.max(d, 3)}
                disabled={disabled}
                onChange={(v) => modifier(i, { prix_unitaire_ht: v, ...(ligne.taux_change != null ? SANS_CONVERSION : {}) })}
                aria-label={L.pu}
            />
        ),
        remise: (
            <NumberInput
                value={ligne.remise_pct}
                decimales={2}
                disabled={disabled}
                onChange={(v) => modifier(i, { remise_pct: v })}
                aria-label={L.remise}
            />
        ),
        tva: (
            <Select value={String(ligne.taux_tva)} disabled={disabled} onValueChange={(v) => modifier(i, { taux_tva: Number(v) })}>
                <SelectTrigger className="justify-end tabular-nums" aria-label={L.tva}>
                    <SelectValue />
                </SelectTrigger>
                <SelectContent>
                    {options.taux_tva.map((taux) => (
                        <SelectItem key={taux} value={String(taux)}>
                            {taux} %
                        </SelectItem>
                    ))}
                </SelectContent>
            </Select>
        ),
        total: totaux && totaux[i] !== undefined ? fmtMontant(totaux[i], devise) : '…',
        supprimer: (
            <Button
                type="button"
                variant="ghost"
                size="icon"
                className="text-muted-foreground h-9 w-9 hover:text-rose-600"
                onClick={() => supprimer(i)}
                aria-label={`${L.supprimer} ${i + 1}`}
            >
                <Trash2 className="h-4 w-4" />
            </Button>
        ),
    });

    const vide = (
        <p className="text-muted-foreground px-3 py-6 text-center text-sm">
            {t('factures', 'editeur.aucune_ligne', 'Aucune ligne — ajoutez-en une ci-dessous.')}
        </p>
    );

    return (
        <div className="grid gap-3">
            {bureau ? (
                <div className="overflow-x-auto rounded-lg border">
                    <table className="w-full min-w-[820px] text-sm">
                        <thead className="bg-muted/60 text-muted-foreground text-left text-xs font-medium tracking-wide uppercase">
                            <tr>
                                <th className="w-8 px-2 py-2">#</th>
                                <th className="w-24 px-2 py-2">{L.reference}</th>
                                <th className="px-2 py-2">{L.designation}</th>
                                <th className="w-20 px-2 py-2 text-right">{L.quantite}</th>
                                <th className="w-28 px-2 py-2 text-right">{L.pu}</th>
                                <th className="w-20 px-2 py-2 text-right">{L.remise}</th>
                                <th className="w-24 px-2 py-2 text-right">{L.tva}</th>
                                <th className="w-32 px-2 py-2 text-right">{L.total}</th>
                                {!disabled && <th className="w-10 px-1 py-2" aria-label={L.supprimer} />}
                            </tr>
                        </thead>
                        <tbody>
                            {lignes.length === 0 && (
                                <tr>
                                    <td colSpan={9}>{vide}</td>
                                </tr>
                            )}
                            {lignes.map((ligne, i) => {
                                const c = champs(ligne, i);
                                const erreur = erreurDe(i);
                                return (
                                    <Fragment key={i}>
                                        {ouvreGroupe(lignes, i) && (
                                            <tr className="bg-muted/40 border-t">
                                                <td colSpan={9} className="text-foreground/80 px-3 py-1.5 text-xs font-medium">
                                                    {ligne.groupe}
                                                </td>
                                            </tr>
                                        )}
                                        <tr className="border-t align-top">
                                            <td className="text-muted-foreground px-2 py-2 pt-4 text-xs tabular-nums">{i + 1}</td>
                                            <td className="px-2 py-2">{c.reference}</td>
                                            <td className="px-2 py-2">
                                                {c.designation}
                                                {erreur && <p className="mt-1 text-xs text-rose-600">{erreur}</p>}
                                            </td>
                                            <td className="px-2 py-2">{c.quantite}</td>
                                            <td className="px-2 py-2">{c.pu}</td>
                                            <td className="px-2 py-2">{c.remise}</td>
                                            <td className="px-2 py-2">{c.tva}</td>
                                            <td className="px-2 py-2 pt-4 text-right font-medium whitespace-nowrap tabular-nums">{c.total}</td>
                                            {!disabled && <td className="px-1 py-2">{c.supprimer}</td>}
                                        </tr>
                                    </Fragment>
                                );
                            })}
                        </tbody>
                    </table>
                </div>
            ) : (
                <div className="grid gap-3">
                    {lignes.length === 0 && <div className="rounded-lg border">{vide}</div>}
                    {lignes.map((ligne, i) => {
                        const c = champs(ligne, i);
                        const erreur = erreurDe(i);
                        return (
                            <Fragment key={i}>
                                {ouvreGroupe(lignes, i) && <p className="text-foreground/80 px-1 pt-1 text-xs font-medium">{ligne.groupe}</p>}
                                <div className="grid gap-3 rounded-lg border p-3">
                                    <div className="flex items-center justify-between gap-2">
                                        <span className="text-muted-foreground text-xs font-medium">
                                            {t('factures', 'editeur.ligne_n', 'Ligne {n}').replace('{n}', String(i + 1))}
                                        </span>
                                        <span className="flex items-center gap-1">
                                            <span className="font-semibold tabular-nums">{c.total}</span>
                                            {!disabled && c.supprimer}
                                        </span>
                                    </div>
                                    <div className="grid gap-1.5">
                                        <Label htmlFor={idDesignation(i)} className="text-muted-foreground text-xs">
                                            {L.designation}
                                        </Label>
                                        {c.designation}
                                        {erreur && <p className="text-xs text-rose-600">{erreur}</p>}
                                    </div>
                                    <div className="grid grid-cols-2 gap-3">
                                        <div className="grid gap-1.5">
                                            <span className="text-muted-foreground text-xs">{L.reference}</span>
                                            {c.reference}
                                        </div>
                                        <div className="grid gap-1.5">
                                            <span className="text-muted-foreground text-xs">{L.pu}</span>
                                            {c.pu}
                                        </div>
                                        <div className="grid gap-1.5">
                                            <span className="text-muted-foreground text-xs">{L.quantite}</span>
                                            {c.quantite}
                                        </div>
                                        <div className="grid gap-1.5">
                                            <span className="text-muted-foreground text-xs">{L.remise}</span>
                                            {c.remise}
                                        </div>
                                        <div className="col-span-2 grid gap-1.5">
                                            <span className="text-muted-foreground text-xs">{L.tva}</span>
                                            {c.tva}
                                        </div>
                                    </div>
                                </div>
                            </Fragment>
                        );
                    })}
                </div>
            )}

            {!disabled && (
                <div className="flex flex-wrap items-center gap-2">
                    <Button id={ID_AJOUTER_LIGNE} type="button" variant="outline" size="sm" onClick={() => ajouter(ligneVide(options))}>
                        <Plus className="mr-1 h-4 w-4" />
                        {t('factures', 'editeur.ajouter_ligne', 'Ajouter une ligne')}
                    </Button>
                    {options.articles.length > 0 && (
                        <DropdownMenu modal={false}>
                            <DropdownMenuTrigger asChild>
                                <Button type="button" variant="ghost" size="sm">
                                    {t('factures', 'editeur.depuis_article', 'Depuis un article')}
                                    <ChevronDown className="ml-1 h-4 w-4" />
                                </Button>
                            </DropdownMenuTrigger>
                            <DropdownMenuContent align="start">
                                <DropdownMenuLabel className="text-muted-foreground text-xs">
                                    {t('factures', 'editeur.articles', 'Articles')}
                                </DropdownMenuLabel>
                                {options.articles.map((a) => (
                                    <DropdownMenuItem
                                        key={a.reference}
                                        onSelect={() =>
                                            ajouter({
                                                ...ligneVide(options),
                                                reference: a.reference,
                                                designation: a.designation,
                                                taux_tva: a.taux_tva,
                                            })
                                        }
                                    >
                                        <span className="text-muted-foreground w-16 font-mono text-xs">{a.reference}</span>
                                        {a.designation}
                                    </DropdownMenuItem>
                                ))}
                            </DropdownMenuContent>
                        </DropdownMenu>
                    )}
                    {erreurs.lignes && <p className="text-sm text-rose-600">{erreurs.lignes}</p>}
                </div>
            )}
        </div>
    );
}
