import { FrDateInput } from '@/components/fr-date-input';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { useTranslation } from '@/hooks/use-translation';
import { cn } from '@/lib/utils';
import { CalendarRange, ChevronLeft, ChevronRight } from 'lucide-react';
import { useLayoutEffect, useRef, useState } from 'react';
import { anneeVoisine, cleMois, estMoisCourant, nomsMois, plage, plageInvalide, voisine, type ParamsPeriode } from '../periode';
import type { PeriodeListe } from '../types';

interface Props {
    periode: PeriodeListe;
    /** Pièces par mois de `periode.annee`, clés 1 → 12. */
    repartition: Record<number, number>;
    onChange: (params: ParamsPeriode) => void;
}

/**
 * Période de la liste des factures, le même découpage que Swiver : un mois
 * (le mois en cours à l'ouverture), une année, ou une plage libre. Les pièces
 * y sont rangées par date de facture. La période vit dans l'URL : un mois se
 * met en favori et le bouton « précédent » du navigateur y revient.
 */
export function PeriodeBar({ periode, repartition, onChange }: Props) {
    const { t, locale } = useTranslation();
    const tr = (cle: string, fr: string) => t('factures', cle, fr);

    const longs = nomsMois(locale, 'long');
    const courts = nomsMois(locale, 'short');
    const aujourdhui = new Date();
    const moisCourant = aujourdhui.getMonth() + 1;
    const anneeCourante = aujourdhui.getFullYear();

    const [plageOuverte, setPlageOuverte] = useState(false);
    const [du, setDu] = useState(periode.du);
    const [au, setAu] = useState(periode.au);
    const refus = plageInvalide(du, au);

    // Sur mobile la bande défile : on centre le mois choisi (ou le mois en
    // cours), sinon septembre reste caché derrière janvier. `scrollLeft` et non
    // `scrollIntoView` : ce dernier ferait aussi défiler la page verticalement.
    const bande = useRef<HTMLDivElement>(null);
    const moisVise = periode.mode === 'mois' ? periode.mois : periode.annee === anneeCourante ? moisCourant : null;
    useLayoutEffect(() => {
        const conteneur = bande.current;
        const cible = moisVise !== null ? conteneur?.querySelector<HTMLElement>(`[data-mois="${moisVise}"]`) : null;
        if (!conteneur || !cible || conteneur.scrollWidth <= conteneur.clientWidth) return;
        conteneur.scrollLeft = cible.offsetLeft - (conteneur.clientWidth - cible.offsetWidth) / 2;
    }, [moisVise, periode.annee]);

    const titre =
        periode.mode === 'mois' && periode.mois !== null
            ? `${longs[periode.mois - 1]} ${periode.annee}`
            : periode.mode === 'annee'
              ? `${tr('periode.annee', 'Année')} ${periode.annee}`
              : tr('periode.personnalise', 'Personnalisé');

    const precedente = voisine(periode, -1);
    const suivante = voisine(periode, 1);

    const MODES: { cle: PeriodeListe['mode']; libelle: string }[] = [
        { cle: 'mois', libelle: tr('periode.mode_mois', 'Mois') },
        { cle: 'annee', libelle: tr('periode.mode_annee', 'Année') },
    ];

    const choisirMode = (mode: PeriodeListe['mode']) => {
        if (mode === periode.mode) return;
        // Vers « Mois » : le mois en cours si l'année affichée est l'année en cours, sinon janvier.
        if (mode === 'mois') onChange({ mois: cleMois(periode.annee, periode.annee === anneeCourante ? moisCourant : 1) });
        if (mode === 'annee') onChange({ annee: periode.annee });
    };

    const ouvrirPlage = (ouvert: boolean) => {
        if (ouvert) {
            setDu(periode.du);
            setAu(periode.au);
        }
        setPlageOuverte(ouvert);
    };

    const MESSAGE_REFUS: Record<NonNullable<typeof refus>, string> = {
        incomplete: tr('periode.plage_incomplete', 'Choisissez les deux dates.'),
        ordre: tr('periode.plage_ordre', 'La date de fin précède la date de début.'),
        trop_longue: tr('periode.plage_trop_longue', 'Deux ans au plus.'),
    };

    return (
        <div className="flex w-full min-w-0 flex-col gap-2" data-tour="factures-periode">
            {/* Titre de la période, flèches, retour au mois en cours — et le choix du découpage */}
            <div className="flex w-full min-w-0 flex-wrap items-center justify-between gap-2">
                <div className="flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1">
                    <div className="flex items-center gap-1">
                        <Button
                            type="button"
                            variant="outline"
                            size="icon"
                            className="size-8 bg-white"
                            disabled={precedente === null}
                            onClick={() => precedente && onChange(precedente)}
                            aria-label={tr('periode.precedente', 'Période précédente')}
                        >
                            <ChevronLeft className="size-4" />
                        </Button>
                        <Button
                            type="button"
                            variant="outline"
                            size="icon"
                            className="size-8 bg-white"
                            disabled={suivante === null}
                            onClick={() => suivante && onChange(suivante)}
                            aria-label={tr('periode.suivante', 'Période suivante')}
                        >
                            <ChevronRight className="size-4" />
                        </Button>
                    </div>
                    <h2 className="text-lg font-semibold" aria-live="polite">
                        {titre}
                    </h2>
                    <span className="text-muted-foreground text-sm tabular-nums">{plage(periode)}</span>
                    {!estMoisCourant(periode, aujourdhui) && (
                        <button
                            type="button"
                            onClick={() => onChange({ mois: cleMois(anneeCourante, moisCourant) })}
                            className="text-secondary text-sm font-medium hover:underline"
                        >
                            {tr('periode.retour', 'Retour au mois en cours')}
                        </button>
                    )}
                </div>

                <div className="flex items-center rounded-md border bg-white p-0.5" role="group" aria-label={tr('periode.decoupage', 'Découpage')}>
                    {MODES.map((m) => (
                        <button
                            key={m.cle}
                            type="button"
                            aria-pressed={periode.mode === m.cle}
                            onClick={() => choisirMode(m.cle)}
                            className={cn(
                                'rounded px-3 py-1 text-sm transition',
                                periode.mode === m.cle ? 'bg-secondary/10 text-primary font-semibold' : 'text-muted-foreground hover:text-foreground',
                            )}
                        >
                            {m.libelle}
                        </button>
                    ))}
                    <Popover open={plageOuverte} onOpenChange={ouvrirPlage}>
                        <PopoverTrigger asChild>
                            <button
                                type="button"
                                aria-pressed={periode.mode === 'personnalise'}
                                className={cn(
                                    'inline-flex items-center gap-1.5 rounded px-3 py-1 text-sm transition',
                                    periode.mode === 'personnalise'
                                        ? 'bg-secondary/10 text-primary font-semibold'
                                        : 'text-muted-foreground hover:text-foreground',
                                )}
                            >
                                <CalendarRange className="size-3.5" aria-hidden />
                                {tr('periode.mode_personnalise', 'Personnalisé')}
                            </button>
                        </PopoverTrigger>
                        <PopoverContent align="end" className="w-72">
                            <form
                                className="grid gap-3"
                                onSubmit={(e) => {
                                    e.preventDefault();
                                    if (refus) return;
                                    setPlageOuverte(false);
                                    onChange({ du, au });
                                }}
                            >
                                <div className="grid gap-1.5">
                                    <Label htmlFor="periode-du">{tr('periode.du', 'Du')}</Label>
                                    <FrDateInput id="periode-du" value={du} onChange={setDu} />
                                </div>
                                <div className="grid gap-1.5">
                                    <Label htmlFor="periode-au">{tr('periode.au', 'Au')}</Label>
                                    <FrDateInput id="periode-au" value={au} onChange={setAu} min={du || undefined} />
                                </div>
                                {refus && refus !== 'incomplete' && <p className="text-xs text-rose-700">{MESSAGE_REFUS[refus]}</p>}
                                <Button type="submit" size="sm" className="bg-secondary hover:bg-secondary/90" disabled={refus !== null}>
                                    {tr('periode.appliquer', 'Afficher cette période')}
                                </Button>
                            </form>
                        </PopoverContent>
                    </Popover>
                </div>
            </div>

            {/* Bande des mois de l'année, flèches d'année aux deux bouts (défile seule sur mobile) */}
            <div ref={bande} className="relative flex w-full min-w-0 items-stretch gap-1 overflow-x-auto rounded-lg border bg-white p-1">
                <button
                    type="button"
                    onClick={() => onChange(anneeVoisine(periode, -1))}
                    className="text-muted-foreground hover:bg-muted hover:text-foreground inline-flex shrink-0 items-center gap-0.5 rounded-md px-2 text-sm tabular-nums"
                    aria-label={`${tr('periode.annee', 'Année')} ${periode.annee - 1}`}
                >
                    <ChevronLeft className="size-3.5" aria-hidden />
                    {periode.annee - 1}
                </button>
                {courts.map((court, i) => {
                    const mois = i + 1;
                    const choisi = periode.mode === 'mois' && periode.mois === mois;
                    const courant = periode.annee === anneeCourante && mois === moisCourant;
                    const nombre = repartition[mois] ?? 0;
                    return (
                        <button
                            key={mois}
                            type="button"
                            onClick={() => onChange({ mois: cleMois(periode.annee, mois) })}
                            aria-pressed={choisi}
                            data-mois={mois}
                            aria-label={`${longs[i]} ${periode.annee} — ${nombre}`}
                            title={courant ? tr('periode.mois_courant', 'Mois en cours') : undefined}
                            className={cn(
                                'relative flex min-w-14 flex-1 shrink-0 flex-col items-center rounded-md border-b-2 px-1.5 py-1 text-sm transition',
                                choisi ? 'border-secondary bg-secondary/10 text-primary font-semibold' : 'hover:bg-muted border-transparent',
                                !choisi && nombre === 0 && 'text-muted-foreground/70',
                            )}
                        >
                            <span className="inline-flex items-center gap-1">
                                {courant && <span className="bg-secondary size-1.5 rounded-full" aria-hidden />}
                                {court}
                            </span>
                            <span className={cn('text-[11px] leading-4 tabular-nums', choisi ? 'text-primary' : 'text-muted-foreground')}>
                                {nombre > 0 ? nombre : '–'}
                            </span>
                        </button>
                    );
                })}
                <button
                    type="button"
                    onClick={() => onChange(anneeVoisine(periode, 1))}
                    className="text-muted-foreground hover:bg-muted hover:text-foreground inline-flex shrink-0 items-center gap-0.5 rounded-md px-2 text-sm tabular-nums"
                    aria-label={`${tr('periode.annee', 'Année')} ${periode.annee + 1}`}
                >
                    {periode.annee + 1}
                    <ChevronRight className="size-3.5" aria-hidden />
                </button>
            </div>
        </div>
    );
}
