import type { ITeamRepository } from '../../domain/repositories/ITeamRepository'; import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository'; import type { ITeamStatsRepository } from '../../domain/repositories/ITeamStatsRepository'; import type { IResultRepository } from '../../domain/repositories/IResultRepository'; import type { Logger } from '@core/shared/application'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort'; import { MediaReference } from '@core/domain/media/MediaReference'; export type GetAllTeamsInput = {}; export type GetAllTeamsErrorCode = 'REPOSITORY_ERROR'; export interface TeamSummary { id: string; name: string; tag: string; description: string; ownerId: string; leagues: string[]; createdAt: Date; memberCount: number; totalWins?: number; totalRaces?: number; performanceLevel?: string; specialization?: string; region?: string; languages?: string[]; logoRef?: MediaReference; logoUrl?: string | null; rating?: number; category?: string | undefined; isRecruiting: boolean; } export interface GetAllTeamsResult { teams: TeamSummary[]; totalCount: number; } /** * Use Case for retrieving all teams. */ export class GetAllTeamsUseCase { constructor( private readonly teamRepository: ITeamRepository, private readonly teamMembershipRepository: ITeamMembershipRepository, private readonly teamStatsRepository: ITeamStatsRepository, private readonly resultRepository: IResultRepository, private readonly logger: Logger, private readonly output: UseCaseOutputPort, ) {} async execute( _input: GetAllTeamsInput = {}, ): Promise>> { void _input; this.logger.debug('Executing GetAllTeamsUseCase'); try { const teams = await this.teamRepository.findAll(); const enrichedTeams: TeamSummary[] = await Promise.all( teams.map(async (team) => { const memberCount = await this.teamMembershipRepository.countByTeamId(team.id); // Get logo reference from team entity const logoRef = team.logoRef; // Try to get pre-computed stats first let stats = await this.teamStatsRepository.getTeamStats(team.id); // If no pre-computed stats, compute them on-the-fly from results if (!stats) { this.logger.debug(`Computing stats for team ${team.id} on-the-fly`); const teamMemberships = await this.teamMembershipRepository.getTeamMembers(team.id); const teamMemberIds = teamMemberships.map(m => m.driverId.toString()); const allResults = await this.resultRepository.findAll(); const teamResults = allResults.filter(r => teamMemberIds.includes(r.driverId.toString())); const wins = teamResults.filter(r => r.position.toNumber() === 1).length; const totalRaces = teamResults.length; // Calculate rating const baseRating = 1000; const winBonus = wins * 50; const raceBonus = Math.min(totalRaces * 5, 200); const rating = Math.round(baseRating + winBonus + raceBonus); // Determine performance level let performanceLevel: 'beginner' | 'intermediate' | 'advanced' | 'pro'; if (wins >= 20) performanceLevel = 'pro'; else if (wins >= 10) performanceLevel = 'advanced'; else if (wins >= 5) performanceLevel = 'intermediate'; else performanceLevel = 'beginner'; stats = { performanceLevel, specialization: 'mixed', region: 'International', languages: ['en'], totalWins: wins, totalRaces, rating, }; } return { id: team.id, name: team.name.props, tag: team.tag.props, description: team.description.props, ownerId: team.ownerId.toString(), leagues: team.leagues.map(l => l.toString()), createdAt: team.createdAt.toDate(), memberCount, totalWins: stats!.totalWins, totalRaces: stats!.totalRaces, performanceLevel: stats!.performanceLevel, specialization: stats!.specialization, region: stats!.region, languages: stats!.languages, logoRef: logoRef, logoUrl: null, // Will be resolved by presenter rating: stats!.rating, category: team.category, isRecruiting: team.isRecruiting, }; }), ); const result: GetAllTeamsResult = { teams: enrichedTeams, totalCount: enrichedTeams.length, }; this.logger.debug('Successfully retrieved all teams.'); this.output.present(result); return Result.ok(undefined); } catch (error) { this.logger.error('Error retrieving all teams', error instanceof Error ? error : new Error(String(error))); return Result.err({ code: 'REPOSITORY_ERROR', details: { message: error instanceof Error ? error.message : 'Failed to load teams' }, }); } } }