import { describe, expect, it } from 'vitest';
import { frToIso, isoToFr, masquerDateFr, positionApresChiffres } from './fr-date';

describe('masquerDateFr — les barres obliques se posent seules', () => {
    it('compose la date au fil des chiffres', () => {
        expect(masquerDateFr('1')).toBe('1');
        expect(masquerDateFr('12')).toBe('12/');
        expect(masquerDateFr('12/3')).toBe('12/3');
        expect(masquerDateFr('12/03')).toBe('12/03/');
        expect(masquerDateFr('12/03/2')).toBe('12/03/2');
        expect(masquerDateFr('12/03/2026')).toBe('12/03/2026');
    });

    it('accepte les huit chiffres tapés d’affilée', () => {
        expect(masquerDateFr('12032026')).toBe('12/03/2026');
    });

    it('ignore tout ce qui n’est pas un chiffre', () => {
        expect(masquerDateFr('12-03-2026')).toBe('12/03/2026');
        expect(masquerDateFr('  12 03 2026 ')).toBe('12/03/2026');
        expect(masquerDateFr('abc')).toBe('');
    });

    it('tronque au-delà de huit chiffres plutôt que de déborder', () => {
        expect(masquerDateFr('120320269999')).toBe('12/03/2026');
    });

    /**
     * Le cas qui rend un masque naïf inutilisable : sans lui, effacer la barre
     * la repose aussitôt et le curseur ne peut jamais revenir dans le jour.
     */
    it('ne repose pas la barre pendant une suppression', () => {
        expect(masquerDateFr('12', true)).toBe('12');
        expect(masquerDateFr('12/03', true)).toBe('12/03');
        // hors des frontières, suppression ou non, le masque est le même
        expect(masquerDateFr('12/0', true)).toBe('12/0');
    });

    it('laisse passer une date impossible — ce n’est pas son travail', () => {
        expect(masquerDateFr('34567890')).toBe('34/56/7890');
    });
});

describe('frToIso', () => {
    it('convertit une date française en ISO', () => {
        expect(frToIso('12/03/2026')).toBe('2026-03-12');
        expect(frToIso('1/3/2026')).toBe('2026-03-01');
        expect(frToIso(' 12/03/2026 ')).toBe('2026-03-12');
    });

    it('accepte huit chiffres nus (collage depuis un tableur)', () => {
        expect(frToIso('12032026')).toBe('2026-03-12');
    });

    it('refuse une date qui n’existe pas au calendrier', () => {
        // Partait au serveur en `2026-02-31`, que PHP lit comme le 3 mars.
        expect(frToIso('31/02/2026')).toBeNull();
        expect(frToIso('31/04/2026')).toBeNull();
        expect(frToIso('30/02/2026')).toBeNull();
    });

    it('connaît les années bissextiles', () => {
        expect(frToIso('29/02/2024')).toBe('2024-02-29');
        expect(frToIso('29/02/2026')).toBeNull();
    });

    it('refuse ce qui n’est pas une date', () => {
        expect(frToIso('')).toBeNull();
        expect(frToIso('12/03')).toBeNull();
        expect(frToIso('12/03/26')).toBeNull();
        expect(frToIso('00/03/2026')).toBeNull();
        expect(frToIso('12/13/2026')).toBeNull();
    });

    it('fait l’aller-retour avec isoToFr', () => {
        expect(frToIso(isoToFr('2026-03-12'))).toBe('2026-03-12');
    });
});

describe('positionApresChiffres — le curseur suit les chiffres, pas les caractères', () => {
    it('se pose après le n-ième chiffre', () => {
        expect(positionApresChiffres('12/03/2026', 0, false)).toBe(0);
        expect(positionApresChiffres('12/03/2026', 2, false)).toBe(2);
        expect(positionApresChiffres('12/03/2026', 3, false)).toBe(4);
        expect(positionApresChiffres('12/03/2026', 8, false)).toBe(10);
    });

    it('franchit la barre que le masque vient de poser', () => {
        // « 12 » tapé → masque « 12/ » → le chiffre suivant doit tomber dans le mois
        expect(positionApresChiffres('12/', 2, true)).toBe(3);
        expect(positionApresChiffres('12/03/', 4, true)).toBe(6);
    });

    it('reste devant la barre en suppression', () => {
        expect(positionApresChiffres('12/', 2, false)).toBe(2);
    });

    it('ne dépasse jamais la fin du masque', () => {
        expect(positionApresChiffres('12', 8, true)).toBe(2);
    });
});
