import { type CacheService } from '@modules/shared/infrastructure/cache.service';
import { type IMarketIndexRepository, type PriceTrendPoint } from '../../domain/repositories/market-index.repository';
import { GetPriceTrendHandler } from '../queries/get-price-trend/get-price-trend.handler';
import { GetPriceTrendQuery } from '../queries/get-price-trend/get-price-trend.query';

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

  it('returns price trend data for a district', async () => {
    const trendData: PriceTrendPoint[] = [
      { period: '2025-Q4', medianPrice: '4500000000', avgPriceM2: 75000000, totalListings: 120 },
      { period: '2026-Q1', medianPrice: '5000000000', avgPriceM2: 80000000, totalListings: 150 },
    ];
    mockRepo.getPriceTrend.mockResolvedValue(trendData);

    const query = new GetPriceTrendQuery('Quận 1', 'Hồ Chí Minh', 'APARTMENT', ['2025-Q4', '2026-Q1']);
    const result = await handler.execute(query);

    expect(result.district).toBe('Quận 1');
    expect(result.city).toBe('Hồ Chí Minh');
    expect(result.propertyType).toBe('APARTMENT');
    expect(result.trend).toEqual(trendData);
    expect(mockRepo.getPriceTrend).toHaveBeenCalledWith('Quận 1', 'Hồ Chí Minh', 'APARTMENT', ['2025-Q4', '2026-Q1']);
  });

  it('returns empty trend when no data available', async () => {
    mockRepo.getPriceTrend.mockResolvedValue([]);

    const query = new GetPriceTrendQuery('Quận 9', 'Hồ Chí Minh', 'HOUSE', ['2026-Q1']);
    const result = await handler.execute(query);

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