import { DauCalculationService } from '../../../../src/domain/services/dau-calculation.service';
import { DauQueryResult } from '../../../../src/domain/repositories/event-log.repository.interface';

describe('DauCalculationService', () => {
  let service: DauCalculationService;

  beforeEach(() => {
    service = new DauCalculationService();
  });

  describe('createStatsFromQueryResult', () => {
    it('should create DailyActiveStats from query result', () => {
      const day = new Date('2025-01-01');
      const result: DauQueryResult = {
        total: 1000,
        byProvince: new Map([
          ['Shanghai', 500],
          ['Beijing', 300],
        ]),
        byCity: new Map([
          ['Shanghai', 500],
          ['Haidian', 300],
        ]),
      };

      const stats = service.createStatsFromQueryResult(day, result);

      expect(stats.day).toEqual(day);
      expect(stats.dauCount).toBe(1000);
      expect(stats.dauByProvince.get('Shanghai')).toBe(500);
      expect(stats.dauByProvince.get('Beijing')).toBe(300);
      expect(stats.dauByCity.get('Shanghai')).toBe(500);
      expect(stats.dauByCity.get('Haidian')).toBe(300);
    });

    it('should handle empty province and city maps', () => {
      const day = new Date('2025-01-01');
      const result: DauQueryResult = {
        total: 100,
        byProvince: new Map(),
        byCity: new Map(),
      };

      const stats = service.createStatsFromQueryResult(day, result);

      expect(stats.dauCount).toBe(100);
      expect(stats.dauByProvince.size).toBe(0);
      expect(stats.dauByCity.size).toBe(0);
    });

    it('should handle zero total', () => {
      const day = new Date('2025-01-01');
      const result: DauQueryResult = {
        total: 0,
        byProvince: new Map(),
        byCity: new Map(),
      };

      const stats = service.createStatsFromQueryResult(day, result);

      expect(stats.dauCount).toBe(0);
    });
  });

  describe('mergeQueryResults', () => {
    it('should return empty result for empty input', () => {
      const merged = service.mergeQueryResults([]);

      expect(merged.total).toBe(0);
      expect(merged.byProvince.size).toBe(0);
      expect(merged.byCity.size).toBe(0);
    });

    it('should return single result unchanged', () => {
      const result: DauQueryResult = {
        total: 500,
        byProvince: new Map([['Shanghai', 500]]),
        byCity: new Map([['Shanghai', 500]]),
      };

      const merged = service.mergeQueryResults([result]);

      expect(merged.total).toBe(500);
      expect(merged.byProvince.get('Shanghai')).toBe(500);
      expect(merged.byCity.get('Shanghai')).toBe(500);
    });

    it('should take max total from multiple results', () => {
      const results: DauQueryResult[] = [
        {
          total: 300,
          byProvince: new Map(),
          byCity: new Map(),
        },
        {
          total: 500,
          byProvince: new Map(),
          byCity: new Map(),
        },
        {
          total: 400,
          byProvince: new Map(),
          byCity: new Map(),
        },
      ];

      const merged = service.mergeQueryResults(results);

      expect(merged.total).toBe(500);
    });

    it('should take max count per province from multiple results', () => {
      const results: DauQueryResult[] = [
        {
          total: 1000,
          byProvince: new Map([
            ['Shanghai', 500],
            ['Beijing', 200],
          ]),
          byCity: new Map(),
        },
        {
          total: 1200,
          byProvince: new Map([
            ['Shanghai', 600],
            ['Guangdong', 300],
          ]),
          byCity: new Map(),
        },
      ];

      const merged = service.mergeQueryResults(results);

      expect(merged.byProvince.get('Shanghai')).toBe(600);
      expect(merged.byProvince.get('Beijing')).toBe(200);
      expect(merged.byProvince.get('Guangdong')).toBe(300);
    });

    it('should take max count per city from multiple results', () => {
      const results: DauQueryResult[] = [
        {
          total: 1000,
          byProvince: new Map(),
          byCity: new Map([
            ['Shenzhen', 400],
            ['Guangzhou', 300],
          ]),
        },
        {
          total: 1200,
          byProvince: new Map(),
          byCity: new Map([
            ['Shenzhen', 500],
            ['Beijing', 200],
          ]),
        },
      ];

      const merged = service.mergeQueryResults(results);

      expect(merged.byCity.get('Shenzhen')).toBe(500);
      expect(merged.byCity.get('Guangzhou')).toBe(300);
      expect(merged.byCity.get('Beijing')).toBe(200);
    });

    it('should handle mixed data from multiple results', () => {
      const results: DauQueryResult[] = [
        {
          total: 800,
          byProvince: new Map([['Shanghai', 400]]),
          byCity: new Map([['Shanghai', 400]]),
        },
        {
          total: 1000,
          byProvince: new Map([
            ['Shanghai', 500],
            ['Beijing', 300],
          ]),
          byCity: new Map([
            ['Shanghai', 500],
            ['Haidian', 300],
          ]),
        },
        {
          total: 900,
          byProvince: new Map([['Guangdong', 450]]),
          byCity: new Map([['Shenzhen', 450]]),
        },
      ];

      const merged = service.mergeQueryResults(results);

      expect(merged.total).toBe(1000);
      expect(merged.byProvince.get('Shanghai')).toBe(500);
      expect(merged.byProvince.get('Beijing')).toBe(300);
      expect(merged.byProvince.get('Guangdong')).toBe(450);
      expect(merged.byCity.get('Shanghai')).toBe(500);
      expect(merged.byCity.get('Haidian')).toBe(300);
      expect(merged.byCity.get('Shenzhen')).toBe(450);
    });
  });
});
