import { Result } from '@core/shared/domain/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { Driver } from '../../domain/entities/Driver'; import type { League } from '../../domain/entities/League'; import type { DriverRepository } from '../../domain/repositories/DriverRepository'; import type { LeagueMembershipRepository } from '../../domain/repositories/LeagueMembershipRepository'; import type { LeagueRepository } from '../../domain/repositories/LeagueRepository'; import type { StandingRepository } from '../../domain/repositories/StandingRepository'; export interface GetLeagueOwnerSummaryInput { leagueId: string; } export type GetLeagueOwnerSummaryErrorCode = 'LEAGUE_NOT_FOUND' | 'OWNER_NOT_FOUND' | 'REPOSITORY_ERROR'; export interface GetLeagueOwnerSummaryResult { league: League; owner: Driver; totalMembers: number; activeMembers: number; rating: number | null; rank: number | null; } export class GetLeagueOwnerSummaryUseCase { constructor( private readonly leagueRepository: LeagueRepository, private readonly driverRepository: DriverRepository, private readonly leagueMembershipRepository: LeagueMembershipRepository, private readonly standingRepository: StandingRepository, ) {} async execute( input: GetLeagueOwnerSummaryInput, ): Promise>> { try { const league = await this.leagueRepository.findById(input.leagueId); if (!league) { return Result.err({ code: 'LEAGUE_NOT_FOUND', details: { message: 'League not found' }, }); } const owner = await this.driverRepository.findById(league.ownerId.toString()); if (!owner) { return Result.err({ code: 'OWNER_NOT_FOUND', details: { message: 'League owner not found' }, }); } const members = await this.leagueMembershipRepository.getLeagueMembers(input.leagueId); const totalMembers = members.length; const activeMembers = members.filter(m => m.status.toString() === 'active').length; // Calculate rating and rank for the owner let rating: number | null = null; let rank: number | null = null; try { // Get standing for the owner in this league const ownerStanding = await this.standingRepository.findByDriverIdAndLeagueId(owner.id.toString(), league.id.toString()); if (ownerStanding) { // Calculate rating from standing const baseRating = 1000; const pointsBonus = ownerStanding.points.toNumber() * 2; const positionBonus = Math.max(0, 50 - (ownerStanding.position.toNumber() * 2)); const winBonus = ownerStanding.wins * 100; rating = Math.round(baseRating + pointsBonus + positionBonus + winBonus); // Calculate rank among all drivers in this league const leagueStandings = await this.standingRepository.findByLeagueId(league.id.toString()); const driverStats = new Map(); for (const standing of leagueStandings) { const driverId = standing.driverId.toString(); const standingBaseRating = 1000; const standingPointsBonus = standing.points.toNumber() * 2; const standingPositionBonus = Math.max(0, 50 - (standing.position.toNumber() * 2)); const standingWinBonus = standing.wins * 100; const standingRating = Math.round(standingBaseRating + standingPointsBonus + standingPositionBonus + standingWinBonus); driverStats.set(driverId, { rating: standingRating }); } const rankings = Array.from(driverStats.entries()) .sort(([, a], [, b]) => b.rating - a.rating) .map(([driverId], index) => ({ driverId, rank: index + 1 })); const ownerRanking = rankings.find(r => r.driverId === owner.id.toString()); rank = ownerRanking ? ownerRanking.rank : null; } } catch (error) { // If rating calculation fails, continue with null values console.error('Failed to calculate rating/rank:', error); } return Result.ok({ league, owner, totalMembers, activeMembers, rating, rank, }); } catch (error: unknown) { const message = error instanceof Error ? error.message : 'Failed to get league owner summary'; return Result.err({ code: 'REPOSITORY_ERROR', details: { message }, }); } } }