import { ChampionshipStanding } from '@core/racing/domain/entities/championship/ChampionshipStanding';
import { Game } from '@core/racing/domain/entities/Game';
import type { LeagueScoringConfig } from '@core/racing/domain/entities/LeagueScoringConfig';
import { Season } from '@core/racing/domain/entities/season/Season';
import type { ChampionshipStandingRepository } from '@core/racing/domain/repositories/ChampionshipStandingRepository';
import type { GameRepository } from '@core/racing/domain/repositories/GameRepository';
import type { LeagueScoringConfigRepository } from '@core/racing/domain/repositories/LeagueScoringConfigRepository';
import type { SeasonRepository } from '@core/racing/domain/repositories/SeasonRepository';
import type { Logger } from '@core/shared/domain/Logger';


export class InMemoryGameRepository implements GameRepository {
  private games: Game[];
  private readonly logger: Logger;

  constructor(logger: Logger, seedData?: Game[]) {
    this.logger = logger;
    this.logger.info('InMemoryGameRepository initialized.');
    this.games = seedData ? [...seedData] : [];
  }

  async findById(id: string): Promise<Game | null> {
    this.logger.debug(`Finding game by id: ${id}`);
    try {
      const game = this.games.find((g) => g.id.toString() === id) ?? null;
      if (game) {
        this.logger.info(`Found game: ${game.id}`);
      } else {
        this.logger.warn(`Game with id ${id} not found.`);
      }
      return game;
    } catch (error) {
      this.logger.error(`Error finding game by id ${id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async findAll(): Promise<Game[]> {
    this.logger.debug('Finding all games.');
    try {
      const games = [...this.games];
      this.logger.info(`Found ${games.length} games.`);
      return games;
    } catch (error) {
      this.logger.error('Error finding all games:', error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  seed(game: Game): void {
    this.logger.debug(`Seeding game: ${game.id}`);
    try {
      this.games.push(game);
      this.logger.info(`Game ${game.id} seeded successfully.`);
    } catch (error) {
      this.logger.error(`Error seeding game ${game.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }
}

export class InMemorySeasonRepository implements SeasonRepository {
  private seasons: Season[];
  private readonly logger: Logger;

  constructor(logger: Logger, seedData?: Season[]) {
    this.logger = logger;
    this.logger.info('InMemorySeasonRepository initialized.');
    this.seasons = seedData ? [...seedData] : [];
  }

  async findById(id: string): Promise<Season | null> {
    this.logger.debug(`Finding season by id: ${id}`);
    try {
      const season = this.seasons.find((s) => s.id === id) ?? null;
      if (season) {
        this.logger.info(`Found season: ${season.id}`);
      } else {
        this.logger.warn(`Season with id ${id} not found.`);
      }
      return season;
    } catch (error) {
      this.logger.error(`Error finding season by id ${id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async findByLeagueId(leagueId: string): Promise<Season[]> {
    this.logger.debug(`Finding seasons by league id: ${leagueId}`);
    try {
      const seasons = this.seasons.filter((s) => s.leagueId === leagueId);
      this.logger.info(`Found ${seasons.length} seasons for league id: ${leagueId}.`);
      return seasons;
    } catch (error) {
      this.logger.error(`Error finding seasons by league id ${leagueId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async create(season: Season): Promise<Season> {
    this.logger.debug(`Creating season: ${season.id}`);
    try {
      // Backward-compatible alias for add()
      this.seasons.push(season);
      this.logger.info(`Season ${season.id} created successfully.`);
      return season;
    } catch (error) {
      this.logger.error(`Error creating season ${season.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async add(season: Season): Promise<void> {
    this.logger.debug(`Adding season: ${season.id}`);
    try {
      this.seasons.push(season);
      this.logger.info(`Season ${season.id} added successfully.`);
    } catch (error) {
      this.logger.error(`Error adding season ${season.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async update(season: Season): Promise<void> {
    this.logger.debug(`Updating season: ${season.id}`);
    try {
      const index = this.seasons.findIndex((s) => s.id === season.id);
      if (index === -1) {
        this.logger.warn(`Season with id ${season.id} not found for update. Adding as new.`);
        this.seasons.push(season);
        return;
      }
      this.seasons[index] = season;
      this.logger.info(`Season ${season.id} updated successfully.`);
    } catch (error) {
      this.logger.error(`Error updating season ${season.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async listByLeague(leagueId: string): Promise<Season[]> {
    this.logger.debug(`Listing seasons by league id: ${leagueId}`);
    try {
      const seasons = this.seasons.filter((s) => s.leagueId === leagueId);
      this.logger.info(`Found ${seasons.length} seasons for league id: ${leagueId}.`);
      return seasons;
    } catch (error) {
      this.logger.error(`Error listing seasons by league id ${leagueId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async listActiveByLeague(leagueId: string): Promise<Season[]> {
    this.logger.debug(`Listing active seasons by league id: ${leagueId}`);
    try {
      const seasons = this.seasons.filter(
        (s) => s.leagueId === leagueId && s.status.isActive(),
      );
      this.logger.info(`Found ${seasons.length} active seasons for league id: ${leagueId}.`);
      return seasons;
    } catch (error) {
      this.logger.error(`Error listing active seasons by league id ${leagueId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  seed(season: Season): void {
    this.logger.debug(`Seeding season: ${season.id}`);
    try {
      this.seasons.push(season);
      this.logger.info(`Season ${season.id} seeded successfully.`);
    } catch (error) {
      this.logger.error(`Error seeding season ${season.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }
}

export class InMemoryLeagueScoringConfigRepository
  implements LeagueScoringConfigRepository
{
  private configs: LeagueScoringConfig[];
  private readonly logger: Logger;

  constructor(logger: Logger, seedData?: LeagueScoringConfig[]) {
    this.logger = logger;
    this.logger.info('InMemoryLeagueScoringConfigRepository initialized.');
    this.configs = seedData ? [...seedData] : [];
  }

  async findBySeasonId(seasonId: string): Promise<LeagueScoringConfig | null> {
    this.logger.debug(`Finding league scoring config by seasonId: ${seasonId}`);
    try {
      const config = this.configs.find((c) => c.seasonId.toString() === seasonId) ?? null;
      if (config) {
        this.logger.info(`Found league scoring config for seasonId: ${seasonId}.`);
      } else {
        this.logger.warn(`League scoring config for seasonId ${seasonId} not found.`);
      }
      return config;
    } catch (error) {
      this.logger.error(`Error finding league scoring config for seasonId ${seasonId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async save(config: LeagueScoringConfig): Promise<LeagueScoringConfig> {
    this.logger.debug(`Saving league scoring config: ${config.id} for seasonId: ${config.seasonId}`);
    try {
      const existingIndex = this.configs.findIndex(
        (c) => c.id === config.id,
      );
      if (existingIndex >= 0) {
        this.configs[existingIndex] = config;
        this.logger.info(`Updated existing league scoring config: ${config.id}.`);
      } else {
        this.configs.push(config);
        this.logger.info(`Created new league scoring config: ${config.id}.`);
      }
      return config;
    } catch (error) {
      this.logger.error(`Error saving league scoring config ${config.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  seed(config: LeagueScoringConfig): void {
    this.logger.debug(`Seeding league scoring config: ${config.id}`);
    try {
      this.configs.push(config);
      this.logger.info(`League scoring config ${config.id} seeded successfully.`);
    } catch (error) {
      this.logger.error(`Error seeding league scoring config ${config.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }
}

export class InMemoryChampionshipStandingRepository
  implements ChampionshipStandingRepository
{
  private standings: ChampionshipStanding[] = [];
  private readonly logger: Logger;

  constructor(logger: Logger, seedData?: ChampionshipStanding[]) {
    this.logger = logger;
    this.logger.info('InMemoryChampionshipStandingRepository initialized.');
    this.standings = seedData ? [...seedData] : [];
  }

  async findBySeasonAndChampionship(
    seasonId: string,
    championshipId: string,
  ): Promise<ChampionshipStanding[]> {
    this.logger.debug(`Finding championship standings for season: ${seasonId}, championship: ${championshipId}`);
    try {
      const standings = this.standings.filter(
        (s) => s.seasonId === seasonId && s.championshipId === championshipId,
      );
      this.logger.info(`Found ${standings.length} championship standings.`);
      return standings;
    } catch (error) {
      this.logger.error(`Error finding championship standings for season ${seasonId}, championship ${championshipId}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  async saveAll(standings: ChampionshipStanding[]): Promise<void> {
    this.logger.debug(`Saving ${standings.length} championship standings.`);
    try {
      this.standings = standings;
      this.logger.info(`${standings.length} championship standings saved.`);
    } catch (error) {
      this.logger.error(`Error saving championship standings:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  seed(standing: ChampionshipStanding): void {
    this.logger.debug(`Seeding championship standing: ${standing.id}`);
    try {
      this.standings.push(standing);
      this.logger.info(`Championship standing ${standing.id} seeded successfully.`);
    } catch (error) {
      this.logger.error(`Error seeding championship standing ${standing.id}:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  getAll(): ChampionshipStanding[] {
    this.logger.debug('Getting all championship standings.');
    try {
      const standings = [...this.standings];
      this.logger.info(`Retrieved ${standings.length} championship standings.`);
      return standings;
    } catch (error) {
      this.logger.error(`Error getting all championship standings:`, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }
}