import { type CacheService } from '@modules/shared/infrastructure/cache.service';
import { type IMarketIndexRepository, type MarketReportResult } from '../../domain/repositories/market-index.repository';
import { GetMarketReportHandler } from '../queries/get-market-report/get-market-report.handler';
import { GetMarketReportQuery } from '../queries/get-market-report/get-market-report.query';

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

  beforeEach(() => {
    mockRepo = {
      findById: vi.fn(),
      findByKey: vi.fn(),
      save: vi.fn(),
      update: vi.fn(),
      getMarketReport: vi.fn(),
      getHeatmap: vi.fn(),
      getPriceTrend: vi.fn(),
      getDistrictStats: vi.fn(),
    };
    const mockCache = { getOrSet: vi.fn((_key: string, loader: () => Promise<unknown>) => loader()) } as unknown as CacheService;
    handler = new GetMarketReportHandler(mockRepo as any, mockCache);
  });

  it('returns market report with district data', async () => {
    const districts: MarketReportResult[] = [
      {
        district: 'Quận 1',
        city: 'Hồ Chí Minh',
        propertyType: 'APARTMENT',
        period: '2026-Q1',
        medianPrice: '5000000000',
        avgPriceM2: 80000000,
        totalListings: 150,
        daysOnMarket: 45,
        inventoryLevel: 3.2,
        absorptionRate: 0.65,
        yoyChange: 0.08,
      },
    ];
    mockRepo.getMarketReport.mockResolvedValue(districts);

    const query = new GetMarketReportQuery('Hồ Chí Minh', '2026-Q1', 'APARTMENT');
    const result = await handler.execute(query);

    expect(result.city).toBe('Hồ Chí Minh');
    expect(result.period).toBe('2026-Q1');
    expect(result.districts).toEqual(districts);
    expect(mockRepo.getMarketReport).toHaveBeenCalledWith('Hồ Chí Minh', '2026-Q1', 'APARTMENT');
  });

  it('returns report without propertyType filter', async () => {
    mockRepo.getMarketReport.mockResolvedValue([]);

    const query = new GetMarketReportQuery('Hà Nội', '2026-Q1');
    const result = await handler.execute(query);

    expect(result.districts).toEqual([]);
    expect(mockRepo.getMarketReport).toHaveBeenCalledWith('Hà Nội', '2026-Q1', undefined);
  });
});
