import type {
  ILeagueDriverSeasonStatsPresenter,
  LeagueDriverSeasonStatsItemViewModel,
  LeagueDriverSeasonStatsViewModel,
  LeagueDriverSeasonStatsResultDTO,
} from '@core/racing/application/presenters/ILeagueDriverSeasonStatsPresenter';

export class LeagueDriverSeasonStatsPresenter implements ILeagueDriverSeasonStatsPresenter {
  private viewModel: LeagueDriverSeasonStatsViewModel | null = null;

  reset(): void {
    this.viewModel = null;
  }

  present(dto: LeagueDriverSeasonStatsResultDTO): void {
    const { leagueId, standings, penalties, driverResults, driverRatings } = dto;

    const stats: LeagueDriverSeasonStatsItemViewModel[] = standings.map((standing) => {
      const penalty = penalties.get(standing.driverId) ?? { baseDelta: 0, bonusDelta: 0 };
      const totalPenaltyPoints = penalty.baseDelta;
      const bonusPoints = penalty.bonusDelta;

      const racesCompleted = standing.racesCompleted;
      const pointsPerRace = racesCompleted > 0 ? standing.points / racesCompleted : 0;

      const ratingInfo = driverRatings.get(standing.driverId) ?? { rating: null, ratingChange: null };

      const results = driverResults.get(standing.driverId) ?? [];
      let avgFinish: number | null = null;
      if (results.length > 0) {
        const totalPositions = results.reduce((sum, r) => sum + r.position, 0);
        const avg = totalPositions / results.length;
        avgFinish = Number.isFinite(avg) ? Number(avg.toFixed(2)) : null;
      }

      return {
        leagueId,
        driverId: standing.driverId,
        position: standing.position,
        driverName: '',
        teamId: '',
        teamName: '',
        totalPoints: standing.points + totalPenaltyPoints + bonusPoints,
        basePoints: standing.points,
        penaltyPoints: Math.abs(totalPenaltyPoints),
        bonusPoints,
        pointsPerRace,
        racesStarted: results.length,
        racesFinished: results.length,
        dnfs: 0,
        noShows: 0,
        avgFinish,
        rating: ratingInfo.rating,
        ratingChange: ratingInfo.ratingChange,
      };
    });

    stats.sort((a, b) => a.position - b.position);

    this.viewModel = {
      leagueId,
      stats,
    };
  }

  getViewModel(): LeagueDriverSeasonStatsViewModel {
    if (!this.viewModel) {
      throw new Error('Presenter has not been called yet');
    }
    return this.viewModel;
  }
}