import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useTranslation } from '@/hooks/use-translation';
import { CalendarClock, Repeat, Star, Trash2Icon, TriangleAlert } from 'lucide-react';
import { equivalentLabel, percentEquivalent, RULE_BOUNDS } from '../lib/rule-units';
import { formatDayMonthYear, hasHoliday, holidayOffsets, isEventSeason, offsetWindowLabel, seasonStatus } from '../lib/season-calendar';
import type { MovableHolidays, YieldSeason } from '../types';
import HelpHint from './HelpHint';

const NS = 'yield.index';

type YieldSeasonRowProps = {
    value: YieldSeason;
    onChange: (patch: Partial<YieldSeason>) => void;
    onRemove: () => void;
    /** Focus the percent input on mount (template gallery pre-fills everything else). */
    autoFocusPct?: boolean;
    /** Date locale du jour (YYYY-MM-DD) : ancre de la « prochaine occurrence ». */
    today: string;
    /** Dates des fêtes mobiles (config/yield-holidays.php). */
    holidays?: MovableHolidays;
};

/**
 * One editable season row for the yield date-range editor: a name, an inclusive
 * date range and a PERCENT adjustment (fork of logements' SeasonFormFields with
 * the price field swapped for a % input). Invalid ranges (start > end) are flagged
 * inline; the parent owns overlap trimming.
 *
 * L'écran ne doit pas mentir sur ce que fait le moteur (lib/season-calendar.ts,
 * copie de SeasonCalendar) — d'où, en lecture seule :
 *  - « Chaque année » : la saison revient tous les ans ; ses dates ne donnent
 *    que le jour et le mois, la prochaine occurrence est affichée ;
 *  - « Événement prioritaire » : l'emporte sur la saison qu'il recouvre ;
 *  - « Date mobile : Aïd el-Fitr (J-2 → J+1) » : les deux champs de date sont
 *    remplacés par la prochaine occurrence calculée d'après la table des fêtes
 *    (les dates stockées n'y sont qu'un cache) ; un avertissement ambre dit
 *    quand la table n'a plus de date dans les 12 mois — la ligne ne modifie
 *    alors aucun prix. Le nom et le % restent modifiables.
 * Les contrôles pour poser ces drapeaux viendront avec le lot 2.
 */
export default function YieldSeasonRow({ value, onChange, onRemove, autoFocusPct, today, holidays }: YieldSeasonRowProps) {
    const { t, locale } = useTranslation();

    const movable = hasHoliday(value);
    const status = seasonStatus(value, today, holidays);
    const offsets = holidayOffsets(value);
    const invalidRange = !movable && value.start_date !== '' && value.end_date !== '' && value.start_date > value.end_date;

    const nextLine =
        status.next &&
        t(NS, 'season_next_occurrence', 'Prochaine occurrence : :from → :to')
            .replace(':from', formatDayMonthYear(status.next.start_date))
            .replace(':to', formatDayMonthYear(status.next.end_date));

    return (
        <div className="flex flex-col items-start justify-between gap-4 rounded-md border p-4 md:flex-row">
            <div className="grid w-full grid-cols-1 gap-4 md:grid-cols-2">
                {(value.repeat === 'yearly' || isEventSeason(value) || movable) && (
                    <div className="col-span-full flex flex-wrap gap-1.5">
                        {value.repeat === 'yearly' && !movable && (
                            <Badge variant="outline" className="gap-1 border-sky-300 text-sky-800 dark:border-sky-800 dark:text-sky-200">
                                <Repeat />
                                {t(NS, 'season_badge_yearly', 'Chaque année')}
                                <HelpHint
                                    text={t(
                                        NS,
                                        'season_badge_yearly_help',
                                        'Revient chaque année aux mêmes jours : seuls le jour et le mois des dates comptent.',
                                    )}
                                />
                            </Badge>
                        )}
                        {isEventSeason(value) && (
                            <Badge variant="outline" className="gap-1 border-violet-300 text-violet-800 dark:border-violet-800 dark:text-violet-200">
                                <Star />
                                {t(NS, 'season_badge_event', 'Événement prioritaire')}
                                <HelpHint text={t(NS, 'season_badge_event_help', 'L’emporte sur la saison qu’il recouvre, nuit par nuit.')} />
                            </Badge>
                        )}
                        {movable && (
                            <Badge
                                variant="outline"
                                className="gap-1 border-violet-300 whitespace-normal text-violet-800 dark:border-violet-800 dark:text-violet-200"
                            >
                                <CalendarClock />
                                {t(NS, 'season_badge_movable', 'Date mobile : :holiday (:window)')
                                    .replace(':holiday', holidayLabel(t, value.holiday))
                                    .replace(':window', offsets ? offsetWindowLabel(offsets, t(NS, 'season_offset_day', 'J')) : '?')}
                            </Badge>
                        )}
                    </div>
                )}
                <div className="col-span-full max-w-sm">
                    <Label>{t(NS, 'season_name', 'Nom de la saison')}</Label>
                    <Input
                        type="text"
                        placeholder={t(NS, 'season_name_placeholder', 'Ex. Été, Noël…')}
                        value={value.name}
                        onChange={(e) => onChange({ name: e.target.value })}
                    />
                </div>
                {movable ? (
                    // Fête mobile : les dates viennent de la table, pas d'un champ.
                    <div className="col-span-full flex flex-col gap-1 text-sm">
                        {status.next && (
                            <p>
                                {nextLine}
                                {status.estimated && (
                                    <span className="text-muted-foreground">
                                        {' '}
                                        · {t(NS, 'season_movable_estimated', 'date estimée à un jour près')}
                                    </span>
                                )}
                            </p>
                        )}
                        {status.missing && (
                            <p className="flex items-center gap-1.5 rounded-md border border-amber-300 bg-amber-50 px-2 py-1 text-xs text-amber-800 dark:border-amber-900/40 dark:bg-amber-950/30 dark:text-amber-200">
                                <TriangleAlert className="h-3.5 w-3.5 shrink-0" />
                                {t(
                                    NS,
                                    'season_movable_dates_missing',
                                    'Aucune date connue pour cette fête dans les 12 prochains mois : cette ligne ne modifie aucun prix.',
                                )}
                            </p>
                        )}
                    </div>
                ) : (
                    <>
                        <div>
                            <Label>
                                {t(NS, 'from', 'Du')}
                                <span className="text-red-500">*</span>
                            </Label>
                            <Input type="date" value={value.start_date} onChange={(e) => onChange({ start_date: e.target.value })} />
                        </div>
                        <div>
                            <Label>
                                {t(NS, 'to', 'Au')} <span className="text-red-500">*</span>
                            </Label>
                            <Input
                                type="date"
                                value={value.end_date}
                                min={value.start_date || undefined}
                                onChange={(e) => onChange({ end_date: e.target.value })}
                            />
                        </div>
                        {value.repeat === 'yearly' && nextLine && <p className="text-muted-foreground col-span-full text-xs">{nextLine}</p>}
                    </>
                )}
                <div>
                    <Label>
                        {t(NS, 'season_pct', 'Ajustement %')} <span className="text-red-500">*</span>
                        <HelpHint
                            text={t(
                                NS,
                                'season_pct_help',
                                'Pourcentage appliqué pendant cette saison. Exemple base 100 : +45 % = 145 ; -15 % = 85 ; 0 = prix normal.',
                            )}
                        />
                    </Label>
                    <div className="flex items-center gap-2">
                        <Input
                            type="number"
                            step="1"
                            min={RULE_BOUNDS.seasonPct.min}
                            max={RULE_BOUNDS.seasonPct.max}
                            value={value.pct}
                            autoFocus={autoFocusPct}
                            onChange={(e) => onChange({ pct: e.target.value === '' ? 0 : Number(e.target.value) })}
                            className="text-right"
                        />
                        <span className="text-muted-foreground text-xs">%</span>
                        {/* Le pourcentage lu en multiplicateur : « +45 % → soit ×1,45 ». */}
                        <span className="text-muted-foreground shrink-0 text-xs">
                            {equivalentLabel(t(NS, 'unit_equivalent', 'soit :value'), percentEquivalent(value.pct, locale))}
                        </span>
                    </div>
                </div>
                {invalidRange && (
                    <p className="col-span-full text-xs text-red-500">
                        {t(NS, 'start_date_before_end_date', 'La date de début doit précéder la date de fin.')}
                    </p>
                )}
            </div>
            <div className="flex items-center gap-2">
                <Button variant="outline" className="cursor-pointer" onClick={onRemove} type="button">
                    <Trash2Icon className="h-4 w-4 text-red-500" />
                </Button>
            </div>
        </div>
    );
}

/**
 * Libellé TRADUIT d'une fête : appels t() littéraux, pour que
 * YieldTranslationsTest vérifie chaque clé en fr ET en en (la table
 * config/yield-holidays.php ne porte aucun libellé).
 */
function holidayLabel(t: (namespace: string, key: string, fallback?: string) => string, holiday: YieldSeason['holiday']): string {
    switch (holiday) {
        case 'eid_al_fitr':
            return t(NS, 'holiday_eid_al_fitr', 'Aïd el-Fitr');
        case 'eid_al_adha':
            return t(NS, 'holiday_eid_al_adha', 'Aïd el-Adha');
        case 'easter':
            return t(NS, 'holiday_easter', 'Pâques');
        default:
            return String(holiday ?? '');
    }
}
