/**
 * Tests for GetTeamRatingsSummaryQuery
 */

import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
import { GetTeamRatingsSummaryQuery, GetTeamRatingsSummaryQueryHandler } from './GetTeamRatingsSummaryQuery';
import { TeamRatingSnapshot } from '../../domain/services/TeamRatingSnapshotCalculator';
import { TeamRatingValue } from '../../domain/value-objects/TeamRatingValue';
import { TeamRatingEvent } from '../../domain/entities/TeamRatingEvent';
import { TeamRatingEventId } from '../../domain/value-objects/TeamRatingEventId';
import { TeamRatingDimensionKey } from '../../domain/value-objects/TeamRatingDimensionKey';
import { TeamRatingDelta } from '../../domain/value-objects/TeamRatingDelta';

describe('GetTeamRatingsSummaryQuery', () => {
  let mockTeamRatingRepo: any;
  let mockRatingEventRepo: any;
  let handler: GetTeamRatingsSummaryQueryHandler;

  beforeEach(() => {
    mockTeamRatingRepo = {
      findByTeamId: vi.fn(),
    };
    mockRatingEventRepo = {
      getAllByTeamId: vi.fn(),
    };

    handler = new GetTeamRatingsSummaryQueryHandler(
      mockTeamRatingRepo,
      mockRatingEventRepo
    );
  });

  describe('execute', () => {
    it('should return summary with platform ratings', async () => {
      const teamId = 'team-123';

      // Mock team rating snapshot
      const snapshot: TeamRatingSnapshot = {
        teamId,
        driving: TeamRatingValue.create(75),
        adminTrust: TeamRatingValue.create(60),
        overall: 70.5,
        lastUpdated: new Date('2024-01-01T10:00:00Z'),
        eventCount: 5,
      };
      mockTeamRatingRepo.findByTeamId.mockResolvedValue(snapshot);

      // Mock rating events
      const event = TeamRatingEvent.create({
        id: TeamRatingEventId.generate(),
        teamId,
        dimension: TeamRatingDimensionKey.create('driving'),
        delta: TeamRatingDelta.create(10),
        occurredAt: new Date('2024-01-01T10:00:00Z'),
        createdAt: new Date('2024-01-01T10:00:00Z'),
        source: { type: 'race', id: 'race-123' },
        reason: { code: 'RACE_FINISH' },
        visibility: { public: true },
        version: 1,
      });
      mockRatingEventRepo.getAllByTeamId.mockResolvedValue([event]);

      const query: GetTeamRatingsSummaryQuery = { teamId };
      const result = await handler.execute(query);

      expect(result.teamId).toBe(teamId);
      expect(result.platform.driving.value).toBe(75);
      expect(result.platform.adminTrust.value).toBe(60);
      expect(result.platform.overall).toBe(70.5);
      expect(result.lastRatingEventAt).toBe('2024-01-01T10:00:00.000Z');
    });

    it('should handle missing team rating gracefully', async () => {
      const teamId = 'team-123';

      mockTeamRatingRepo.findByTeamId.mockResolvedValue(null);
      mockRatingEventRepo.getAllByTeamId.mockResolvedValue([]);

      const query: GetTeamRatingsSummaryQuery = { teamId };
      const result = await handler.execute(query);

      expect(result.teamId).toBe(teamId);
      expect(result.platform.driving.value).toBe(0);
      expect(result.platform.adminTrust.value).toBe(0);
      expect(result.platform.overall).toBe(0);
      expect(result.lastRatingEventAt).toBeUndefined();
    });

    it('should handle multiple events and find latest', async () => {
      const teamId = 'team-123';

      const snapshot: TeamRatingSnapshot = {
        teamId,
        driving: TeamRatingValue.create(80),
        adminTrust: TeamRatingValue.create(70),
        overall: 77,
        lastUpdated: new Date('2024-01-02T10:00:00Z'),
        eventCount: 10,
      };
      mockTeamRatingRepo.findByTeamId.mockResolvedValue(snapshot);

      // Multiple events with different timestamps
      const events = [
        TeamRatingEvent.create({
          id: TeamRatingEventId.generate(),
          teamId,
          dimension: TeamRatingDimensionKey.create('driving'),
          delta: TeamRatingDelta.create(5),
          occurredAt: new Date('2024-01-01T08:00:00Z'),
          createdAt: new Date('2024-01-01T08:00:00Z'),
          source: { type: 'race', id: 'race-1' },
          reason: { code: 'RACE_FINISH' },
          visibility: { public: true },
          version: 1,
        }),
        TeamRatingEvent.create({
          id: TeamRatingEventId.generate(),
          teamId,
          dimension: TeamRatingDimensionKey.create('driving'),
          delta: TeamRatingDelta.create(10),
          occurredAt: new Date('2024-01-02T10:00:00Z'),
          createdAt: new Date('2024-01-02T10:00:00Z'),
          source: { type: 'race', id: 'race-2' },
          reason: { code: 'RACE_FINISH' },
          visibility: { public: true },
          version: 1,
        }),
      ];
      mockRatingEventRepo.getAllByTeamId.mockResolvedValue(events);

      const query: GetTeamRatingsSummaryQuery = { teamId };
      const result = await handler.execute(query);

      expect(result.lastRatingEventAt).toBe('2024-01-02T10:00:00.000Z');
    });

    it('should calculate confidence and sampleSize from event count', async () => {
      const teamId = 'team-123';

      const snapshot: TeamRatingSnapshot = {
        teamId,
        driving: TeamRatingValue.create(65),
        adminTrust: TeamRatingValue.create(55),
        overall: 62,
        lastUpdated: new Date('2024-01-01T10:00:00Z'),
        eventCount: 8,
      };
      mockTeamRatingRepo.findByTeamId.mockResolvedValue(snapshot);
      mockRatingEventRepo.getAllByTeamId.mockResolvedValue([]);

      const query: GetTeamRatingsSummaryQuery = { teamId };
      const result = await handler.execute(query);

      // Confidence should be min(1, eventCount/10) = 0.8
      expect(result.platform.driving.confidence).toBe(0.8);
      expect(result.platform.driving.sampleSize).toBe(8);
      expect(result.platform.adminTrust.confidence).toBe(0.8);
      expect(result.platform.adminTrust.sampleSize).toBe(8);
    });

    it('should handle empty events array', async () => {
      const teamId = 'team-123';

      const snapshot: TeamRatingSnapshot = {
        teamId,
        driving: TeamRatingValue.create(50),
        adminTrust: TeamRatingValue.create(50),
        overall: 50,
        lastUpdated: new Date('2024-01-01T10:00:00Z'),
        eventCount: 0,
      };
      mockTeamRatingRepo.findByTeamId.mockResolvedValue(snapshot);
      mockRatingEventRepo.getAllByTeamId.mockResolvedValue([]);

      const query: GetTeamRatingsSummaryQuery = { teamId };
      const result = await handler.execute(query);

      expect(result.platform.driving.confidence).toBe(0);
      expect(result.platform.driving.sampleSize).toBe(0);
      expect(result.platform.driving.trend).toBe('stable');
      expect(result.lastRatingEventAt).toBeUndefined();
    });
  });
});