import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository';
import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';

export interface GetSeasonDetailsQuery {
  leagueId: string;
  seasonId: string;
}

export interface SeasonDetailsDTO {
  seasonId: string;
  leagueId: string;
  gameId: string;
  name: string;
  status: import('../../domain/entities/Season').SeasonStatus;
  startDate?: Date;
  endDate?: Date;
  maxDrivers?: number;
  schedule?: {
    startDate: Date;
    plannedRounds: number;
  };
  scoring?: {
    scoringPresetId: string;
    customScoringEnabled: boolean;
  };
  dropPolicy?: {
    strategy: import('../../domain/value-objects/SeasonDropPolicy').SeasonDropStrategy;
    n?: number;
  };
  stewarding?: {
    decisionMode: import('../../domain/entities/League').StewardingDecisionMode;
    requiredVotes?: number;
    requireDefense: boolean;
    defenseTimeLimit: number;
    voteTimeLimit: number;
    protestDeadlineHours: number;
    stewardingClosesHours: number;
    notifyAccusedOnProtest: boolean;
    notifyOnVoteRequired: boolean;
  };
}

type GetSeasonDetailsErrorCode = 'LEAGUE_NOT_FOUND' | 'SEASON_NOT_FOUND';

/**
 * GetSeasonDetailsUseCase
 */
export class GetSeasonDetailsUseCase {
  constructor(
    private readonly leagueRepository: ILeagueRepository,
    private readonly seasonRepository: ISeasonRepository,
  ) {}

  async execute(query: GetSeasonDetailsQuery): Promise<Result<SeasonDetailsDTO, ApplicationErrorCode<GetSeasonDetailsErrorCode>>> {
    const league = await this.leagueRepository.findById(query.leagueId);
    if (!league) {
      return Result.err({
        code: 'LEAGUE_NOT_FOUND',
        details: { message: `League not found: ${query.leagueId}` },
      });
    }

    const season = await this.seasonRepository.findById(query.seasonId);
    if (!season || season.leagueId !== league.id) {
      return Result.err({
        code: 'SEASON_NOT_FOUND',
        details: { message: `Season ${query.seasonId} does not belong to league ${league.id}` },
      });
    }

    return Result.ok({
      seasonId: season.id,
      leagueId: season.leagueId,
      gameId: season.gameId,
      name: season.name,
      status: season.status,
      ...(season.startDate !== undefined ? { startDate: season.startDate } : {}),
      ...(season.endDate !== undefined ? { endDate: season.endDate } : {}),
      ...(season.maxDrivers !== undefined ? { maxDrivers: season.maxDrivers } : {}),
      ...(season.schedule
        ? {
            schedule: {
              startDate: season.schedule.startDate,
              plannedRounds: season.schedule.plannedRounds,
            },
          }
        : {}),
      ...(season.scoringConfig
        ? {
            scoring: {
              scoringPresetId: season.scoringConfig.scoringPresetId,
              customScoringEnabled:
                season.scoringConfig.customScoringEnabled ?? false,
            },
          }
        : {}),
      ...(season.dropPolicy
        ? {
            dropPolicy: {
              strategy: season.dropPolicy.strategy,
              ...(season.dropPolicy.n !== undefined
                ? { n: season.dropPolicy.n }
                : {}),
            },
          }
        : {}),
      ...(season.stewardingConfig
        ? {
            stewarding: {
              decisionMode: season.stewardingConfig.decisionMode,
              ...(season.stewardingConfig.requiredVotes !== undefined
                ? { requiredVotes: season.stewardingConfig.requiredVotes }
                : {}),
              requireDefense: season.stewardingConfig.requireDefense,
              defenseTimeLimit: season.stewardingConfig.defenseTimeLimit,
              voteTimeLimit: season.stewardingConfig.voteTimeLimit,
              protestDeadlineHours:
                season.stewardingConfig.protestDeadlineHours,
              stewardingClosesHours:
                season.stewardingConfig.stewardingClosesHours,
              notifyAccusedOnProtest:
                season.stewardingConfig.notifyAccusedOnProtest,
              notifyOnVoteRequired:
                season.stewardingConfig.notifyOnVoteRequired,
            },
          }
        : {}),
    });
  }
}