import { type CacheService } from '@modules/shared/infrastructure/cache.service';
import { type IMarketIndexRepository, type DistrictStatsResult } from '../../domain/repositories/market-index.repository';
import { GetDistrictStatsHandler } from '../queries/get-district-stats/get-district-stats.handler';
import { GetDistrictStatsQuery } from '../queries/get-district-stats/get-district-stats.query';

describe('GetDistrictStatsHandler', () => {
  let handler: GetDistrictStatsHandler;
  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 GetDistrictStatsHandler(mockRepo as any, mockCache);
  });

  it('returns district statistics', async () => {
    const stats: DistrictStatsResult[] = [
      {
        district: 'Quận 1',
        city: 'Hồ Chí Minh',
        propertyType: 'APARTMENT',
        medianPrice: '6000000000',
        avgPriceM2: 120000000,
        totalListings: 200,
        daysOnMarket: 30,
        inventoryLevel: 2.5,
        absorptionRate: 0.8,
        yoyChange: 0.12,
      },
      {
        district: 'Quận 7',
        city: 'Hồ Chí Minh',
        propertyType: 'APARTMENT',
        medianPrice: '4000000000',
        avgPriceM2: 80000000,
        totalListings: 350,
        daysOnMarket: 40,
        inventoryLevel: 3.0,
        absorptionRate: 0.65,
        yoyChange: 0.05,
      },
    ];
    mockRepo.getDistrictStats.mockResolvedValue(stats);

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

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

  it('returns empty array when no stats available', async () => {
    mockRepo.getDistrictStats.mockResolvedValue([]);

    const query = new GetDistrictStatsQuery('Cần Thơ', '2026-Q1');
    const result = await handler.execute(query);

    expect(result.districts).toEqual([]);
  });
});
