/**
 * Integration Test: Team Leaderboard Use Case Orchestration
 * 
 * Tests the orchestration logic of team leaderboard-related Use Cases:
 * - GetTeamsLeaderboardUseCase: Retrieves ranked list of teams with performance metrics
 * - Validates that Use Cases correctly interact with their Ports (Repositories)
 * - Uses In-Memory adapters for fast, deterministic testing
 * 
 * Focus: Business logic orchestration, NOT UI rendering
 */

import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
import { InMemoryTeamRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryTeamRepository';
import { InMemoryTeamMembershipRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository';
import { GetTeamsLeaderboardUseCase } from '../../../core/racing/application/use-cases/GetTeamsLeaderboardUseCase';
import { Team } from '../../../core/racing/domain/entities/Team';
import { Logger } from '../../../core/shared/domain/Logger';

describe('Team Leaderboard Use Case Orchestration', () => {
  let teamRepository: InMemoryTeamRepository;
  let membershipRepository: InMemoryTeamMembershipRepository;
  let getTeamsLeaderboardUseCase: GetTeamsLeaderboardUseCase;
  let mockLogger: Logger;

  beforeAll(() => {
    mockLogger = {
      info: () => {},
      debug: () => {},
      warn: () => {},
      error: () => {},
    } as unknown as Logger;
    
    teamRepository = new InMemoryTeamRepository(mockLogger);
    membershipRepository = new InMemoryTeamMembershipRepository(mockLogger);
    
    // Mock driver stats provider
    const getDriverStats = (driverId: string) => {
      const statsMap: Record<string, { rating: number, wins: number, totalRaces: number }> = {
        'd1': { rating: 2000, wins: 10, totalRaces: 50 },
        'd2': { rating: 1500, wins: 5, totalRaces: 30 },
        'd3': { rating: 1000, wins: 2, totalRaces: 20 },
      };
      return statsMap[driverId] || null;
    };

    getTeamsLeaderboardUseCase = new GetTeamsLeaderboardUseCase(
      teamRepository,
      membershipRepository,
      getDriverStats,
      mockLogger
    );
  });

  beforeEach(() => {
    teamRepository.clear();
    membershipRepository.clear();
  });

  describe('GetTeamsLeaderboardUseCase - Success Path', () => {
    it('should retrieve ranked team leaderboard with performance metrics', async () => {
      // Scenario: Leaderboard with multiple teams
      // Given: Multiple teams exist
      const team1 = Team.create({ id: 't1', name: 'Pro Team', tag: 'PRO', description: 'Desc', ownerId: 'o1', leagues: [] });
      const team2 = Team.create({ id: 't2', name: 'Am Team', tag: 'AM', description: 'Desc', ownerId: 'o2', leagues: [] });
      await teamRepository.create(team1);
      await teamRepository.create(team2);
      
      // And: Teams have members with different stats
      await membershipRepository.saveMembership({ teamId: 't1', driverId: 'd1', role: 'owner', status: 'active', joinedAt: new Date() });
      await membershipRepository.saveMembership({ teamId: 't2', driverId: 'd3', role: 'owner', status: 'active', joinedAt: new Date() });

      // When: GetTeamsLeaderboardUseCase.execute() is called
      const result = await getTeamsLeaderboardUseCase.execute({ leagueId: 'any' });

      // Then: The result should contain ranked teams
      expect(result.isOk()).toBe(true);
      const { items, topItems } = result.unwrap();
      expect(items).toHaveLength(2);
      
      // And: Teams should be ranked by rating (Pro Team has d1 with 2000, Am Team has d3 with 1000)
      expect(topItems[0]?.team.id.toString()).toBe('t1');
      expect(topItems[0]?.rating).toBe(2000);
      expect(topItems[1]?.team.id.toString()).toBe('t2');
      expect(topItems[1]?.rating).toBe(1000);
    });

    it('should handle empty leaderboard', async () => {
      // Scenario: No teams exist
      // When: GetTeamsLeaderboardUseCase.execute() is called
      const result = await getTeamsLeaderboardUseCase.execute({ leagueId: 'any' });

      // Then: The result should be empty
      expect(result.isOk()).toBe(true);
      const { items } = result.unwrap();
      expect(items).toHaveLength(0);
    });
  });
});
