import { describe, it, expect } from 'vitest';
import { mapApiReportJob, uiTypeToApi } from '../../resources/js/composables/reportsMapper';
import type { ApiReportJob } from '../../resources/js/api/reports';

function makeApi(overrides: Partial<ApiReportJob> = {}): ApiReportJob {
    return {
        id: 1,
        type: 'deals_export',
        parameters: { format: 'csv', date_from: '2026-04-01', date_to: '2026-04-30' },
        status: 'done',
        file_path: 'reports/1/1.csv',
        file_size: 2048,
        generation_seconds: 2,
        error_message: null,
        created_at: '2026-04-15T10:00:00Z',
        finished_at: '2026-04-15T10:01:00Z',
        expires_at: '2026-05-15T10:01:00Z',
        is_expired: false,
        download_url: 'http://localhost/api/reports/jobs/1/file?tenant=1&signature=fake',
        retry_count: 0,
        retry_max: 3,
        ...overrides,
    };
}

describe('reportsMapper', () => {
    it('маппит status pending → queued', () => {
        const ui = mapApiReportJob(makeApi({ status: 'pending' }));
        expect(ui.status).toBe('queued');
    });

    it('маппит status processing → running', () => {
        const ui = mapApiReportJob(makeApi({ status: 'processing' }));
        expect(ui.status).toBe('running');
    });

    it('done и failed остаются как есть', () => {
        expect(mapApiReportJob(makeApi({ status: 'done' })).status).toBe('done');
        expect(mapApiReportJob(makeApi({ status: 'failed' })).status).toBe('failed');
    });

    it('title включает тип + period (один месяц)', () => {
        const ui = mapApiReportJob(makeApi());
        expect(ui.title).toBe('Сделки · детально · апр 2026');
    });

    it('title для разных месяцев показывает диапазон', () => {
        const ui = mapApiReportJob(
            makeApi({ parameters: { format: 'csv', date_from: '2026-03-01', date_to: '2026-04-30' } }),
        );
        expect(ui.title).toBe('Сделки · детально · мар 2026 — апр 2026');
    });

    it('format берётся из parameters.format', () => {
        const ui = mapApiReportJob(
            makeApi({ parameters: { format: 'xlsx', date_from: '2026-04-01', date_to: '2026-04-30' } }),
        );
        expect(ui.format).toBe('xlsx');
    });

    it('sizeText форматирует bytes (KB / MB)', () => {
        expect(mapApiReportJob(makeApi({ file_size: 500 })).sizeText).toBe('500 B');
        expect(mapApiReportJob(makeApi({ file_size: 2048 })).sizeText).toBe('2.0 KB');
        expect(mapApiReportJob(makeApi({ file_size: 1572864 })).sizeText).toBe('1.5 MB');
    });

    it('sizeText null если file_size null', () => {
        expect(mapApiReportJob(makeApi({ file_size: null })).sizeText).toBeNull();
    });

    it('attempt = retry_count + 1', () => {
        expect(mapApiReportJob(makeApi({ retry_count: 0 })).attempt).toBe(1);
        expect(mapApiReportJob(makeApi({ retry_count: 2 })).attempt).toBe(3);
    });

    it('error из error_message', () => {
        expect(mapApiReportJob(makeApi({ error_message: 'boom' })).error).toBe('boom');
    });

    it('timeText для pending = «в очереди»', () => {
        expect(mapApiReportJob(makeApi({ status: 'pending', file_path: null })).timeText).toBe('в очереди');
    });

    it('timeText для processing включает «в работе»', () => {
        const ui = mapApiReportJob(
            makeApi({ status: 'processing', created_at: new Date(Date.now() - 5000).toISOString() }),
        );
        expect(ui.timeText).toContain('в работе');
    });

    it('timeText для done показывает relative «N мин назад»', () => {
        const ui = mapApiReportJob(
            makeApi({
                status: 'done',
                finished_at: new Date(Date.now() - 10 * 60_000).toISOString(),
            }),
        );
        expect(ui.timeText).toBe('10 мин назад');
    });

    it('timeText для finished меньше минуты = «только что»', () => {
        const ui = mapApiReportJob(
            makeApi({ status: 'done', finished_at: new Date(Date.now() - 30_000).toISOString() }),
        );
        expect(ui.timeText).toBe('только что');
    });

    it('uiTypeToApi маппит slug правильно', () => {
        expect(uiTypeToApi('deals')).toBe('deals_export');
        expect(uiTypeToApi('managers')).toBe('managers_summary');
        expect(uiTypeToApi('sources')).toBe('sources_summary');
        expect(uiTypeToApi('billing')).toBe('billing_summary');
    });

    it('progress=50 для running, null для остальных', () => {
        expect(mapApiReportJob(makeApi({ status: 'processing' })).progress).toBe(50);
        expect(mapApiReportJob(makeApi({ status: 'done' })).progress).toBeNull();
        expect(mapApiReportJob(makeApi({ status: 'pending' })).progress).toBeNull();
        expect(mapApiReportJob(makeApi({ status: 'failed' })).progress).toBeNull();
    });

    it('downloadUrl берётся из api.download_url', () => {
        const ui = mapApiReportJob(makeApi({ download_url: 'http://x/file?signature=abc' }));
        expect(ui.downloadUrl).toBe('http://x/file?signature=abc');
    });

    it('downloadUrl = null если api.download_url null', () => {
        expect(mapApiReportJob(makeApi({ download_url: null })).downloadUrl).toBeNull();
    });
});
