import type { GetLeagueFullConfigResult } from '@core/racing/application/use-cases/GetLeagueFullConfigUseCase';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
import { LeagueConfigFormModelDTO } from '../dtos/LeagueConfigFormModelDTO';

export class LeagueConfigPresenter implements UseCaseOutputPort<GetLeagueFullConfigResult> {
  private result: LeagueConfigFormModelDTO | null = null;

  reset() {
    this.result = null;
  }

  present(result: GetLeagueFullConfigResult): void {
    const dto = result.config as unknown as {
      league: { id: string; name: string; description: string; settings: { pointsSystem: string; visibility: string } };
      activeSeason?: {
        stewardingConfig?: {
          decisionMode: string;
          requireDefense: boolean;
          defenseTimeLimit: number;
          voteTimeLimit: number;
          protestDeadlineHours: number;
          stewardingClosesHours: number;
          notifyAccusedOnProtest: boolean;
          notifyOnVoteRequired: boolean;
          requiredVotes?: number;
        };
        dropPolicy?: { strategy: string; n?: number };
        schedule?: {
          startDate?: Date;
          timeOfDay?: { hour: number; minute: number };
        };
      };
      scoringConfig?: { championships: { sessionTypes: string[]; pointsTableBySessionType: Record<string, { getPointsForPosition: (pos: number) => number }> }[] };
    };
    const league = dto.league;
    const settings = league.settings;
    const stewarding = dto.activeSeason?.stewardingConfig;
    const dropPolicy = dto.activeSeason?.dropPolicy;
    const schedule = dto.activeSeason?.schedule;
    const scoringConfig = dto.scoringConfig;

    const visibility: 'ranked' | 'unranked' | 'private' = settings.visibility as 'ranked' | 'unranked' | 'private';

    const championships = scoringConfig?.championships ?? [];

    const firstChampionship = championships[0];
    const firstSessionType = firstChampionship?.sessionTypes[0];
    const firstPointsTable = firstSessionType
      ? firstChampionship.pointsTableBySessionType[firstSessionType]
      : undefined;
    const pointsForWin = firstPointsTable?.getPointsForPosition(1) ?? 0;

    const raceDayOfWeek = schedule?.startDate
      ? schedule.startDate.toLocaleDateString('en-US', { weekday: 'long' }).toLowerCase()
      : 'sunday';
    const raceTimeHour = schedule?.timeOfDay?.hour ?? 20;
    const raceTimeMinute = schedule?.timeOfDay?.minute ?? 0;

    this.result = {
      leagueId: league.id,
      basics: {
        name: league.name,
        description: league.description,
        visibility,
      },
      structure: {
        mode: 'solo',
      },
      championships,
      scoring: {
        type: settings.pointsSystem,
        points: pointsForWin,
      },
      dropPolicy: {
        strategy: dropPolicy?.strategy === 'none' ? 'none' : 'worst_n',
        ...(dropPolicy?.n !== undefined ? { n: dropPolicy.n } : {}),
      },
      timings: {
        raceDayOfWeek,
        raceTimeHour,
        raceTimeMinute,
      },
      stewarding: {
        decisionMode: stewarding?.decisionMode === 'steward_vote' ? 'committee_vote' : 'single_steward',
        requireDefense: stewarding?.requireDefense ?? false,
        defenseTimeLimit: stewarding?.defenseTimeLimit ?? 48,
        voteTimeLimit: stewarding?.voteTimeLimit ?? 72,
        protestDeadlineHours: stewarding?.protestDeadlineHours ?? 48,
        stewardingClosesHours: stewarding?.stewardingClosesHours ?? 168,
        notifyAccusedOnProtest: stewarding?.notifyAccusedOnProtest ?? true,
        notifyOnVoteRequired: stewarding?.notifyOnVoteRequired ?? true,
        ...(stewarding?.requiredVotes !== undefined ? { requiredVotes: stewarding.requiredVotes } : {}),
      },
    };
  }

  getViewModel(): LeagueConfigFormModelDTO | null {
    return this.result;
  }
}