import { describe, expect, it } from 'vitest';
import { cleaningSummary, durationLabel, joinNames, type CleaningTimes } from './cleaning-times';

const done: CleaningTimes = {
    status: 'completed',
    arrived_at: '10:25',
    left_at: '11:40',
    duration_minutes: 75,
    started_at: '2026-09-12T10:25:00+01:00',
    cleaners: ['Khaoula Merseni'],
};

describe('cleaningSummary', () => {
    it('une mission terminée : arrivée, départ, durée et qui', () => {
        expect(cleaningSummary(done, new Date('2026-09-12T15:00:00+01:00'))).toEqual({
            kind: 'done',
            arrivedAt: '10:25',
            leftAt: '11:40',
            durationMinutes: 75,
            cleaners: ['Khaoula Merseni'],
        });
        expect(cleaningSummary({ ...done, status: 'verified' }, new Date())?.kind).toBe('done');
    });

    it('une mission en cours : l’arrivée, et le temps écoulé à l’ouverture', () => {
        const running: CleaningTimes = { ...done, status: 'in_progress', left_at: null, duration_minutes: null };

        expect(cleaningSummary(running, new Date('2026-09-12T11:30:00+01:00'))).toEqual({
            kind: 'in_progress',
            arrivedAt: '10:25',
            elapsedMinutes: 65,
            cleaners: ['Khaoula Merseni'],
        });
    });

    it('le temps écoulé compte les minutes de l’horloge affichée, pas les secondes', () => {
        // « depuis 10:25 » et l'horloge du poste à 11:40 : 1 h 15, dès 11:40:00
        // et jusqu'à 11:40:59 — jamais 1 h 14 (recette A, D1).
        const running: CleaningTimes = { ...done, status: 'in_progress', left_at: null, duration_minutes: null };

        expect(cleaningSummary(running, new Date('2026-09-12T11:40:00+01:00'))).toMatchObject({ elapsedMinutes: 75 });
        expect(cleaningSummary(running, new Date('2026-09-12T11:40:59+01:00'))).toMatchObject({ elapsedMinutes: 75 });
        expect(cleaningSummary(running, new Date('2026-09-12T11:41:00+01:00'))).toMatchObject({ elapsedMinutes: 76 });
        // Même si le serveur envoyait encore les secondes du démarrage.
        expect(cleaningSummary({ ...running, started_at: '2026-09-12T10:25:40+01:00' }, new Date('2026-09-12T11:40:10+01:00'))).toMatchObject({
            elapsedMinutes: 75,
        });
    });

    it('une horloge en retard sur le serveur ne rend jamais une durée négative', () => {
        const running: CleaningTimes = { ...done, status: 'in_progress', left_at: null, duration_minutes: null };

        expect(cleaningSummary(running, new Date('2026-09-12T10:20:00+01:00'))).toMatchObject({ elapsedMinutes: 0 });
    });

    it('rien pour une mission pas démarrée, à refaire, ou sans mission', () => {
        const idle: CleaningTimes = {
            status: 'scheduled',
            arrived_at: null,
            left_at: null,
            duration_minutes: null,
            started_at: null,
            cleaners: [],
        };

        expect(cleaningSummary(idle, new Date())).toBeNull();
        expect(cleaningSummary({ ...idle, status: 'redo' }, new Date())).toBeNull();
        expect(cleaningSummary(null, new Date())).toBeNull();
        expect(cleaningSummary(undefined, new Date())).toBeNull();
    });

    it('une réponse d’avant (sans durée ni noms) reste lisible', () => {
        const legacy = { status: 'completed', arrived_at: '10:25', left_at: '11:40' } as CleaningTimes;

        expect(cleaningSummary(legacy, new Date())).toEqual({
            kind: 'done',
            arrivedAt: '10:25',
            leftAt: '11:40',
            durationMinutes: null,
            cleaners: [],
        });
    });
});

describe('durationLabel', () => {
    it('écrit la durée comme l’app : 45 min, 1 h, 1 h 15', () => {
        expect(durationLabel(45)).toBe('45 min');
        expect(durationLabel(60)).toBe('1 h');
        expect(durationLabel(75)).toBe('1 h 15');
        expect(durationLabel(125)).toBe('2 h 05');
        expect(durationLabel(0)).toBe('0 min');
    });
});

describe('joinNames', () => {
    it('une, deux ou trois personnes, en phrase', () => {
        expect(joinNames(['Khaoula'], 'et')).toBe('Khaoula');
        expect(joinNames(['Khaoula', 'Ghada'], 'et')).toBe('Khaoula et Ghada');
        expect(joinNames(['Khaoula', 'Ghada', 'Sonia'], 'and')).toBe('Khaoula, Ghada and Sonia');
        expect(joinNames([], 'et')).toBe('');
    });
});
