import { SkillLevelService, type SkillLevel } from '@core/racing/domain/services/SkillLevelService'; import type { Logger } from '@core/shared/domain/Logger'; import { Result } from '@core/shared/domain/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import { Team } from '../../domain/entities/Team'; import { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository'; import { TeamRepository } from '../../domain/repositories/TeamRepository'; interface DriverStatsAdapter { rating: number | null; wins: number; totalRaces: number; } export type GetTeamsLeaderboardInput = { leagueId: string; seasonId?: string; }; export interface TeamLeaderboardItem { team: Team; memberCount: number; rating: number | null; totalWins: number; totalRaces: number; performanceLevel: SkillLevel; isRecruiting: boolean; createdAt: Date; } export interface GetTeamsLeaderboardResult { items: TeamLeaderboardItem[]; recruitingCount: number; groupsBySkillLevel: Record; topItems: TeamLeaderboardItem[]; } export type GetTeamsLeaderboardErrorCode = 'LEAGUE_NOT_FOUND' | 'SEASON_NOT_FOUND' | 'REPOSITORY_ERROR'; /** * Use case: GetTeamsLeaderboardUseCase */ export class GetTeamsLeaderboardUseCase { constructor( private readonly teamRepository: TeamRepository, private readonly teamMembershipRepository: TeamMembershipRepository, private readonly getDriverStats: (driverId: string) => DriverStatsAdapter | null, private readonly logger: Logger, ) {} async execute( _input: GetTeamsLeaderboardInput, ): Promise>> { void _input; try { const allTeams = await this.teamRepository.findAll(); const items: TeamLeaderboardItem[] = []; await Promise.all( allTeams.map(async (team: Team) => { const memberships = await this.teamMembershipRepository.getTeamMembers(team.id); const memberCount = memberships.length; let ratingSum = 0; let ratingCount = 0; let totalWins = 0; let totalRaces = 0; for (const membership of memberships) { const stats = this.getDriverStats(membership.driverId); if (!stats) continue; if (typeof stats.rating === 'number') { ratingSum += stats.rating; ratingCount += 1; } totalWins += stats.wins ?? 0; totalRaces += stats.totalRaces ?? 0; } const averageRating = ratingCount > 0 ? ratingSum / ratingCount : null; const performanceLevel = SkillLevelService.getTeamPerformanceLevel(averageRating); items.push({ team, memberCount, rating: averageRating, totalWins, totalRaces, performanceLevel, isRecruiting: true, createdAt: new Date(), }); }), ); const recruitingCount = items.filter((t) => t.isRecruiting).length; const groupsBySkillLevel: Record = { beginner: [], intermediate: [], advanced: [], pro: [], }; items.forEach((item) => { const level = item.performanceLevel; groupsBySkillLevel[level].push(item); }); const topItems = items .slice() .sort((a, b) => (b.rating ?? 0) - (a.rating ?? 0)) .slice(0, 10); const result: GetTeamsLeaderboardResult = { items, recruitingCount, groupsBySkillLevel, topItems, }; return Result.ok(result); } catch (err) { const error = err as { message?: string } | undefined; this.logger.error('Error retrieving teams leaderboard', err as Error); return Result.err({ code: 'REPOSITORY_ERROR', details: { message: error?.message ?? 'Failed to load teams leaderboard' }, }); } } }