import { Module } from '@nestjs/common';

import { LoggingModule } from '../../domain/logging/LoggingModule';

import type { Logger } from '@core/shared/application/Logger';

import type { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository';
import type { ILeagueRepository } from '@core/racing/domain/repositories/ILeagueRepository';
import type { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository';
import type { IResultRepository } from '@core/racing/domain/repositories/IResultRepository';
import type { IStandingRepository } from '@core/racing/domain/repositories/IStandingRepository';
import type { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
import type { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository';
import type { IPenaltyRepository } from '@core/racing/domain/repositories/IPenaltyRepository';
import type { IProtestRepository } from '@core/racing/domain/repositories/IProtestRepository';
import type { ISeasonRepository } from '@core/racing/domain/repositories/ISeasonRepository';
import type { ISeasonSponsorshipRepository } from '@core/racing/domain/repositories/ISeasonSponsorshipRepository';
import type { ILeagueScoringConfigRepository } from '@core/racing/domain/repositories/ILeagueScoringConfigRepository';
import type { IGameRepository } from '@core/racing/domain/repositories/IGameRepository';
import type { ILeagueWalletRepository } from '@core/racing/domain/repositories/ILeagueWalletRepository';
import type { ITransactionRepository } from '@core/racing/domain/repositories/ITransactionRepository';
import type { ISponsorRepository } from '@core/racing/domain/repositories/ISponsorRepository';
import type { ISponsorshipPricingRepository } from '@core/racing/domain/repositories/ISponsorshipPricingRepository';
import type { ISponsorshipRequestRepository } from '@core/racing/domain/repositories/ISponsorshipRequestRepository';
import type { ITeamRepository } from '@core/racing/domain/repositories/ITeamRepository';
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
import type { IDriverStatsRepository } from '@core/racing/domain/repositories/IDriverStatsRepository';
import type { ITeamStatsRepository } from '@core/racing/domain/repositories/ITeamStatsRepository';
import type { IMediaRepository } from '@core/racing/domain/repositories/IMediaRepository';

import { getPointsSystems } from '@adapters/bootstrap/PointsSystems';

import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryLeagueRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryRaceRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRepository';
import { InMemoryResultRepository } from '@adapters/racing/persistence/inmemory/InMemoryResultRepository';
import { InMemoryStandingRepository } from '@adapters/racing/persistence/inmemory/InMemoryStandingRepository';
import { InMemoryLeagueMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository';
import { InMemoryRaceRegistrationRepository } from '@adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository';
import { InMemoryTeamRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamRepository';
import { InMemoryTeamMembershipRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository';
import { InMemoryPenaltyRepository } from '@adapters/racing/persistence/inmemory/InMemoryPenaltyRepository';
import { InMemoryProtestRepository } from '@adapters/racing/persistence/inmemory/InMemoryProtestRepository';
import { InMemorySeasonRepository } from '@adapters/racing/persistence/inmemory/InMemorySeasonRepository';
import { InMemorySeasonSponsorshipRepository } from '@adapters/racing/persistence/inmemory/InMemorySeasonSponsorshipRepository';
import { InMemoryLeagueScoringConfigRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueScoringConfigRepository';
import { InMemoryGameRepository } from '@adapters/racing/persistence/inmemory/InMemoryGameRepository';
import { InMemoryLeagueWalletRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueWalletRepository';
import { InMemoryTransactionRepository } from '@adapters/racing/persistence/inmemory/InMemoryTransactionRepository';
import { InMemorySponsorRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorRepository';
import { InMemorySponsorshipPricingRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorshipPricingRepository';
import { InMemorySponsorshipRequestRepository } from '@adapters/racing/persistence/inmemory/InMemorySponsorshipRequestRepository';
import { InMemoryDriverStatsRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverStatsRepository';
import { InMemoryTeamStatsRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamStatsRepository';
import { InMemoryMediaRepository } from '@adapters/racing/persistence/media/InMemoryMediaRepository';

export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
export const RESULT_REPOSITORY_TOKEN = 'IResultRepository';
export const STANDING_REPOSITORY_TOKEN = 'IStandingRepository';
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
export const RACE_REGISTRATION_REPOSITORY_TOKEN = 'IRaceRegistrationRepository';
export const TEAM_REPOSITORY_TOKEN = 'ITeamRepository';
export const TEAM_MEMBERSHIP_REPOSITORY_TOKEN = 'ITeamMembershipRepository';
export const PENALTY_REPOSITORY_TOKEN = 'IPenaltyRepository';
export const PROTEST_REPOSITORY_TOKEN = 'IProtestRepository';
export const SEASON_REPOSITORY_TOKEN = 'ISeasonRepository';
export const SEASON_SPONSORSHIP_REPOSITORY_TOKEN = 'ISeasonSponsorshipRepository';
export const LEAGUE_SCORING_CONFIG_REPOSITORY_TOKEN = 'ILeagueScoringConfigRepository';
export const GAME_REPOSITORY_TOKEN = 'IGameRepository';
export const LEAGUE_WALLET_REPOSITORY_TOKEN = 'ILeagueWalletRepository';
export const TRANSACTION_REPOSITORY_TOKEN = 'ITransactionRepository';
export const SPONSOR_REPOSITORY_TOKEN = 'ISponsorRepository';
export const SPONSORSHIP_PRICING_REPOSITORY_TOKEN = 'ISponsorshipPricingRepository';
export const SPONSORSHIP_REQUEST_REPOSITORY_TOKEN = 'ISponsorshipRequestRepository';
export const DRIVER_STATS_REPOSITORY_TOKEN = 'IDriverStatsRepository';
export const TEAM_STATS_REPOSITORY_TOKEN = 'ITeamStatsRepository';
export const MEDIA_REPOSITORY_TOKEN = 'IMediaRepository';

@Module({
  imports: [LoggingModule],
  providers: [
    {
      provide: DRIVER_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): IDriverRepository => new InMemoryDriverRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: LEAGUE_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ILeagueRepository => new InMemoryLeagueRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: RACE_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): IRaceRepository => new InMemoryRaceRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: RESULT_REPOSITORY_TOKEN,
      useFactory: (logger: Logger, raceRepo: IRaceRepository): IResultRepository =>
        new InMemoryResultRepository(logger, raceRepo),
      inject: ['Logger', RACE_REPOSITORY_TOKEN],
    },
    {
      provide: STANDING_REPOSITORY_TOKEN,
      useFactory: (
        logger: Logger,
        resultRepo: IResultRepository,
        raceRepo: IRaceRepository,
        leagueRepo: ILeagueRepository,
      ): IStandingRepository => new InMemoryStandingRepository(logger, getPointsSystems(), resultRepo, raceRepo, leagueRepo),
      inject: ['Logger', RESULT_REPOSITORY_TOKEN, RACE_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
    },
    {
      provide: LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ILeagueMembershipRepository => new InMemoryLeagueMembershipRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: RACE_REGISTRATION_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): IRaceRegistrationRepository => new InMemoryRaceRegistrationRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: TEAM_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ITeamRepository => new InMemoryTeamRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ITeamMembershipRepository => new InMemoryTeamMembershipRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: PENALTY_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): IPenaltyRepository => new InMemoryPenaltyRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: PROTEST_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): IProtestRepository => new InMemoryProtestRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: SEASON_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ISeasonRepository => new InMemorySeasonRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: SEASON_SPONSORSHIP_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ISeasonSponsorshipRepository => new InMemorySeasonSponsorshipRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: LEAGUE_SCORING_CONFIG_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ILeagueScoringConfigRepository => new InMemoryLeagueScoringConfigRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: GAME_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): IGameRepository => new InMemoryGameRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: LEAGUE_WALLET_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ILeagueWalletRepository => new InMemoryLeagueWalletRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: TRANSACTION_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ITransactionRepository => new InMemoryTransactionRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: SPONSOR_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ISponsorRepository => new InMemorySponsorRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: SPONSORSHIP_PRICING_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ISponsorshipPricingRepository => new InMemorySponsorshipPricingRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: SPONSORSHIP_REQUEST_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ISponsorshipRequestRepository => new InMemorySponsorshipRequestRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: DRIVER_STATS_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): IDriverStatsRepository => new InMemoryDriverStatsRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: TEAM_STATS_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): ITeamStatsRepository => new InMemoryTeamStatsRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: MEDIA_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): IMediaRepository => new InMemoryMediaRepository(logger),
      inject: ['Logger'],
    },
  ],
  exports: [
    DRIVER_REPOSITORY_TOKEN,
    LEAGUE_REPOSITORY_TOKEN,
    RACE_REPOSITORY_TOKEN,
    RESULT_REPOSITORY_TOKEN,
    STANDING_REPOSITORY_TOKEN,
    LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
    RACE_REGISTRATION_REPOSITORY_TOKEN,
    TEAM_REPOSITORY_TOKEN,
    TEAM_MEMBERSHIP_REPOSITORY_TOKEN,
    PENALTY_REPOSITORY_TOKEN,
    PROTEST_REPOSITORY_TOKEN,
    SEASON_REPOSITORY_TOKEN,
    SEASON_SPONSORSHIP_REPOSITORY_TOKEN,
    LEAGUE_SCORING_CONFIG_REPOSITORY_TOKEN,
    GAME_REPOSITORY_TOKEN,
    LEAGUE_WALLET_REPOSITORY_TOKEN,
    TRANSACTION_REPOSITORY_TOKEN,
    SPONSOR_REPOSITORY_TOKEN,
    SPONSORSHIP_PRICING_REPOSITORY_TOKEN,
    SPONSORSHIP_REQUEST_REPOSITORY_TOKEN,
    DRIVER_STATS_REPOSITORY_TOKEN,
    TEAM_STATS_REPOSITORY_TOKEN,
    MEDIA_REPOSITORY_TOKEN,
  ],
})
export class InMemoryRacingPersistenceModule {}