import type { ReportEntity } from '../../domain/entities/report.entity';
import { ReportStatus } from '../../domain/enums/report-status.enum';
import { ReportType } from '../../domain/enums/report-type.enum';
import { type IReportRepository } from '../../domain/repositories/report.repository';
import { GenerateReportCommand } from '../commands/generate-report/generate-report.command';
import { GenerateReportHandler } from '../commands/generate-report/generate-report.handler';

describe('GenerateReportHandler', () => {
  let handler: GenerateReportHandler;
  let mockReportRepo: { [K in keyof IReportRepository]: ReturnType<typeof vi.fn> };
  let mockQueue: { add: ReturnType<typeof vi.fn> };

  beforeEach(() => {
    mockReportRepo = {
      findById: vi.fn(),
      findByUserId: vi.fn(),
      save: vi.fn(),
      update: vi.fn(),
      delete: vi.fn(),
      countByUserInPeriod: vi.fn(),
    };

    mockQueue = {
      add: vi.fn().mockResolvedValue(undefined),
    };

    handler = new GenerateReportHandler(mockReportRepo as any, mockQueue as any);
  });

  it('creates a report and enqueues generation job', async () => {
    const command = new GenerateReportCommand(
      'user-1',
      ReportType.INDUSTRIAL_LOCATION,
      'Báo cáo KCN Bình Dương',
      { province: 'Bình Dương' },
    );

    const result = await handler.execute(command);

    expect(result.reportId).toBeDefined();
    expect(mockReportRepo.save).toHaveBeenCalledOnce();

    const savedReport = mockReportRepo.save.mock.calls[0][0] as ReportEntity;
    expect(savedReport.userId).toBe('user-1');
    expect(savedReport.type).toBe(ReportType.INDUSTRIAL_LOCATION);
    expect(savedReport.status).toBe(ReportStatus.GENERATING);

    expect(mockQueue.add).toHaveBeenCalledWith(
      'generate',
      { reportId: result.reportId },
      expect.objectContaining({ attempts: 2 }),
    );
  });
});
