import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository';
import type { ILeagueScoringConfigRepository } from '../../domain/repositories/ILeagueScoringConfigRepository';
import type { IGameRepository } from '../../domain/repositories/IGameRepository';
import type {
  ILeagueFullConfigPresenter,
  LeagueFullConfigData,
  LeagueConfigFormViewModel,
} from '../presenters/ILeagueFullConfigPresenter';
import type { AsyncUseCase } from '@core/shared/application';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';

/**
 * Use Case for retrieving a league's full configuration.
 * Orchestrates domain logic and delegates presentation to the presenter.
 */
export class GetLeagueFullConfigUseCase implements AsyncUseCase<{ leagueId: string }, LeagueConfigFormViewModel, 'LEAGUE_NOT_FOUND' | 'PRESENTATION_FAILED'> {
  constructor(
    private readonly leagueRepository: ILeagueRepository,
    private readonly seasonRepository: ISeasonRepository,
    private readonly leagueScoringConfigRepository: ILeagueScoringConfigRepository,
    private readonly gameRepository: IGameRepository,
    private readonly presenter: ILeagueFullConfigPresenter,
  ) {}

  async execute(params: { leagueId: string }): Promise<Result<LeagueConfigFormViewModel, ApplicationErrorCode<'LEAGUE_NOT_FOUND' | 'PRESENTATION_FAILED', { message: string }>>> {
    const { leagueId } = params;

    const league = await this.leagueRepository.findById(leagueId);
    if (!league) {
      return Result.err({ code: 'LEAGUE_NOT_FOUND', details: { message: `League with id ${leagueId} not found` } });
    }

    const seasons = await this.seasonRepository.findByLeagueId(leagueId);
    const activeSeason =
      seasons && seasons.length > 0
        ? seasons.find((s) => s.status === 'active') ?? seasons[0]
        : undefined;

    let scoringConfig = await (async () => {
      if (!activeSeason) return undefined;
      return this.leagueScoringConfigRepository.findBySeasonId(activeSeason.id);
    })();
    let game = await (async () => {
      if (!activeSeason || !activeSeason.gameId) return undefined;
      return this.gameRepository.findById(activeSeason.gameId);
    })();

    const data: LeagueFullConfigData = {
      league,
      ...(activeSeason ? { activeSeason } : {}),
      ...(scoringConfig ? { scoringConfig } : {}),
      ...(game ? { game } : {}),
    };

    this.presenter.reset();
    this.presenter.present(data);
    const viewModel = this.presenter.getViewModel();
    if (!viewModel) {
      return Result.err({ code: 'PRESENTATION_FAILED', details: { message: 'Failed to present league config' } });
    }

    return Result.ok(viewModel);
  }
}