import { v4 as uuidv4 } from 'uuid';
import { League } from '../../domain/entities/League';
import { Season } from '../../domain/entities/Season';
import type { ILeagueRepository } from '../../domain/repositories/ILeagueRepository';
import type { ISeasonRepository } from '../../domain/repositories/ISeasonRepository';
import type { ILeagueScoringConfigRepository } from '../../domain/repositories/ILeagueScoringConfigRepository';
import type { AsyncUseCase } from '@core/shared/application';
import type { Logger } from '@core/shared/application';
import type {
  LeagueScoringPresetProvider,
  LeagueScoringPresetDTO,
} from '../ports/LeagueScoringPresetProvider';
import {
  LeagueVisibility,
  MIN_RANKED_LEAGUE_DRIVERS,
} from '../../domain/value-objects/LeagueVisibility';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { LeagueVisibilityInput } from '../dto/LeagueVisibilityInput';
import type { CreateLeagueWithSeasonAndScoringResultDTO } from '../dto/CreateLeagueWithSeasonAndScoringResultDTO';

export interface CreateLeagueWithSeasonAndScoringCommand {
  name: string;
  description?: string;
  /**
   * League visibility/ranking mode.
   * - 'ranked' (or legacy 'public'): Competitive, public, affects ratings. Requires min 10 drivers.
   * - 'unranked' (or legacy 'private'): Casual with friends, no rating impact.
   */
  visibility: LeagueVisibilityInput;
  ownerId: string;
  gameId: string;
  maxDrivers?: number;
  maxTeams?: number;
  enableDriverChampionship: boolean;
  enableTeamChampionship: boolean;
  enableNationsChampionship: boolean;
  enableTrophyChampionship: boolean;
  scoringPresetId?: string;
}

export class CreateLeagueWithSeasonAndScoringUseCase
  implements AsyncUseCase<CreateLeagueWithSeasonAndScoringCommand, CreateLeagueWithSeasonAndScoringResultDTO, 'VALIDATION_ERROR' | 'UNKNOWN_PRESET' | 'REPOSITORY_ERROR'> {
  constructor(
    private readonly leagueRepository: ILeagueRepository,
    private readonly seasonRepository: ISeasonRepository,
    private readonly leagueScoringConfigRepository: ILeagueScoringConfigRepository,
    private readonly presetProvider: LeagueScoringPresetProvider,
    private readonly logger: Logger,
  ) {}

  async execute(
    command: CreateLeagueWithSeasonAndScoringCommand,
  ): Promise<Result<CreateLeagueWithSeasonAndScoringResultDTO, ApplicationErrorCode<'VALIDATION_ERROR' | 'UNKNOWN_PRESET' | 'REPOSITORY_ERROR', { message: string }>>> {
    this.logger.debug('Executing CreateLeagueWithSeasonAndScoringUseCase', { command });
    const validation = this.validate(command);
    if (validation.isErr()) {
      return Result.err(validation.unwrapErr());
    }
    this.logger.info('Command validated successfully.');
    try {

      const leagueId = uuidv4();
      this.logger.debug(`Generated leagueId: ${leagueId}`);

      const league = League.create({
        id: leagueId,
        name: command.name,
        description: command.description ?? '',
        ownerId: command.ownerId,
        settings: {
          pointsSystem: 'custom',
          ...(command.maxDrivers !== undefined ? { maxDrivers: command.maxDrivers } : {}),
        },
      });

      await this.leagueRepository.create(league);
      this.logger.info(`League ${league.name} (${league.id}) created successfully.`);

      const seasonId = uuidv4();
      this.logger.debug(`Generated seasonId: ${seasonId}`);
      const season = Season.create({
        id: seasonId,
        leagueId: league.id.toString(),
        gameId: command.gameId,
        name: `${command.name} Season 1`,
        year: new Date().getFullYear(),
        order: 1,
        status: 'active',
        startDate: new Date(),
        endDate: new Date(),
      });

      await this.seasonRepository.create(season);
      this.logger.info(`Season ${season.name} (${season.id}) created for league ${league.id}.`);

      const presetId = command.scoringPresetId ?? 'club-default';
      this.logger.debug(`Attempting to retrieve scoring preset: ${presetId}`);
      const preset: LeagueScoringPresetDTO | undefined =
        this.presetProvider.getPresetById(presetId);

      if (!preset) {
        this.logger.error(`Unknown scoring preset: ${presetId}`);
        return Result.err({ code: 'UNKNOWN_PRESET', details: { message: `Unknown scoring preset: ${presetId}` } });
      }
      this.logger.info(`Scoring preset ${preset.name} (${preset.id}) retrieved.`);


      const finalConfig = this.presetProvider.createScoringConfigFromPreset(preset.id, seasonId);
      this.logger.debug(`Scoring configuration created from preset ${preset.id}.`);

      await this.leagueScoringConfigRepository.save(finalConfig);
      this.logger.info(`Scoring configuration saved for season ${seasonId}.`);

      const result: CreateLeagueWithSeasonAndScoringResultDTO = {
        leagueId: league.id.toString(),
        seasonId,
        scoringPresetId: preset.id,
        scoringPresetName: preset.name,
      };
      this.logger.debug('CreateLeagueWithSeasonAndScoringUseCase completed successfully.', { result });
      return Result.ok(result);
    } catch (error) {
      return Result.err({ code: 'REPOSITORY_ERROR', details: { message: error instanceof Error ? error.message : 'Unknown error' } });
    }
  }

  private validate(command: CreateLeagueWithSeasonAndScoringCommand): Result<void, ApplicationErrorCode<'VALIDATION_ERROR', { message: string }>> {
    this.logger.debug('Validating CreateLeagueWithSeasonAndScoringCommand', { command });
    if (!command.name || command.name.trim().length === 0) {
      this.logger.warn('Validation failed: League name is required', { command });
      return Result.err({ code: 'VALIDATION_ERROR', details: { message: 'League name is required' } });
    }
    if (!command.ownerId || command.ownerId.trim().length === 0) {
      this.logger.warn('Validation failed: League ownerId is required', { command });
      return Result.err({ code: 'VALIDATION_ERROR', details: { message: 'League ownerId is required' } });
    }
    if (!command.gameId || command.gameId.trim().length === 0) {
      this.logger.warn('Validation failed: gameId is required', { command });
      return Result.err({ code: 'VALIDATION_ERROR', details: { message: 'gameId is required' } });
    }
    if (!command.visibility) {
      this.logger.warn('Validation failed: visibility is required', { command });
      return Result.err({ code: 'VALIDATION_ERROR', details: { message: 'visibility is required' } });
    }
    if (command.maxDrivers !== undefined && command.maxDrivers <= 0) {
      this.logger.warn('Validation failed: maxDrivers must be greater than 0 when provided', { command });
      return Result.err({ code: 'VALIDATION_ERROR', details: { message: 'maxDrivers must be greater than 0 when provided' } });
    }

    const visibility = LeagueVisibility.fromString(command.visibility);

    if (visibility.isRanked()) {
      const driverCount = command.maxDrivers ?? 0;
      if (driverCount < MIN_RANKED_LEAGUE_DRIVERS) {
        this.logger.warn(
          `Validation failed: Ranked leagues require at least ${MIN_RANKED_LEAGUE_DRIVERS} drivers. Current setting: ${driverCount}.`,
          { command }
        );
        return Result.err({ code: 'VALIDATION_ERROR', details: { message:
          `Ranked leagues require at least ${MIN_RANKED_LEAGUE_DRIVERS} drivers. ` +
          `Current setting: ${driverCount}. ` +
          `For smaller groups, consider creating an Unranked (Friends) league instead.`
        } });
      }
    }
    this.logger.debug('Validation successful.');
    return Result.ok(undefined);
  }
}