import { Provider } from '@nestjs/common';
import { randomUUID } from 'crypto';
import { LeagueService } from './LeagueService';
import * as LeagueTokens from './LeagueTokens';

// Import core interfaces
import type { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository';
import type { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
import type { ILeagueRepository } from '@core/racing/domain/repositories/ILeagueRepository';
import type { IProtestRepository } from '@core/racing/domain/repositories/IProtestRepository';
import type { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository';
import type { ISeasonRepository } from '@core/racing/domain/repositories/ISeasonRepository';
import type { ISeasonSponsorshipRepository } from '@core/racing/domain/repositories/ISeasonSponsorshipRepository';
import type { IStandingRepository } from '@core/racing/domain/repositories/IStandingRepository';
import type { Logger } from '@core/shared/application/Logger';
import type { MediaResolverPort } from '@core/ports/media/MediaResolverPort';

// Import concrete in-memory implementations
import type { ILeagueWalletRepository } from "@core/racing/domain/repositories/ILeagueWalletRepository";
import type { ITransactionRepository } from "@core/racing/domain/repositories/ITransactionRepository";
import { getLeagueScoringPresetById, listLeagueScoringPresets } from '@adapters/bootstrap/LeagueScoringPresets';
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
import { InMemoryLeagueStandingsRepository } from '@adapters/racing/persistence/inmemory/InMemoryLeagueStandingsRepository';
import { MediaResolverAdapter } from '@adapters/media/MediaResolverAdapter';

// Import use cases
import { ApproveLeagueJoinRequestUseCase } from '@core/racing/application/use-cases/ApproveLeagueJoinRequestUseCase';
import { CreateLeagueWithSeasonAndScoringUseCase } from '@core/racing/application/use-cases/CreateLeagueWithSeasonAndScoringUseCase';
import { GetAllLeaguesWithCapacityUseCase } from '@core/racing/application/use-cases/GetAllLeaguesWithCapacityUseCase';
import { GetAllLeaguesWithCapacityAndScoringUseCase } from '@core/racing/application/use-cases/GetAllLeaguesWithCapacityAndScoringUseCase';
import { GetLeagueAdminPermissionsUseCase } from '@core/racing/application/use-cases/GetLeagueAdminPermissionsUseCase';
import { GetLeagueFullConfigUseCase } from '@core/racing/application/use-cases/GetLeagueFullConfigUseCase';
import { GetLeagueJoinRequestsUseCase } from '@core/racing/application/use-cases/GetLeagueJoinRequestsUseCase';
import { GetLeagueMembershipsUseCase } from '@core/racing/application/use-cases/GetLeagueMembershipsUseCase';
import { GetLeagueRosterMembersUseCase } from '@core/racing/application/use-cases/GetLeagueRosterMembersUseCase';
import { GetLeagueRosterJoinRequestsUseCase } from '@core/racing/application/use-cases/GetLeagueRosterJoinRequestsUseCase';
import { GetLeagueOwnerSummaryUseCase } from '@core/racing/application/use-cases/GetLeagueOwnerSummaryUseCase';
import { GetLeagueProtestsUseCase } from '@core/racing/application/use-cases/GetLeagueProtestsUseCase';
import { GetLeagueScheduleUseCase } from '@core/racing/application/use-cases/GetLeagueScheduleUseCase';
import { GetLeagueScoringConfigUseCase } from '@core/racing/application/use-cases/GetLeagueScoringConfigUseCase';
import { GetLeagueSeasonsUseCase } from '@core/racing/application/use-cases/GetLeagueSeasonsUseCase';
import { GetLeagueStandingsUseCase } from '@core/racing/application/use-cases/GetLeagueStandingsUseCase';
import { GetLeagueStatsUseCase } from '@core/racing/application/use-cases/GetLeagueStatsUseCase';
import { GetLeagueWalletUseCase } from '@core/racing/application/use-cases/GetLeagueWalletUseCase';
import { GetRaceProtestsUseCase } from '@core/racing/application/use-cases/GetRaceProtestsUseCase';
import { GetSeasonSponsorshipsUseCase } from '@core/racing/application/use-cases/GetSeasonSponsorshipsUseCase';
import { GetTotalLeaguesUseCase } from '@core/racing/application/use-cases/GetTotalLeaguesUseCase';
import { JoinLeagueUseCase } from '@core/racing/application/use-cases/JoinLeagueUseCase';
import { ListLeagueScoringPresetsUseCase } from '@core/racing/application/use-cases/ListLeagueScoringPresetsUseCase';
import { RejectLeagueJoinRequestUseCase } from '@core/racing/application/use-cases/RejectLeagueJoinRequestUseCase';
import { RemoveLeagueMemberUseCase } from '@core/racing/application/use-cases/RemoveLeagueMemberUseCase';
import { TransferLeagueOwnershipUseCase } from '@core/racing/application/use-cases/TransferLeagueOwnershipUseCase';
import { UpdateLeagueMemberRoleUseCase } from '@core/racing/application/use-cases/UpdateLeagueMemberRoleUseCase';
import { WithdrawFromLeagueWalletUseCase } from '@core/racing/application/use-cases/WithdrawFromLeagueWalletUseCase';

// Schedule mutation use cases
import { CreateLeagueSeasonScheduleRaceUseCase } from '@core/racing/application/use-cases/CreateLeagueSeasonScheduleRaceUseCase';
import { UpdateLeagueSeasonScheduleRaceUseCase } from '@core/racing/application/use-cases/UpdateLeagueSeasonScheduleRaceUseCase';
import { DeleteLeagueSeasonScheduleRaceUseCase } from '@core/racing/application/use-cases/DeleteLeagueSeasonScheduleRaceUseCase';
import { PublishLeagueSeasonScheduleUseCase } from '@core/racing/application/use-cases/PublishLeagueSeasonScheduleUseCase';
import { UnpublishLeagueSeasonScheduleUseCase } from '@core/racing/application/use-cases/UnpublishLeagueSeasonScheduleUseCase';

// Import presenters
import { AllLeaguesWithCapacityPresenter } from './presenters/AllLeaguesWithCapacityPresenter';
import { AllLeaguesWithCapacityAndScoringPresenter } from './presenters/AllLeaguesWithCapacityAndScoringPresenter';
import { ApproveLeagueJoinRequestPresenter } from './presenters/ApproveLeagueJoinRequestPresenter';
import { CreateLeaguePresenter } from './presenters/CreateLeaguePresenter';
import { GetLeagueAdminPermissionsPresenter } from './presenters/GetLeagueAdminPermissionsPresenter';
import { GetLeagueMembershipsPresenter } from './presenters/GetLeagueMembershipsPresenter';
import {
  GetLeagueRosterJoinRequestsPresenter,
  GetLeagueRosterMembersPresenter,
} from './presenters/LeagueRosterAdminReadPresenters';
import { GetLeagueOwnerSummaryPresenter } from './presenters/GetLeagueOwnerSummaryPresenter';
import { GetLeagueProtestsPresenter } from './presenters/GetLeagueProtestsPresenter';
import { GetLeagueSeasonsPresenter } from './presenters/GetLeagueSeasonsPresenter';
import { GetLeagueWalletPresenter } from './presenters/GetLeagueWalletPresenter';
import { GetSeasonSponsorshipsPresenter } from './presenters/GetSeasonSponsorshipsPresenter';
import { JoinLeaguePresenter } from './presenters/JoinLeaguePresenter';
import { LeagueConfigPresenter } from './presenters/LeagueConfigPresenter';
import { LeagueJoinRequestsPresenter } from './presenters/LeagueJoinRequestsPresenter';
import { LeagueSchedulePresenter, LeagueRacesPresenter } from './presenters/LeagueSchedulePresenter';
import { LeagueScoringConfigPresenter } from './presenters/LeagueScoringConfigPresenter';
import { LeagueScoringPresetsPresenter } from './presenters/LeagueScoringPresetsPresenter';
import { LeagueStandingsPresenter } from './presenters/LeagueStandingsPresenter';
import { LeagueStatsPresenter } from './presenters/LeagueStatsPresenter';
import { RejectLeagueJoinRequestPresenter } from './presenters/RejectLeagueJoinRequestPresenter';
import { RemoveLeagueMemberPresenter } from './presenters/RemoveLeagueMemberPresenter';
import { TotalLeaguesPresenter } from './presenters/TotalLeaguesPresenter';
import { TransferLeagueOwnershipPresenter } from './presenters/TransferLeagueOwnershipPresenter';
import { UpdateLeagueMemberRolePresenter } from './presenters/UpdateLeagueMemberRolePresenter';
import { WithdrawFromLeagueWalletPresenter } from './presenters/WithdrawFromLeagueWalletPresenter';

import {
  CreateLeagueSeasonScheduleRacePresenter,
  DeleteLeagueSeasonScheduleRacePresenter,
  PublishLeagueSeasonSchedulePresenter,
  UnpublishLeagueSeasonSchedulePresenter,
  UpdateLeagueSeasonScheduleRacePresenter,
} from './presenters/LeagueSeasonScheduleMutationPresenters';

export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
export const LEAGUE_STANDINGS_REPOSITORY_TOKEN = 'ILeagueStandingsRepository';
export const STANDING_REPOSITORY_TOKEN = 'IStandingRepository';
export const SEASON_REPOSITORY_TOKEN = 'ISeasonRepository';
export const LEAGUE_SCORING_CONFIG_REPOSITORY_TOKEN = 'ILeagueScoringConfigRepository';
export const GAME_REPOSITORY_TOKEN = 'IGameRepository';
export const PROTEST_REPOSITORY_TOKEN = 'IProtestRepository';
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
export const LEAGUE_WALLET_REPOSITORY_TOKEN = 'ILeagueWalletRepository';
export const TRANSACTION_REPOSITORY_TOKEN = 'ITransactionRepository';
export const LOGGER_TOKEN = 'Logger';
export const MEDIA_RESOLVER_TOKEN = 'MediaResolverPort';

export const GET_LEAGUE_STANDINGS_USE_CASE = 'GetLeagueStandingsUseCase';
export const GET_ALL_LEAGUES_WITH_CAPACITY_USE_CASE = 'GetAllLeaguesWithCapacityUseCase';
export const GET_ALL_LEAGUES_WITH_CAPACITY_AND_SCORING_USE_CASE = 'GetAllLeaguesWithCapacityAndScoringUseCase';
export const GET_LEAGUE_STATS_USE_CASE = 'GetLeagueStatsUseCase';
export const GET_LEAGUE_FULL_CONFIG_USE_CASE = 'GetLeagueFullConfigUseCase';
export const GET_LEAGUE_SCORING_CONFIG_USE_CASE = 'GetLeagueScoringConfigUseCase';
export const LIST_LEAGUE_SCORING_PRESETS_USE_CASE = 'ListLeagueScoringPresetsUseCase';
export const JOIN_LEAGUE_USE_CASE = 'JoinLeagueUseCase';
export const TRANSFER_LEAGUE_OWNERSHIP_USE_CASE = 'TransferLeagueOwnershipUseCase';
export const CREATE_LEAGUE_WITH_SEASON_AND_SCORING_USE_CASE = 'CreateLeagueWithSeasonAndScoringUseCase';
export const GET_RACE_PROTESTS_USE_CASE = 'GetRaceProtestsUseCase';
export const GET_TOTAL_LEAGUES_USE_CASE = 'GetTotalLeaguesUseCase';
export const GET_LEAGUE_JOIN_REQUESTS_USE_CASE = 'GetLeagueJoinRequestsUseCase';
export const APPROVE_LEAGUE_JOIN_REQUEST_USE_CASE = 'ApproveLeagueJoinRequestUseCase';
export const REJECT_LEAGUE_JOIN_REQUEST_USE_CASE = 'RejectLeagueJoinRequestUseCase';
export const REMOVE_LEAGUE_MEMBER_USE_CASE = 'RemoveLeagueMemberUseCase';
export const UPDATE_LEAGUE_MEMBER_ROLE_USE_CASE = 'UpdateLeagueMemberRoleUseCase';
export const GET_LEAGUE_OWNER_SUMMARY_USE_CASE = 'GetLeagueOwnerSummaryUseCase';
export const GET_LEAGUE_PROTESTS_USE_CASE = 'GetLeagueProtestsUseCase';
export const GET_LEAGUE_SEASONS_USE_CASE = 'GetLeagueSeasonsUseCase';
export const GET_LEAGUE_MEMBERSHIPS_USE_CASE = 'GetLeagueMembershipsUseCase';
export const GET_LEAGUE_ROSTER_MEMBERS_USE_CASE = 'GetLeagueRosterMembersUseCase';
export const GET_LEAGUE_ROSTER_JOIN_REQUESTS_USE_CASE = 'GetLeagueRosterJoinRequestsUseCase';
export const GET_LEAGUE_SCHEDULE_USE_CASE = 'GetLeagueScheduleUseCase';
export const GET_LEAGUE_ADMIN_PERMISSIONS_USE_CASE = 'GetLeagueAdminPermissionsUseCase';
export const GET_LEAGUE_WALLET_USE_CASE = 'GetLeagueWalletUseCase';
export const WITHDRAW_FROM_LEAGUE_WALLET_USE_CASE = 'WithdrawFromLeagueWalletUseCase';
export const GET_SEASON_SPONSORSHIPS_USE_CASE = 'GetSeasonSponsorshipsUseCase';

export const GET_ALL_LEAGUES_WITH_CAPACITY_OUTPUT_PORT_TOKEN = 'GetAllLeaguesWithCapacityOutputPort_TOKEN';
export const GET_ALL_LEAGUES_WITH_CAPACITY_AND_SCORING_OUTPUT_PORT_TOKEN = 'GetAllLeaguesWithCapacityAndScoringOutputPort_TOKEN';
export const GET_LEAGUE_STANDINGS_OUTPUT_PORT_TOKEN = 'GetLeagueStandingsOutputPort_TOKEN';
export const GET_LEAGUE_PROTESTS_OUTPUT_PORT_TOKEN = 'GetLeagueProtestsOutputPort_TOKEN';
export const GET_SEASON_SPONSORSHIPS_OUTPUT_PORT_TOKEN = 'GetSeasonSponsorshipsOutputPort_TOKEN';
export const LIST_LEAGUE_SCORING_PRESETS_OUTPUT_PORT_TOKEN = 'ListLeagueScoringPresetsOutputPort_TOKEN';
export const APPROVE_LEAGUE_JOIN_REQUEST_OUTPUT_PORT_TOKEN = 'ApproveLeagueJoinRequestOutputPort_TOKEN';
export const CREATE_LEAGUE_OUTPUT_PORT_TOKEN = 'CreateLeagueOutputPort_TOKEN';
export const GET_LEAGUE_ADMIN_PERMISSIONS_OUTPUT_PORT_TOKEN = 'GetLeagueAdminPermissionsOutputPort_TOKEN';
export const GET_LEAGUE_MEMBERSHIPS_OUTPUT_PORT_TOKEN = 'GetLeagueMembershipsOutputPort_TOKEN';
export const GET_LEAGUE_ROSTER_MEMBERS_OUTPUT_PORT_TOKEN = 'GetLeagueRosterMembersOutputPort_TOKEN';
export const GET_LEAGUE_ROSTER_JOIN_REQUESTS_OUTPUT_PORT_TOKEN = 'GetLeagueRosterJoinRequestsOutputPort_TOKEN';
export const GET_LEAGUE_OWNER_SUMMARY_OUTPUT_PORT_TOKEN = 'GetLeagueOwnerSummaryOutputPort_TOKEN';
export const GET_LEAGUE_SEASONS_OUTPUT_PORT_TOKEN = 'GetLeagueSeasonsOutputPort_TOKEN';
export const JOIN_LEAGUE_OUTPUT_PORT_TOKEN = 'JoinLeagueOutputPort_TOKEN';
export const GET_LEAGUE_SCHEDULE_OUTPUT_PORT_TOKEN = 'GetLeagueScheduleOutputPort_TOKEN';
export const GET_LEAGUE_STATS_OUTPUT_PORT_TOKEN = 'GetLeagueStatsOutputPort_TOKEN';
export const REJECT_LEAGUE_JOIN_REQUEST_OUTPUT_PORT_TOKEN = 'RejectLeagueJoinRequestOutputPort_TOKEN';
export const REMOVE_LEAGUE_MEMBER_OUTPUT_PORT_TOKEN = 'RemoveLeagueMemberOutputPort_TOKEN';
export const TOTAL_LEAGUES_OUTPUT_PORT_TOKEN = 'TotalLeaguesOutputPort_TOKEN';
export const TRANSFER_LEAGUE_OWNERSHIP_OUTPUT_PORT_TOKEN = 'TransferLeagueOwnershipOutputPort_TOKEN';
export const UPDATE_LEAGUE_MEMBER_ROLE_OUTPUT_PORT_TOKEN = 'UpdateLeagueMemberRoleOutputPort_TOKEN';
export const GET_LEAGUE_FULL_CONFIG_OUTPUT_PORT_TOKEN = 'GetLeagueFullConfigOutputPort_TOKEN';
export const GET_LEAGUE_SCORING_CONFIG_OUTPUT_PORT_TOKEN = 'GetLeagueScoringConfigOutputPort_TOKEN';
export const GET_LEAGUE_WALLET_OUTPUT_PORT_TOKEN = 'GetLeagueWalletOutputPort_TOKEN';
export const WITHDRAW_FROM_LEAGUE_WALLET_OUTPUT_PORT_TOKEN = 'WithdrawFromLeagueWalletOutputPort_TOKEN';

export const LeagueProviders: Provider[] = [
  LeagueService,
  {
    provide: LEAGUE_STANDINGS_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryLeagueStandingsRepository(logger), // Factory for InMemoryLeagueStandingsRepository
    inject: [LOGGER_TOKEN],
  },
  {
    provide: LOGGER_TOKEN,
    useClass: ConsoleLogger,
  },
  {
    provide: MEDIA_RESOLVER_TOKEN,
    useFactory: () => new MediaResolverAdapter({}),
  },
  // Presenters
  AllLeaguesWithCapacityPresenter,
  {
    provide: AllLeaguesWithCapacityAndScoringPresenter,
    useFactory: (mediaResolver: MediaResolverPort) => {
      const presenter = new AllLeaguesWithCapacityAndScoringPresenter();
      presenter.setMediaResolver(mediaResolver);
      return presenter;
    },
    inject: [MEDIA_RESOLVER_TOKEN],
  },
  ApproveLeagueJoinRequestPresenter,
  CreateLeaguePresenter,
  GetLeagueAdminPermissionsPresenter,
  GetLeagueMembershipsPresenter,
  GetLeagueRosterMembersPresenter,
  GetLeagueRosterJoinRequestsPresenter,
  GetLeagueOwnerSummaryPresenter,
  GetLeagueProtestsPresenter,
  GetLeagueSeasonsPresenter,
  GetLeagueWalletPresenter,
  GetSeasonSponsorshipsPresenter,
  JoinLeaguePresenter,
  LeagueConfigPresenter,
  LeagueJoinRequestsPresenter,
  LeagueRacesPresenter,
  LeagueSchedulePresenter,
  LeagueScoringConfigPresenter,
  LeagueScoringPresetsPresenter,
  LeagueStandingsPresenter,
  LeagueStatsPresenter,
  RejectLeagueJoinRequestPresenter,
  RemoveLeagueMemberPresenter,
  TotalLeaguesPresenter,
  TransferLeagueOwnershipPresenter,
  UpdateLeagueMemberRolePresenter,
  WithdrawFromLeagueWalletPresenter,
  CreateLeagueSeasonScheduleRacePresenter,
  UpdateLeagueSeasonScheduleRacePresenter,
  DeleteLeagueSeasonScheduleRacePresenter,
  PublishLeagueSeasonSchedulePresenter,
  UnpublishLeagueSeasonSchedulePresenter,
  // Output ports
  {
    provide: GET_ALL_LEAGUES_WITH_CAPACITY_OUTPUT_PORT_TOKEN,
    useExisting: AllLeaguesWithCapacityPresenter,
  },
  {
    provide: GET_ALL_LEAGUES_WITH_CAPACITY_AND_SCORING_OUTPUT_PORT_TOKEN,
    useExisting: AllLeaguesWithCapacityAndScoringPresenter,
  },
  {
    provide: GET_LEAGUE_STANDINGS_OUTPUT_PORT_TOKEN,
    useExisting: LeagueStandingsPresenter,
  },
  {
    provide: GET_LEAGUE_PROTESTS_OUTPUT_PORT_TOKEN,
    useExisting: GetLeagueProtestsPresenter,
  },
  {
    provide: GET_SEASON_SPONSORSHIPS_OUTPUT_PORT_TOKEN,
    useExisting: GetSeasonSponsorshipsPresenter,
  },
  {
    provide: LIST_LEAGUE_SCORING_PRESETS_OUTPUT_PORT_TOKEN,
    useExisting: LeagueScoringPresetsPresenter,
  },
  {
    provide: APPROVE_LEAGUE_JOIN_REQUEST_OUTPUT_PORT_TOKEN,
    useExisting: ApproveLeagueJoinRequestPresenter,
  },
  {
    provide: CREATE_LEAGUE_OUTPUT_PORT_TOKEN,
    useExisting: CreateLeaguePresenter,
  },
  {
    provide: GET_LEAGUE_ADMIN_PERMISSIONS_OUTPUT_PORT_TOKEN,
    useExisting: GetLeagueAdminPermissionsPresenter,
  },
  {
    provide: GET_LEAGUE_MEMBERSHIPS_OUTPUT_PORT_TOKEN,
    useExisting: GetLeagueMembershipsPresenter,
  },
  {
    provide: GET_LEAGUE_ROSTER_MEMBERS_OUTPUT_PORT_TOKEN,
    useExisting: GetLeagueRosterMembersPresenter,
  },
  {
    provide: GET_LEAGUE_ROSTER_JOIN_REQUESTS_OUTPUT_PORT_TOKEN,
    useExisting: GetLeagueRosterJoinRequestsPresenter,
  },
  {
    provide: GET_LEAGUE_OWNER_SUMMARY_OUTPUT_PORT_TOKEN,
    useExisting: GetLeagueOwnerSummaryPresenter,
  },
  {
    provide: GET_LEAGUE_SEASONS_OUTPUT_PORT_TOKEN,
    useExisting: GetLeagueSeasonsPresenter,
  },
  {
    provide: JOIN_LEAGUE_OUTPUT_PORT_TOKEN,
    useExisting: JoinLeaguePresenter,
  },
  {
    provide: GET_LEAGUE_SCHEDULE_OUTPUT_PORT_TOKEN,
    useExisting: LeagueSchedulePresenter,
  },
  {
    provide: GET_LEAGUE_STATS_OUTPUT_PORT_TOKEN,
    useExisting: LeagueStatsPresenter,
  },
  {
    provide: REJECT_LEAGUE_JOIN_REQUEST_OUTPUT_PORT_TOKEN,
    useExisting: RejectLeagueJoinRequestPresenter,
  },
  {
    provide: REMOVE_LEAGUE_MEMBER_OUTPUT_PORT_TOKEN,
    useExisting: RemoveLeagueMemberPresenter,
  },
  {
    provide: TOTAL_LEAGUES_OUTPUT_PORT_TOKEN,
    useExisting: TotalLeaguesPresenter,
  },
  {
    provide: TRANSFER_LEAGUE_OWNERSHIP_OUTPUT_PORT_TOKEN,
    useExisting: TransferLeagueOwnershipPresenter,
  },
  {
    provide: UPDATE_LEAGUE_MEMBER_ROLE_OUTPUT_PORT_TOKEN,
    useExisting: UpdateLeagueMemberRolePresenter,
  },
  {
    provide: GET_LEAGUE_FULL_CONFIG_OUTPUT_PORT_TOKEN,
    useExisting: LeagueConfigPresenter,
  },
  {
    provide: GET_LEAGUE_SCORING_CONFIG_OUTPUT_PORT_TOKEN,
    useExisting: LeagueScoringConfigPresenter,
  },
  {
    provide: GET_LEAGUE_WALLET_OUTPUT_PORT_TOKEN,
    useExisting: GetLeagueWalletPresenter,
  },
  {
    provide: WITHDRAW_FROM_LEAGUE_WALLET_OUTPUT_PORT_TOKEN,
    useExisting: WithdrawFromLeagueWalletPresenter,
  },

  // Schedule mutation output ports
  {
    provide: LeagueTokens.CREATE_LEAGUE_SEASON_SCHEDULE_RACE_OUTPUT_PORT_TOKEN,
    useExisting: CreateLeagueSeasonScheduleRacePresenter,
  },
  {
    provide: LeagueTokens.UPDATE_LEAGUE_SEASON_SCHEDULE_RACE_OUTPUT_PORT_TOKEN,
    useExisting: UpdateLeagueSeasonScheduleRacePresenter,
  },
  {
    provide: LeagueTokens.DELETE_LEAGUE_SEASON_SCHEDULE_RACE_OUTPUT_PORT_TOKEN,
    useExisting: DeleteLeagueSeasonScheduleRacePresenter,
  },
  {
    provide: LeagueTokens.PUBLISH_LEAGUE_SEASON_SCHEDULE_OUTPUT_PORT_TOKEN,
    useExisting: PublishLeagueSeasonSchedulePresenter,
  },
  {
    provide: LeagueTokens.UNPUBLISH_LEAGUE_SEASON_SCHEDULE_OUTPUT_PORT_TOKEN,
    useExisting: UnpublishLeagueSeasonSchedulePresenter,
  },

  // Use cases
  {
    provide: GET_ALL_LEAGUES_WITH_CAPACITY_USE_CASE,
    useFactory: (leagueRepo: ILeagueRepository, membershipRepo: ILeagueMembershipRepository) =>
      new GetAllLeaguesWithCapacityUseCase(leagueRepo, membershipRepo),
    inject: [LEAGUE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN],
  },
  {
    provide: GET_ALL_LEAGUES_WITH_CAPACITY_AND_SCORING_USE_CASE,
    useFactory: (
      leagueRepo: ILeagueRepository,
      membershipRepo: ILeagueMembershipRepository,
      seasonRepo: ISeasonRepository,
      scoringRepo: import('@core/racing/domain/repositories/ILeagueScoringConfigRepository').ILeagueScoringConfigRepository,
      gameRepo: import('@core/racing/domain/repositories/IGameRepository').IGameRepository,
      output: AllLeaguesWithCapacityAndScoringPresenter,
    ) =>
      new GetAllLeaguesWithCapacityAndScoringUseCase(
        leagueRepo,
        membershipRepo,
        seasonRepo,
        scoringRepo,
        gameRepo,
        { getPresetById: getLeagueScoringPresetById },
        output,
      ),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      SEASON_REPOSITORY_TOKEN,
      LEAGUE_SCORING_CONFIG_REPOSITORY_TOKEN,
      GAME_REPOSITORY_TOKEN,
      GET_ALL_LEAGUES_WITH_CAPACITY_AND_SCORING_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_STANDINGS_USE_CASE,
    useFactory: (
      standingRepo: IStandingRepository,
      driverRepo: IDriverRepository,
      output: LeagueStandingsPresenter,
    ) => new GetLeagueStandingsUseCase(standingRepo, driverRepo, output),
    inject: [
      STANDING_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
      GET_LEAGUE_STANDINGS_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_STATS_USE_CASE,
    useClass: GetLeagueStatsUseCase,
  },
  {
    provide: GET_LEAGUE_FULL_CONFIG_USE_CASE,
    useClass: GetLeagueFullConfigUseCase,
  },
  {
    provide: CREATE_LEAGUE_WITH_SEASON_AND_SCORING_USE_CASE,
    useClass: CreateLeagueWithSeasonAndScoringUseCase,
  },
  {
    provide: GET_RACE_PROTESTS_USE_CASE,
    useClass: GetRaceProtestsUseCase,
  },
  {
    provide: GET_TOTAL_LEAGUES_USE_CASE,
    useFactory: (leagueRepo: ILeagueRepository, output: TotalLeaguesPresenter) =>
      new GetTotalLeaguesUseCase(leagueRepo, output),
    inject: [LEAGUE_REPOSITORY_TOKEN, TOTAL_LEAGUES_OUTPUT_PORT_TOKEN],
  },
  {
    provide: GET_LEAGUE_JOIN_REQUESTS_USE_CASE,
    useFactory: (
      membershipRepo: ILeagueMembershipRepository,
      driverRepo: IDriverRepository,
      leagueRepo: ILeagueRepository,
      output: LeagueJoinRequestsPresenter,
    ) => new GetLeagueJoinRequestsUseCase(membershipRepo, driverRepo, leagueRepo, output),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN, LeagueJoinRequestsPresenter],
  },
  {
    provide: APPROVE_LEAGUE_JOIN_REQUEST_USE_CASE,
    useFactory: (
      membershipRepo: ILeagueMembershipRepository,
      leagueRepo: ILeagueRepository,
    ) => new ApproveLeagueJoinRequestUseCase(membershipRepo, leagueRepo),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
  },
  {
    provide: REJECT_LEAGUE_JOIN_REQUEST_USE_CASE,
    useFactory: (membershipRepo: ILeagueMembershipRepository) =>
      new RejectLeagueJoinRequestUseCase(membershipRepo),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN],
  },
  {
    provide: REMOVE_LEAGUE_MEMBER_USE_CASE,
    useFactory: (
      membershipRepo: ILeagueMembershipRepository,
      output: RemoveLeagueMemberPresenter,
    ) => new RemoveLeagueMemberUseCase(membershipRepo, output),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, REMOVE_LEAGUE_MEMBER_OUTPUT_PORT_TOKEN],
  },
  {
    provide: UPDATE_LEAGUE_MEMBER_ROLE_USE_CASE,
    useFactory: (
      membershipRepo: ILeagueMembershipRepository,
      output: UpdateLeagueMemberRolePresenter,
    ) => new UpdateLeagueMemberRoleUseCase(membershipRepo, output),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, UPDATE_LEAGUE_MEMBER_ROLE_OUTPUT_PORT_TOKEN],
  },
  {
    provide: GET_LEAGUE_OWNER_SUMMARY_USE_CASE,
    useClass: GetLeagueOwnerSummaryUseCase,
  },
  {
    provide: GET_LEAGUE_PROTESTS_USE_CASE,
    useFactory: (
      raceRepo: IRaceRepository,
      protestRepo: IProtestRepository,
      driverRepo: IDriverRepository,
      leagueRepo: ILeagueRepository,
      output: GetLeagueProtestsPresenter,
    ) => new GetLeagueProtestsUseCase(raceRepo, protestRepo, driverRepo, leagueRepo, output),
    inject: [
      RACE_REPOSITORY_TOKEN,
      PROTEST_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
      GET_LEAGUE_PROTESTS_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_SEASONS_USE_CASE,
    useClass: GetLeagueSeasonsUseCase,
  },
  {
    provide: GET_LEAGUE_MEMBERSHIPS_USE_CASE,
    useFactory: (
      membershipRepo: ILeagueMembershipRepository,
      driverRepo: IDriverRepository,
      leagueRepo: ILeagueRepository,
      output: GetLeagueMembershipsPresenter,
    ) => new GetLeagueMembershipsUseCase(membershipRepo, driverRepo, leagueRepo, output),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN, GetLeagueMembershipsPresenter],
  },
  {
    provide: GET_LEAGUE_ROSTER_MEMBERS_USE_CASE,
    useFactory: (
      membershipRepo: ILeagueMembershipRepository,
      driverRepo: IDriverRepository,
      leagueRepo: ILeagueRepository,
      output: GetLeagueRosterMembersPresenter,
    ) => new GetLeagueRosterMembersUseCase(membershipRepo, driverRepo, leagueRepo, output),
    inject: [
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
      GET_LEAGUE_ROSTER_MEMBERS_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_ROSTER_JOIN_REQUESTS_USE_CASE,
    useFactory: (
      membershipRepo: ILeagueMembershipRepository,
      driverRepo: IDriverRepository,
      leagueRepo: ILeagueRepository,
      output: GetLeagueRosterJoinRequestsPresenter,
    ) => new GetLeagueRosterJoinRequestsUseCase(membershipRepo, driverRepo, leagueRepo, output),
    inject: [
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
      GET_LEAGUE_ROSTER_JOIN_REQUESTS_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_SCHEDULE_USE_CASE,
    useFactory: (
      leagueRepo: ILeagueRepository,
      seasonRepo: ISeasonRepository,
      raceRepo: IRaceRepository,
      logger: Logger,
      output: LeagueSchedulePresenter,
    ) => new GetLeagueScheduleUseCase(leagueRepo, seasonRepo, raceRepo, logger, output),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      SEASON_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
      GET_LEAGUE_SCHEDULE_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_ADMIN_PERMISSIONS_USE_CASE,
    useFactory: (
      leagueRepo: ILeagueRepository,
      leagueMembershipRepo: ILeagueMembershipRepository,
      logger: Logger,
      output: GetLeagueAdminPermissionsPresenter,
    ) => new GetLeagueAdminPermissionsUseCase(leagueRepo, leagueMembershipRepo, logger, output),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
      GET_LEAGUE_ADMIN_PERMISSIONS_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_WALLET_USE_CASE,
    useFactory: (
      leagueRepo: ILeagueRepository,
      walletRepo: ILeagueWalletRepository,
      transactionRepo: ITransactionRepository,
      output: GetLeagueWalletPresenter,
    ) => new GetLeagueWalletUseCase(leagueRepo, walletRepo, transactionRepo, output),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_WALLET_REPOSITORY_TOKEN,
      TRANSACTION_REPOSITORY_TOKEN,
      GET_LEAGUE_WALLET_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: WITHDRAW_FROM_LEAGUE_WALLET_USE_CASE,
    useFactory: (
      leagueRepo: ILeagueRepository,
      walletRepo: ILeagueWalletRepository,
      transactionRepo: ITransactionRepository,
      logger: Logger,
      output: WithdrawFromLeagueWalletPresenter,
    ) => new WithdrawFromLeagueWalletUseCase(leagueRepo, walletRepo, transactionRepo, logger, output),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_WALLET_REPOSITORY_TOKEN,
      TRANSACTION_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
      WITHDRAW_FROM_LEAGUE_WALLET_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: GET_SEASON_SPONSORSHIPS_USE_CASE,
    useFactory: (
      seasonSponsorshipRepo: ISeasonSponsorshipRepository,
      seasonRepo: ISeasonRepository,
      leagueRepo: ILeagueRepository,
      leagueMembershipRepo: ILeagueMembershipRepository,
      raceRepo: IRaceRepository,
      output: GetSeasonSponsorshipsPresenter,
    ) =>
      new GetSeasonSponsorshipsUseCase(
        seasonSponsorshipRepo,
        seasonRepo,
        leagueRepo,
        leagueMembershipRepo,
        raceRepo,
        output,
      ),
    inject: [
      'ISeasonSponsorshipRepository',
      SEASON_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      GET_SEASON_SPONSORSHIPS_OUTPUT_PORT_TOKEN,
    ],
  },
  { // TODO wtf is this here? doesn't look like it adhers to our concepts
    provide: LIST_LEAGUE_SCORING_PRESETS_USE_CASE,
    useFactory: (output: LeagueScoringPresetsPresenter) =>
      new ListLeagueScoringPresetsUseCase(listLeagueScoringPresets(), output),
    inject: [LIST_LEAGUE_SCORING_PRESETS_OUTPUT_PORT_TOKEN],
  },
  {
    provide: JOIN_LEAGUE_USE_CASE,
    useFactory: (
      membershipRepo: ILeagueMembershipRepository,
      logger: Logger,
      output: JoinLeaguePresenter,
    ) => new JoinLeagueUseCase(membershipRepo, logger, output),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN, JoinLeaguePresenter],
  },
  {
    provide: TRANSFER_LEAGUE_OWNERSHIP_USE_CASE,
    useClass: TransferLeagueOwnershipUseCase,
  },
  {
    provide: GET_LEAGUE_SCORING_CONFIG_USE_CASE,
    useClass: GetLeagueScoringConfigUseCase,
  },

  // Schedule mutation use cases
  {
    provide: LeagueTokens.CREATE_LEAGUE_SEASON_SCHEDULE_RACE_USE_CASE,
    useFactory: (
      seasonRepo: ISeasonRepository,
      raceRepo: IRaceRepository,
      logger: Logger,
      output: CreateLeagueSeasonScheduleRacePresenter,
    ) =>
      new CreateLeagueSeasonScheduleRaceUseCase(seasonRepo, raceRepo, logger, output, {
        generateRaceId: () => `race-${randomUUID()}`,
      }),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
      LeagueTokens.CREATE_LEAGUE_SEASON_SCHEDULE_RACE_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: LeagueTokens.UPDATE_LEAGUE_SEASON_SCHEDULE_RACE_USE_CASE,
    useFactory: (
      seasonRepo: ISeasonRepository,
      raceRepo: IRaceRepository,
      logger: Logger,
      output: UpdateLeagueSeasonScheduleRacePresenter,
    ) => new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepo, raceRepo, logger, output),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
      LeagueTokens.UPDATE_LEAGUE_SEASON_SCHEDULE_RACE_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: LeagueTokens.DELETE_LEAGUE_SEASON_SCHEDULE_RACE_USE_CASE,
    useFactory: (
      seasonRepo: ISeasonRepository,
      raceRepo: IRaceRepository,
      logger: Logger,
      output: DeleteLeagueSeasonScheduleRacePresenter,
    ) => new DeleteLeagueSeasonScheduleRaceUseCase(seasonRepo, raceRepo, logger, output),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
      LeagueTokens.DELETE_LEAGUE_SEASON_SCHEDULE_RACE_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: LeagueTokens.PUBLISH_LEAGUE_SEASON_SCHEDULE_USE_CASE,
    useFactory: (
      seasonRepo: ISeasonRepository,
      logger: Logger,
      output: PublishLeagueSeasonSchedulePresenter,
    ) => new PublishLeagueSeasonScheduleUseCase(seasonRepo, logger, output),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
      LeagueTokens.PUBLISH_LEAGUE_SEASON_SCHEDULE_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: LeagueTokens.UNPUBLISH_LEAGUE_SEASON_SCHEDULE_USE_CASE,
    useFactory: (
      seasonRepo: ISeasonRepository,
      logger: Logger,
      output: UnpublishLeagueSeasonSchedulePresenter,
    ) => new UnpublishLeagueSeasonScheduleUseCase(seasonRepo, logger, output),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
      LeagueTokens.UNPUBLISH_LEAGUE_SEASON_SCHEDULE_OUTPUT_PORT_TOKEN,
    ],
  },
];