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

// Import core interfaces
import type { Logger } from '@core/shared/application/Logger';
import { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository';
import { IRaceRepository } from '@core/racing/domain/repositories/IRaceRepository';
import { IResultRepository } from '@core/racing/domain/repositories/IResultRepository';
import { ILeagueRepository } from '@core/racing/domain/repositories/ILeagueRepository';
import { IStandingRepository } from '@core/racing/domain/repositories/IStandingRepository';
import { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
import { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository';
import { IFeedRepository } from '@core/social/domain/repositories/IFeedRepository';
import { ISocialGraphRepository } from '@core/social/domain/repositories/ISocialGraphRepository';

import { SOCIAL_FEED_REPOSITORY_TOKEN, SOCIAL_GRAPH_REPOSITORY_TOKEN } from '../../persistence/social/SocialPersistenceTokens';
import { ImageServicePort } from '@core/media/application/ports/ImageServicePort';
import { DashboardOverviewUseCase } from '@core/racing/application/use-cases/DashboardOverviewUseCase';

// Import concrete implementations
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImageServiceAdapter';
import { DashboardOverviewPresenter } from './presenters/DashboardOverviewPresenter';
import { DashboardService } from './DashboardService';

// Define injection tokens
export const LOGGER_TOKEN = 'Logger';
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
export const RACE_REPOSITORY_TOKEN = 'IRaceRepository';
export const RESULT_REPOSITORY_TOKEN = 'IResultRepository';
export const LEAGUE_REPOSITORY_TOKEN = 'ILeagueRepository';
export const STANDING_REPOSITORY_TOKEN = 'IStandingRepository';
export const LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN = 'ILeagueMembershipRepository';
export const RACE_REGISTRATION_REPOSITORY_TOKEN = 'IRaceRegistrationRepository';
export const IMAGE_SERVICE_TOKEN = 'IImageServicePort';
export const DASHBOARD_OVERVIEW_USE_CASE_TOKEN = 'DashboardOverviewUseCase';
export const DASHBOARD_OVERVIEW_OUTPUT_PORT_TOKEN = 'DashboardOverviewOutputPort';

export const DashboardProviders: Provider[] = [
  DashboardOverviewPresenter,
  {
    provide: LOGGER_TOKEN,
    useClass: ConsoleLogger,
  },
  {
    provide: IMAGE_SERVICE_TOKEN,
    useFactory: (logger: Logger) => new InMemoryImageServiceAdapter(logger),
    inject: [LOGGER_TOKEN],
  },
  {
    provide: DASHBOARD_OVERVIEW_OUTPUT_PORT_TOKEN,
    useExisting: DashboardOverviewPresenter,
  },
  {
    provide: DASHBOARD_OVERVIEW_USE_CASE_TOKEN,
    useFactory: (
      driverRepo: IDriverRepository,
      raceRepo: IRaceRepository,
      resultRepo: IResultRepository,
      leagueRepo: ILeagueRepository,
      standingRepo: IStandingRepository,
      membershipRepo: ILeagueMembershipRepository,
      registrationRepo: IRaceRegistrationRepository,
      feedRepo: IFeedRepository,
      socialRepo: ISocialGraphRepository,
      imageService: ImageServicePort,
      output: DashboardOverviewPresenter,
    ) =>
      new DashboardOverviewUseCase(
        driverRepo,
        raceRepo,
        resultRepo,
        leagueRepo,
        standingRepo,
        membershipRepo,
        registrationRepo,
        feedRepo,
        socialRepo,
        async (driverId: string) => imageService.getDriverAvatar(driverId),
        () => null,
        output,
      ),
    inject: [
      DRIVER_REPOSITORY_TOKEN,
      RACE_REPOSITORY_TOKEN,
      RESULT_REPOSITORY_TOKEN,
      LEAGUE_REPOSITORY_TOKEN,
      STANDING_REPOSITORY_TOKEN,
      LEAGUE_MEMBERSHIP_REPOSITORY_TOKEN,
      RACE_REGISTRATION_REPOSITORY_TOKEN,
      SOCIAL_FEED_REPOSITORY_TOKEN,
      SOCIAL_GRAPH_REPOSITORY_TOKEN,
      IMAGE_SERVICE_TOKEN,
      DASHBOARD_OVERVIEW_OUTPUT_PORT_TOKEN,
    ],
  },
  {
    provide: DashboardService,
    useFactory: (
      logger: Logger,
      dashboardOverviewUseCase: DashboardOverviewUseCase,
      presenter: DashboardOverviewPresenter,
      imageService: ImageServicePort,
    ) => new DashboardService(logger, dashboardOverviewUseCase, presenter, imageService),
    inject: [
      LOGGER_TOKEN,
      DASHBOARD_OVERVIEW_USE_CASE_TOKEN,
      DASHBOARD_OVERVIEW_OUTPUT_PORT_TOKEN,
      IMAGE_SERVICE_TOKEN,
    ],
  },
];