import { TeamStatistics } from '../../../src/domain/aggregates/team-statistics/team-statistics.aggregate';
import { TeamStatisticsUpdatedEvent } from '../../../src/domain/events';

describe('TeamStatistics Aggregate', () => {
  describe('create', () => {
    it('should create empty team statistics', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');

      expect(stats.userId).toBe(100n);
      expect(stats.directReferralCount).toBe(0);
      expect(stats.totalTeamCount).toBe(0);
      expect(stats.personalPlantingCount).toBe(0);
      expect(stats.teamPlantingCount).toBe(0);
      expect(stats.leaderboardScore).toBe(0);
    });
  });

  describe('reconstitute', () => {
    it('should reconstitute from persistence data', () => {
      const props = {
        id: 1n,
        userId: 100n,
        accountSequence: 'D25010100001',
        directReferralCount: 5,
        totalTeamCount: 100,
        personalPlantingCount: 10,
        teamPlantingCount: 90,
        leaderboardScore: 60,
        maxDirectTeamCount: 40,
        provinceCityDistribution: { '110000': { '110100': 50 } },
        lastCalculatedAt: new Date(),
        createdAt: new Date(),
        updatedAt: new Date(),
        directReferrals: [
          { referralId: 200n, teamCount: 40 },
          { referralId: 300n, teamCount: 30 },
        ],
      };

      const stats = TeamStatistics.reconstitute(props);

      expect(stats.id).toBe(1n);
      expect(stats.userId).toBe(100n);
      expect(stats.directReferralCount).toBe(5);
      expect(stats.totalTeamCount).toBe(100);
      expect(stats.leaderboardScore).toBe(60);
    });
  });

  describe('addDirectReferral', () => {
    it('should increment direct referral count', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');

      stats.addDirectReferral(200n);
      expect(stats.directReferralCount).toBe(1);

      stats.addDirectReferral(300n);
      expect(stats.directReferralCount).toBe(2);
    });
  });

  describe('addPersonalPlanting', () => {
    it('should add personal planting count', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');

      stats.addPersonalPlanting(10, '110000', '110100');

      expect(stats.personalPlantingCount).toBe(10);
      expect(stats.totalTeamCount).toBe(10);
    });

    it('should emit TeamStatisticsUpdatedEvent', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');
      stats.addPersonalPlanting(10, '110000', '110100');

      expect(stats.domainEvents.length).toBe(1);
      expect(stats.domainEvents[0]).toBeInstanceOf(TeamStatisticsUpdatedEvent);
    });

    it('should update province/city distribution', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');

      stats.addPersonalPlanting(10, '110000', '110100');
      stats.addPersonalPlanting(5, '110000', '110100');

      expect(stats.provinceCityDistribution.getCityTotal('110000', '110100')).toBe(15);
    });
  });

  describe('addTeamPlanting', () => {
    it('should add team planting count', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');

      stats.addTeamPlanting(20, '110000', '110100', 200n);

      expect(stats.teamPlantingCount).toBe(20);
      expect(stats.totalTeamCount).toBe(20);
    });

    it('should track direct referral team count', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');
      stats.addDirectReferral(200n);
      stats.addDirectReferral(300n);

      stats.addTeamPlanting(30, '110000', '110100', 200n);
      stats.addTeamPlanting(20, '110000', '110100', 300n);

      const directStats = stats.getDirectReferralStats();
      expect(directStats.get(200n)).toBe(30);
      expect(directStats.get(300n)).toBe(20);
    });

    it('should recalculate leaderboard score', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');
      stats.addDirectReferral(200n);
      stats.addDirectReferral(300n);

      stats.addTeamPlanting(50, '110000', '110100', 200n);
      stats.addTeamPlanting(30, '110000', '110100', 300n);

      // Total = 80, max direct = 50, score = 30
      expect(stats.leaderboardScore).toBe(30);
    });
  });

  describe('getDirectReferralStats', () => {
    it('should return copy of direct referral stats', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');
      stats.addDirectReferral(200n);
      stats.addTeamPlanting(30, '110000', '110100', 200n);

      const directStats = stats.getDirectReferralStats();
      directStats.set(999n, 100); // Modify copy

      // Original should not be affected
      expect(stats.getDirectReferralStats().has(999n)).toBe(false);
    });
  });

  describe('clearDomainEvents', () => {
    it('should clear domain events', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');
      stats.addPersonalPlanting(10, '110000', '110100');
      expect(stats.domainEvents.length).toBe(1);

      stats.clearDomainEvents();
      expect(stats.domainEvents.length).toBe(0);
    });
  });

  describe('toPersistence', () => {
    it('should convert to persistence format', () => {
      const stats = TeamStatistics.create(100n, 'D25010100001');
      stats.addDirectReferral(200n);
      stats.addTeamPlanting(30, '110000', '110100', 200n);

      const data = stats.toPersistence();

      expect(data.userId).toBe(100n);
      expect(data.directReferralCount).toBe(1);
      expect(data.totalTeamCount).toBe(30);
      expect(data.teamPlantingCount).toBe(30);
      expect(data.directReferrals).toContainEqual({ referralId: 200n, teamCount: 30 });
    });
  });
});
