import { describe, it, expect, beforeEach, vi } from 'vitest';

vi.mock('../../resources/js/api/client', () => ({
    apiClient: {
        get: vi.fn(),
        post: vi.fn(),
        patch: vi.fn(),
        delete: vi.fn(),
    },
    ensureCsrfCookie: vi.fn(),
}));

import {
    listReportJobs,
    createReportJob,
    retryReportJob,
    cancelReportJob,
    deleteReportJob,
} from '../../resources/js/api/reports';
import { apiClient, ensureCsrfCookie } from '../../resources/js/api/client';

const FAKE_JOB = {
    id: 1,
    type: 'deals_export' as const,
    parameters: { format: 'csv' as const, date_from: '2026-05-01', date_to: '2026-05-12' },
    status: 'pending' as const,
    file_path: null,
    file_size: null,
    generation_seconds: null,
    error_message: null,
    created_at: '2026-05-12T20:00:00Z',
    finished_at: null,
    expires_at: null,
    is_expired: false,
    download_url: null,
    retry_count: 0,
    retry_max: 3,
};

describe('api/reports', () => {
    beforeEach(() => vi.clearAllMocks());

    it('listReportJobs() без params → все undefined', async () => {
        vi.mocked(apiClient.get).mockResolvedValue({
            data: {
                jobs: [],
                total: 0,
                limit: 50,
                offset: 0,
                counts: { pending: 0, processing: 0, done: 0, failed: 0 },
                quota: { active: 0, max_active: 5 },
            },
        });
        await listReportJobs();
        expect(apiClient.get).toHaveBeenCalledWith('/api/reports/jobs', {
            params: { status: undefined, limit: undefined, offset: undefined },
        });
    });

    it('listReportJobs({status, limit, offset}) → passes params', async () => {
        vi.mocked(apiClient.get).mockResolvedValue({
            data: {
                jobs: [FAKE_JOB],
                total: 1,
                limit: 25,
                offset: 0,
                counts: { pending: 1, processing: 0, done: 0, failed: 0 },
                quota: { active: 1, max_active: 5 },
            },
        });
        const r = await listReportJobs({ status: 'pending', limit: 25, offset: 0 });
        expect(apiClient.get).toHaveBeenCalledWith('/api/reports/jobs', {
            params: { status: 'pending', limit: 25, offset: 0 },
        });
        expect(r.jobs).toHaveLength(1);
    });

    it('createReportJob() POSTs /api/reports/jobs + unwraps data.job', async () => {
        vi.mocked(apiClient.post).mockResolvedValue({ data: { job: FAKE_JOB } });
        const payload = {
            type: 'deals_export' as const,
            format: 'csv' as const,
            parameters: { date_from: '2026-05-01', date_to: '2026-05-12', project_id: 7 },
        };
        const r = await createReportJob(payload);
        expect(ensureCsrfCookie).toHaveBeenCalledOnce();
        expect(apiClient.post).toHaveBeenCalledWith('/api/reports/jobs', payload);
        expect(r.id).toBe(1);
    });

    it('retryReportJob() POSTs /api/reports/jobs/{id}/retry', async () => {
        vi.mocked(apiClient.post).mockResolvedValue({ data: { job: { ...FAKE_JOB, retry_count: 1 } } });
        const r = await retryReportJob(42);
        expect(ensureCsrfCookie).toHaveBeenCalledOnce();
        expect(apiClient.post).toHaveBeenCalledWith('/api/reports/jobs/42/retry');
        expect(r.retry_count).toBe(1);
    });

    it('cancelReportJob() POSTs /api/reports/jobs/{id}/cancel', async () => {
        vi.mocked(apiClient.post).mockResolvedValue({ data: { job: { ...FAKE_JOB, status: 'failed' as const } } });
        await cancelReportJob(42);
        expect(ensureCsrfCookie).toHaveBeenCalledOnce();
        expect(apiClient.post).toHaveBeenCalledWith('/api/reports/jobs/42/cancel');
    });

    it('deleteReportJob() DELETE /api/reports/jobs/{id}', async () => {
        vi.mocked(apiClient.delete).mockResolvedValue({ data: undefined });
        await deleteReportJob(7);
        expect(ensureCsrfCookie).toHaveBeenCalledOnce();
        expect(apiClient.delete).toHaveBeenCalledWith('/api/reports/jobs/7');
    });
});
