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

// Import core interfaces
import type { MediaResolverPort } from '@core/ports/media/MediaResolverPort';
import type { DriverRepository } from '@core/racing/domain/repositories/DriverRepository';
import type { LeagueMembershipRepository } from '@core/racing/domain/repositories/LeagueMembershipRepository';
import type { LeagueRepository } from '@core/racing/domain/repositories/LeagueRepository';
import type { ProtestRepository } from '@core/racing/domain/repositories/ProtestRepository';
import type { RaceRepository } from '@core/racing/domain/repositories/RaceRepository';
import type { SeasonRepository } from '@core/racing/domain/repositories/SeasonRepository';
import type { SeasonSponsorshipRepository } from '@core/racing/domain/repositories/SeasonSponsorshipRepository';
import type { StandingRepository } from '@core/racing/domain/repositories/StandingRepository';
import type { Logger } from '@core/shared/domain/Logger';

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

// Import use cases
import { ApproveLeagueJoinRequestUseCase } from '@core/racing/application/use-cases/ApproveLeagueJoinRequestUseCase';
import { CreateLeagueWithSeasonAndScoringUseCase } from '@core/racing/application/use-cases/CreateLeagueWithSeasonAndScoringUseCase';
import { GetAllLeaguesWithCapacityAndScoringUseCase } from '@core/racing/application/use-cases/GetAllLeaguesWithCapacityAndScoringUseCase';
import { GetAllLeaguesWithCapacityUseCase } from '@core/racing/application/use-cases/GetAllLeaguesWithCapacityUseCase';
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 { GetLeagueOwnerSummaryUseCase } from '@core/racing/application/use-cases/GetLeagueOwnerSummaryUseCase';
import { GetLeagueProtestsUseCase } from '@core/racing/application/use-cases/GetLeagueProtestsUseCase';
import { GetLeagueRosterJoinRequestsUseCase } from '@core/racing/application/use-cases/GetLeagueRosterJoinRequestsUseCase';
import { GetLeagueRosterMembersUseCase } from '@core/racing/application/use-cases/GetLeagueRosterMembersUseCase';
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 { 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 { UpdateLeagueSeasonScheduleRaceUseCase } from '@core/racing/application/use-cases/UpdateLeagueSeasonScheduleRaceUseCase';

// Import presenters
import { AllLeaguesWithCapacityAndScoringPresenter } from './presenters/AllLeaguesWithCapacityAndScoringPresenter';
import { AllLeaguesWithCapacityPresenter } from './presenters/AllLeaguesWithCapacityPresenter';
import { ApproveLeagueJoinRequestPresenter } from './presenters/ApproveLeagueJoinRequestPresenter';
import { CreateLeaguePresenter } from './presenters/CreateLeaguePresenter';
import { GetLeagueAdminPermissionsPresenter } from './presenters/GetLeagueAdminPermissionsPresenter';
import { GetLeagueMembershipsPresenter } from './presenters/GetLeagueMembershipsPresenter';
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 {
    GetLeagueRosterJoinRequestsPresenter,
    GetLeagueRosterMembersPresenter,
} from './presenters/LeagueRosterAdminReadPresenters';
import { LeagueRacesPresenter, LeagueSchedulePresenter } 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 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,

  // Use cases
  {
    provide: GET_ALL_LEAGUES_WITH_CAPACITY_USE_CASE,
    useFactory: (leagueRepo: LeagueRepository, membershipRepo: LeagueMembershipRepository) =>
      new GetAllLeaguesWithCapacityUseCase(leagueRepo, membershipRepo),
    inject: [LEAGUE_REPOSITORY_TOKEN, LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN],
  },
  {
    provide: GET_ALL_LEAGUES_WITH_CAPACITY_AND_SCORING_USE_CASE,
    useFactory: (
      leagueRepo: LeagueRepository,
      membershipRepo: LeagueMembershipRepository,
      seasonRepo: SeasonRepository,
      scoringRepo: import('@core/racing/domain/repositories/LeagueScoringConfigRepository').LeagueScoringConfigRepository,
      gameRepo: import('@core/racing/domain/repositories/GameRepository').GameRepository,
    ) =>
      new GetAllLeaguesWithCapacityAndScoringUseCase(
        leagueRepo,
        membershipRepo,
        seasonRepo,
        scoringRepo,
        gameRepo,
        { getPresetById: getLeagueScoringPresetById },
      ),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      SEASON_REPOSITORY_TOKEN,
      LEAGUE_SCORING_CONFIG_REPOSITORY_TOKEN,
      GAME_REPOSITORY_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_STANDINGS_USE_CASE,
    useFactory: (
      standingRepo: StandingRepository,
      driverRepo: DriverRepository,
    ) => new GetLeagueStandingsUseCase(standingRepo, driverRepo),
    inject: [
      STANDING_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_STATS_USE_CASE,
    useClass: GetLeagueStatsUseCase,
  },
  {
    provide: GET_LEAGUE_FULL_CONFIG_USE_CASE,
    useFactory: (
      leagueRepo: LeagueRepository,
      seasonRepo: SeasonRepository,
      scoringRepo: import('@core/racing/domain/repositories/LeagueScoringConfigRepository').LeagueScoringConfigRepository,
      gameRepo: import('@core/racing/domain/repositories/GameRepository').GameRepository,
    ) =>
      new GetLeagueFullConfigUseCase(leagueRepo, seasonRepo, scoringRepo, gameRepo),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      SEASON_REPOSITORY_TOKEN,
      LEAGUE_SCORING_CONFIG_REPOSITORY_TOKEN,
      GAME_REPOSITORY_TOKEN,
    ],
  },
  {
    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: LeagueRepository) =>
      new GetTotalLeaguesUseCase(leagueRepo),
    inject: [LEAGUE_REPOSITORY_TOKEN],
  },
  {
    provide: GET_LEAGUE_JOIN_REQUESTS_USE_CASE,
    useFactory: (
      membershipRepo: LeagueMembershipRepository,
      driverRepo: DriverRepository,
      leagueRepo: LeagueRepository,
    ) => new GetLeagueJoinRequestsUseCase(membershipRepo, driverRepo, leagueRepo),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
  },
  {
    provide: APPROVE_LEAGUE_JOIN_REQUEST_USE_CASE,
    useFactory: (
      membershipRepo: LeagueMembershipRepository,
      leagueRepo: LeagueRepository,
    ) => new ApproveLeagueJoinRequestUseCase(membershipRepo, leagueRepo),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
  },
  {
    provide: REJECT_LEAGUE_JOIN_REQUEST_USE_CASE,
    useFactory: (membershipRepo: LeagueMembershipRepository) =>
      new RejectLeagueJoinRequestUseCase(membershipRepo),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN],
  },
  {
    provide: REMOVE_LEAGUE_MEMBER_USE_CASE,
    useFactory: (
      membershipRepo: LeagueMembershipRepository,
    ) => new RemoveLeagueMemberUseCase(membershipRepo),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN],
  },
  {
    provide: UPDATE_LEAGUE_MEMBER_ROLE_USE_CASE,
    useFactory: (
      membershipRepo: LeagueMembershipRepository,
    ) => new UpdateLeagueMemberRoleUseCase(membershipRepo),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN],
  },
  {
    provide: GET_LEAGUE_OWNER_SUMMARY_USE_CASE,
    useFactory: (
      leagueRepo: LeagueRepository,
      driverRepo: DriverRepository,
      leagueMembershipRepo: LeagueMembershipRepository,
      standingRepo: StandingRepository,
    ) => new GetLeagueOwnerSummaryUseCase(leagueRepo, driverRepo, leagueMembershipRepo, standingRepo),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      STANDING_REPOSITORY_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_PROTESTS_USE_CASE,
    useFactory: (
      raceRepo: RaceRepository,
      protestRepo: ProtestRepository,
      driverRepo: DriverRepository,
      leagueRepo: LeagueRepository,
    ) => new GetLeagueProtestsUseCase(raceRepo, protestRepo, driverRepo, leagueRepo),
    inject: [
      RACE_REPOSITORY_TOKEN,
      PROTEST_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_SEASONS_USE_CASE,
    useClass: GetLeagueSeasonsUseCase,
  },
  {
    provide: GET_LEAGUE_MEMBERSHIPS_USE_CASE,
    useFactory: (
      membershipRepo: LeagueMembershipRepository,
      driverRepo: DriverRepository,
      leagueRepo: LeagueRepository,
    ) => new GetLeagueMembershipsUseCase(membershipRepo, driverRepo, leagueRepo),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LEAGUE_REPOSITORY_TOKEN],
  },
  {
    provide: GET_LEAGUE_ROSTER_MEMBERS_USE_CASE,
    useFactory: (
      membershipRepo: LeagueMembershipRepository,
      driverRepo: DriverRepository,
      leagueRepo: LeagueRepository,
    ) => new GetLeagueRosterMembersUseCase(membershipRepo, driverRepo, leagueRepo),
    inject: [
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_ROSTER_JOIN_REQUESTS_USE_CASE,
    useFactory: (
      membershipRepo: LeagueMembershipRepository,
      driverRepo: DriverRepository,
      leagueRepo: LeagueRepository,
    ) => new GetLeagueRosterJoinRequestsUseCase(membershipRepo, driverRepo, leagueRepo),
    inject: [
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      DRIVER_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_SCHEDULE_USE_CASE,
    useFactory: (
      leagueRepo: LeagueRepository,
      seasonRepo: SeasonRepository,
      raceRepo: RaceRepository,
      logger: Logger,
    ) => new GetLeagueScheduleUseCase(leagueRepo, seasonRepo, raceRepo, logger),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      SEASON_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_ADMIN_PERMISSIONS_USE_CASE,
    useFactory: (
      leagueRepo: LeagueRepository,
      leagueMembershipRepo: LeagueMembershipRepository,
      logger: Logger,
    ) => new GetLeagueAdminPermissionsUseCase(leagueRepo, leagueMembershipRepo, logger),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
    ],
  },
  {
    provide: GET_LEAGUE_WALLET_USE_CASE,
    useFactory: (
      leagueRepo: LeagueRepository,
      walletRepo: LeagueWalletRepository,
      transactionRepo: TransactionRepository,
    ) => new GetLeagueWalletUseCase(leagueRepo, walletRepo, transactionRepo),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_WALLET_REPOSITORY_TOKEN,
      TRANSACTION_REPOSITORY_TOKEN,
    ],
  },
  {
    provide: WITHDRAW_FROM_LEAGUE_WALLET_USE_CASE,
    useFactory: (
      leagueRepo: LeagueRepository,
      walletRepo: LeagueWalletRepository,
      transactionRepo: TransactionRepository,
      logger: Logger,
    ) => new WithdrawFromLeagueWalletUseCase(leagueRepo, walletRepo, transactionRepo, logger),
    inject: [
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_WALLET_REPOSITORY_TOKEN,
      TRANSACTION_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
    ],
  },
  {
    provide: GET_SEASON_SPONSORSHIPS_USE_CASE,
    useFactory: (
      seasonSponsorshipRepo: SeasonSponsorshipRepository,
      seasonRepo: SeasonRepository,
      leagueRepo: LeagueRepository,
      leagueMembershipRepo: LeagueMembershipRepository,
      raceRepo: RaceRepository,
    ) =>
      new GetSeasonSponsorshipsUseCase(
        seasonSponsorshipRepo,
        seasonRepo,
        leagueRepo,
        leagueMembershipRepo,
        raceRepo,
      ),
    inject: [
      'ISeasonSponsorshipRepository',
      SEASON_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
    ],
  },
  { // TODO wtf is this here? doesn't look like it adhers to our concepts
    provide: LIST_LEAGUE_SCORING_PRESETS_USE_CASE,
    useFactory: () =>
      new ListLeagueScoringPresetsUseCase(listLeagueScoringPresets()),
    inject: [],
  },
  {
    provide: JOIN_LEAGUE_USE_CASE,
    useFactory: (
      membershipRepo: LeagueMembershipRepository,
      logger: Logger,
    ) => new JoinLeagueUseCase(membershipRepo, logger),
    inject: [LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
  },
  {
    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: SeasonRepository,
      raceRepo: RaceRepository,
      logger: Logger,
    ) =>
      new CreateLeagueSeasonScheduleRaceUseCase(seasonRepo, raceRepo, logger, {
        generateRaceId: () => `race-${randomUUID()}`,
      }),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
    ],
  },
  {
    provide: LeagueTokens.UPDATE_LEAGUE_SEASON_SCHEDULE_RACE_USE_CASE,
    useFactory: (
      seasonRepo: SeasonRepository,
      raceRepo: RaceRepository,
      logger: Logger,
    ) => new UpdateLeagueSeasonScheduleRaceUseCase(seasonRepo, raceRepo, logger),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
    ],
  },
  {
    provide: LeagueTokens.DELETE_LEAGUE_SEASON_SCHEDULE_RACE_USE_CASE,
    useFactory: (
      seasonRepo: SeasonRepository,
      raceRepo: RaceRepository,
      logger: Logger,
    ) => new DeleteLeagueSeasonScheduleRaceUseCase(seasonRepo, raceRepo, logger),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
    ],
  },
  {
    provide: LeagueTokens.PUBLISH_LEAGUE_SEASON_SCHEDULE_USE_CASE,
    useFactory: (
      seasonRepo: SeasonRepository,
      logger: Logger,
    ) => new PublishLeagueSeasonScheduleUseCase(seasonRepo, logger),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
    ],
  },
  {
    provide: LeagueTokens.UNPUBLISH_LEAGUE_SEASON_SCHEDULE_USE_CASE,
    useFactory: (
      seasonRepo: SeasonRepository,
      logger: Logger,
    ) => new UnpublishLeagueSeasonScheduleUseCase(seasonRepo, logger),
    inject: [
      SEASON_REPOSITORY_TOKEN,
      LOGGER_TOKEN,
    ],
  },
];