import { LeaguesApiClient } from "@/lib/api/leagues/LeaguesApiClient"; import { DriversApiClient } from "@/lib/api/drivers/DriversApiClient"; import type { LeagueConfigFormModel } from "@core/racing/application"; import type { LeagueScoringPresetDTO } from "@core/racing/application/ports/LeagueScoringPresetProvider"; import type { GetDriverOutputDTO } from "@/lib/types/generated/GetDriverOutputDTO"; import { LeagueSettingsViewModel } from "@/lib/view-models/LeagueSettingsViewModel"; import { DriverSummaryViewModel } from "@/lib/view-models/DriverSummaryViewModel"; /** * League Settings Service * * Orchestrates league settings operations by coordinating API calls and view model creation. * All dependencies are injected via constructor. */ export class LeagueSettingsService { constructor( private readonly leaguesApiClient: LeaguesApiClient, private readonly driversApiClient: DriversApiClient ) {} /** * Get league settings with view model transformation */ async getLeagueSettings(leagueId: string): Promise { try { // Get league basic info (includes ownerId in DTO) const allLeagues = await this.leaguesApiClient.getAllWithCapacity(); const leagueDto = allLeagues.leagues.find(l => l.id === leagueId); if (!leagueDto) return null; const league = { id: leagueDto.id, name: leagueDto.name, ownerId: leagueDto.ownerId, }; // Get config const configDto = await this.leaguesApiClient.getLeagueConfig(leagueId); const config: LeagueConfigFormModel = configDto.config; // Get presets const presetsDto = await this.leaguesApiClient.getScoringPresets(); const presets: LeagueScoringPresetDTO[] = presetsDto.presets; // Get leaderboard once so we can hydrate rating / rank for owner + members const leaderboardDto = await this.driversApiClient.getLeaderboard(); const leaderboardByDriverId = new Map( leaderboardDto.drivers.map(driver => [driver.id, driver]) ); // Get owner const ownerDriver = await this.driversApiClient.getDriver(league.ownerId); let owner: DriverSummaryViewModel | null = null; if (ownerDriver) { const ownerStats = leaderboardByDriverId.get(ownerDriver.id); owner = new DriverSummaryViewModel({ driver: ownerDriver, rating: ownerStats?.rating ?? null, rank: ownerStats?.rank ?? null, }); } // Get members const membershipsDto = await this.leaguesApiClient.getMemberships(leagueId); const members: DriverSummaryViewModel[] = []; for (const member of membershipsDto.members) { if (member.driverId !== league.ownerId && member.role !== 'owner') { const driver = await this.driversApiClient.getDriver(member.driverId); if (driver) { const memberStats = leaderboardByDriverId.get(driver.id); members.push(new DriverSummaryViewModel({ driver, rating: memberStats?.rating ?? null, rank: memberStats?.rank ?? null, })); } } } return new LeagueSettingsViewModel({ league, config, presets, owner, members, }); } catch (error) { console.error('Failed to load league settings:', error); return null; } } /** * Transfer league ownership */ async transferOwnership(leagueId: string, currentOwnerId: string, newOwnerId: string): Promise { try { const result = await this.leaguesApiClient.transferOwnership(leagueId, currentOwnerId, newOwnerId); return result.success; } catch (error) { console.error('Failed to transfer ownership:', error); throw error; } } }