/**
 * Dates de séjour affichées dans l'en-tête d'une discussion.
 *
 * Module PUR, sans React ni accès au DOM : c'est la seule forme testable ici,
 * vitest tournant en environnement `node` (vitest.config.ts) — ni jsdom, ni
 * testing-library dans ce dépôt.
 */

/**
 * Statuts de `config/status.php` : 1 Confirmé, 2 Supprimé, 3 Modifié, 4 Demander.
 *
 * On affiche les dates pour 1 ET 3. « Modifié » est une vraie réservation — le
 * canal a changé quelque chose après coup —, et c'est déjà la définition que
 * retient tout le tableau de bord (`DashboardService`, `whereIn('status_id', ['1','3'])`).
 * Ne garder que le 1 strict ferait disparaître les dates d'une réservation
 * modifiée par l'OTA, sans rien dire au gérant.
 *
 * Le 4 est écarté parce qu'une demande n'est pas une réservation : ses dates
 * sont demandées, pas retenues. Le 2 l'est parce qu'il n'y a plus de séjour.
 */
export const STAY_DATE_STATUSES = [1, 3] as const;

export function showsStayDates(status?: number | null): boolean {
    return status !== null && status !== undefined && (STAY_DATE_STATUSES as readonly number[]).includes(status);
}

/**
 * Découpe un `Y-m-d` (ce que renvoie `mapDiscussion()` via `toDateString()`)
 * sans passer par `new Date(value)`.
 *
 * `new Date('2026-03-12')` est lu comme MINUIT UTC : dans un fuseau négatif, la
 * date rendue est la veille. Le piège est déjà documenté dans `fr-date.ts`, qui
 * construit ses dates composant par composant pour la même raison.
 */
export function parseIsoDay(value?: string | null): { year: number; month: number; day: number } | null {
    if (!value) return null;

    const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(value.trim());
    if (!match) return null;

    const year = Number(match[1]);
    const month = Number(match[2]);
    const day = Number(match[3]);

    if (month < 1 || month > 12 || day < 1 || day > 31) return null;

    return { year, month, day };
}

/** `2026-03-12` → `12/03/2026`. Chaîne vide si la valeur est inexploitable. */
export function formatDay(value?: string | null): string {
    const parsed = parseIsoDay(value);
    if (!parsed) return '';

    const pad = (n: number) => String(n).padStart(2, '0');

    return `${pad(parsed.day)}/${pad(parsed.month)}/${parsed.year}`;
}

/**
 * `12/03/2026 → 15/03/2026`. L'année est répétée des deux côtés : un séjour à
 * cheval sur deux années se lisait faux quand seule la fin la portait.
 *
 * Rend `null` — et non une chaîne vide — quand il n'y a rien à montrer, pour que
 * l'appelant décide de ne pas rendre la ligne du tout.
 */
export function stayRange(checkin?: string | null, checkout?: string | null): string | null {
    const from = formatDay(checkin);
    const to = formatDay(checkout);

    if (from && to) return `${from} → ${to}`;

    // Une seule borne connue vaut mieux que rien : le gérant lit au moins l'arrivée.
    return from || to || null;
}
