import { ForbiddenException, NotFoundException } from '@nestjs/common';
import { 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 { GetReportHandler } from '../queries/get-report/get-report.handler';
import { GetReportQuery } from '../queries/get-report/get-report.query';

function createReport(userId = 'user-1'): ReportEntity {
  return new ReportEntity('rpt-1', {
    userId,
    type: ReportType.DISTRICT_ANALYSIS,
    title: 'Phân tích Quận 1',
    params: { city: 'Hồ Chí Minh', district: 'Quận 1' },
    content: { sections: {} },
    pdfUrl: null,
    status: ReportStatus.READY,
    errorMsg: null,
  });
}

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

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

    handler = new GetReportHandler(mockReportRepo as any);
  });

  it('returns report for the owner', async () => {
    const report = createReport('user-1');
    mockReportRepo.findById.mockResolvedValue(report);

    const result = await handler.execute(new GetReportQuery('rpt-1', 'user-1'));

    expect(result.id).toBe('rpt-1');
    expect(result.type).toBe(ReportType.DISTRICT_ANALYSIS);
    expect(result.status).toBe(ReportStatus.READY);
  });

  it('throws NotFoundException when report does not exist', async () => {
    mockReportRepo.findById.mockResolvedValue(null);

    await expect(
      handler.execute(new GetReportQuery('nonexistent', 'user-1')),
    ).rejects.toThrow(NotFoundException);
  });

  it('throws ForbiddenException when user does not own report', async () => {
    mockReportRepo.findById.mockResolvedValue(createReport('other-user'));

    await expect(
      handler.execute(new GetReportQuery('rpt-1', 'user-1')),
    ).rejects.toThrow(ForbiddenException);
  });
});
