import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { recalculateWithBackfill } from '../../../../modules/statistics-insights/usecases/stats/recalculateWithBackfill.usecase.js';
import { InMemoryStatsGateway } from '../../../../tests/stubs/stats.stub.js';
import { StubDiffStatsFetchGateway } from '../../../../tests/stubs/diffStatsFetch.stub.js';
import { ProjectStatsFactory, ReviewStatsFactory } from '../../../../tests/factories/projectStats.factory.js';
describe('recalculateWithBackfill', () => {
    beforeEach(() => {
        vi.useFakeTimers();
    });
    afterEach(() => {
        vi.useRealTimers();
    });
    it('should recalculate stats without backfill when shouldBackfill is false', async () => {
        const statsGateway = new InMemoryStatsGateway();
        const reviews = [
            ReviewStatsFactory.create({ id: 'r1', mrNumber: 1, score: 6 }),
            ReviewStatsFactory.create({ id: 'r2', mrNumber: 2, score: 8 }),
        ];
        statsGateway.saveProjectStats('/test/project', ProjectStatsFactory.create({
            reviews,
            averageScore: 0,
        }));
        const progressUpdates = [];
        const promise = recalculateWithBackfill({ projectPath: '/test/project', shouldBackfill: false, platform: 'gitlab' }, {
            statsGateway,
            diffStatsFetchGateways: null,
            onProgress: (progress) => progressUpdates.push({ ...progress }),
            logger: { warn: vi.fn(), error: vi.fn() },
        });
        await vi.runAllTimersAsync();
        await promise;
        const saved = statsGateway.loadProjectStats('/test/project');
        expect(saved?.averageScore).toBe(7);
        expect(progressUpdates.at(-1)?.status).toBe('completed');
    });
    it('should run backfill before recalculation when shouldBackfill is true', async () => {
        const statsGateway = new InMemoryStatsGateway();
        const diffStatsFetchGateway = new StubDiffStatsFetchGateway();
        const reviews = [
            ReviewStatsFactory.create({ id: 'r1', mrNumber: 10 }),
        ];
        statsGateway.saveProjectStats('/test/project', ProjectStatsFactory.create({ reviews }));
        diffStatsFetchGateway.setResponse(10, { commitsCount: 3, additions: 100, deletions: 20 });
        const progressUpdates = [];
        const promise = recalculateWithBackfill({ projectPath: '/test/project', shouldBackfill: true, platform: 'gitlab' }, {
            statsGateway,
            diffStatsFetchGateways: { gitlab: diffStatsFetchGateway, github: diffStatsFetchGateway },
            onProgress: (progress) => progressUpdates.push({ ...progress }),
            logger: { warn: vi.fn(), error: vi.fn() },
        });
        await vi.runAllTimersAsync();
        await promise;
        const saved = statsGateway.loadProjectStats('/test/project');
        expect(saved?.reviews[0].diffStats).toEqual({ commitsCount: 3, additions: 100, deletions: 20 });
        expect(progressUpdates.at(-1)?.status).toBe('completed');
    });
    it('should skip backfill when platform is null', async () => {
        const statsGateway = new InMemoryStatsGateway();
        const diffStatsFetchGateway = new StubDiffStatsFetchGateway();
        const reviews = [
            ReviewStatsFactory.create({ id: 'r1', mrNumber: 10 }),
        ];
        statsGateway.saveProjectStats('/test/project', ProjectStatsFactory.create({ reviews }));
        const progressUpdates = [];
        const promise = recalculateWithBackfill({ projectPath: '/test/project', shouldBackfill: true, platform: null }, {
            statsGateway,
            diffStatsFetchGateways: { gitlab: diffStatsFetchGateway, github: diffStatsFetchGateway },
            onProgress: (progress) => progressUpdates.push({ ...progress }),
            logger: { warn: vi.fn(), error: vi.fn() },
        });
        await vi.runAllTimersAsync();
        await promise;
        expect(diffStatsFetchGateway.fetchCallCount).toBe(0);
        expect(progressUpdates.at(-1)?.status).toBe('completed');
    });
    it('should use github gateway when platform is github', async () => {
        const statsGateway = new InMemoryStatsGateway();
        const gitlabGateway = new StubDiffStatsFetchGateway();
        const githubGateway = new StubDiffStatsFetchGateway();
        const reviews = [
            ReviewStatsFactory.create({ id: 'r1', mrNumber: 10 }),
        ];
        statsGateway.saveProjectStats('/test/project', ProjectStatsFactory.create({ reviews }));
        githubGateway.setResponse(10, { commitsCount: 5, additions: 200, deletions: 50 });
        const promise = recalculateWithBackfill({ projectPath: '/test/project', shouldBackfill: true, platform: 'github' }, {
            statsGateway,
            diffStatsFetchGateways: { gitlab: gitlabGateway, github: githubGateway },
            onProgress: vi.fn(),
            logger: { warn: vi.fn(), error: vi.fn() },
        });
        await vi.runAllTimersAsync();
        await promise;
        expect(githubGateway.fetchCallCount).toBe(1);
        expect(gitlabGateway.fetchCallCount).toBe(0);
    });
    it('should log error and not throw when recalculation fails', async () => {
        const statsGateway = new InMemoryStatsGateway();
        const diffStatsFetchGateway = new StubDiffStatsFetchGateway();
        const errorLogger = vi.fn();
        diffStatsFetchGateway.setFailure(10);
        const reviews = [
            ReviewStatsFactory.create({ id: 'r1', mrNumber: 10 }),
        ];
        statsGateway.saveProjectStats('/test/project', ProjectStatsFactory.create({ reviews }));
        const promise = recalculateWithBackfill({ projectPath: '/test/project', shouldBackfill: true, platform: 'gitlab' }, {
            statsGateway,
            diffStatsFetchGateways: { gitlab: diffStatsFetchGateway, github: diffStatsFetchGateway },
            onProgress: vi.fn(),
            logger: { warn: vi.fn(), error: errorLogger },
        });
        await vi.runAllTimersAsync();
        await expect(promise).resolves.toBeUndefined();
    });
    it('should broadcast completion progress after recalculation', async () => {
        const statsGateway = new InMemoryStatsGateway();
        const reviews = [
            ReviewStatsFactory.create({ id: 'r1', mrNumber: 1, score: 9 }),
        ];
        statsGateway.saveProjectStats('/test/project', ProjectStatsFactory.create({ reviews }));
        const progressUpdates = [];
        const promise = recalculateWithBackfill({ projectPath: '/test/project', shouldBackfill: false, platform: null }, {
            statsGateway,
            diffStatsFetchGateways: null,
            onProgress: (progress) => progressUpdates.push({ ...progress }),
            logger: { warn: vi.fn(), error: vi.fn() },
        });
        await vi.runAllTimersAsync();
        await promise;
        const lastProgress = progressUpdates.at(-1);
        expect(lastProgress).toEqual({
            total: 0,
            completed: 0,
            failed: 0,
            status: 'completed',
        });
    });
});
//# sourceMappingURL=recalculateWithBackfill.usecase.test.js.map