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

// Import core interfaces
import { IAvatarGenerationRepository } from '@core/media/domain/repositories/IAvatarGenerationRepository';
import { IMediaRepository } from '@core/media/domain/repositories/IMediaRepository';
import { IAvatarRepository } from '@core/media/domain/repositories/IAvatarRepository';
import { FaceValidationPort } from '@core/media/application/ports/FaceValidationPort';
import { AvatarGenerationPort } from '@core/media/application/ports/AvatarGenerationPort';
import { MediaStoragePort } from '@core/media/application/ports/MediaStoragePort';
import type { Logger, UseCaseOutputPort } from '@core/shared/application';

// Import use cases
import { RequestAvatarGenerationUseCase } from '@core/media/application/use-cases/RequestAvatarGenerationUseCase';
import { UploadMediaUseCase } from '@core/media/application/use-cases/UploadMediaUseCase';
import { GetMediaUseCase } from '@core/media/application/use-cases/GetMediaUseCase';
import { DeleteMediaUseCase } from '@core/media/application/use-cases/DeleteMediaUseCase';
import { GetAvatarUseCase } from '@core/media/application/use-cases/GetAvatarUseCase';
import { UpdateAvatarUseCase } from '@core/media/application/use-cases/UpdateAvatarUseCase';

// Import result types
import type { RequestAvatarGenerationResult } from '@core/media/application/use-cases/RequestAvatarGenerationUseCase';
import type { UploadMediaResult } from '@core/media/application/use-cases/UploadMediaUseCase';
import type { GetMediaResult } from '@core/media/application/use-cases/GetMediaUseCase';
import type { DeleteMediaResult } from '@core/media/application/use-cases/DeleteMediaUseCase';
import type { GetAvatarResult } from '@core/media/application/use-cases/GetAvatarUseCase';
import type { UpdateAvatarResult } from '@core/media/application/use-cases/UpdateAvatarUseCase';

// Import presenters
import { RequestAvatarGenerationPresenter } from './presenters/RequestAvatarGenerationPresenter';
import { UploadMediaPresenter } from './presenters/UploadMediaPresenter';
import { GetMediaPresenter } from './presenters/GetMediaPresenter';
import { DeleteMediaPresenter } from './presenters/DeleteMediaPresenter';
import { GetAvatarPresenter } from './presenters/GetAvatarPresenter';
import { UpdateAvatarPresenter } from './presenters/UpdateAvatarPresenter';

import {
  AVATAR_GENERATION_REPOSITORY_TOKEN,
  MEDIA_REPOSITORY_TOKEN,
  AVATAR_REPOSITORY_TOKEN,
  FACE_VALIDATION_PORT_TOKEN,
  AVATAR_GENERATION_PORT_TOKEN,
  MEDIA_STORAGE_PORT_TOKEN,
  LOGGER_TOKEN,
  REQUEST_AVATAR_GENERATION_USE_CASE_TOKEN,
  UPLOAD_MEDIA_USE_CASE_TOKEN,
  GET_MEDIA_USE_CASE_TOKEN,
  DELETE_MEDIA_USE_CASE_TOKEN,
  GET_AVATAR_USE_CASE_TOKEN,
  UPDATE_AVATAR_USE_CASE_TOKEN,
  REQUEST_AVATAR_GENERATION_OUTPUT_PORT_TOKEN,
  UPLOAD_MEDIA_OUTPUT_PORT_TOKEN,
  GET_MEDIA_OUTPUT_PORT_TOKEN,
  DELETE_MEDIA_OUTPUT_PORT_TOKEN,
  GET_AVATAR_OUTPUT_PORT_TOKEN,
  UPDATE_AVATAR_OUTPUT_PORT_TOKEN,
} from './MediaTokens';

export * from './MediaTokens';

import type { FaceValidationResult } from '@core/media/application/ports/FaceValidationPort';
import type { AvatarGenerationResult } from '@core/media/application/ports/AvatarGenerationPort';

// External adapters (ports) - these remain mock implementations
class MockFaceValidationAdapter implements FaceValidationPort {
  async validateFacePhoto(): Promise<FaceValidationResult> {
    return {
      isValid: true,
      hasFace: true,
      faceCount: 1,
      confidence: 0.95,
    };
  }
}

class MockAvatarGenerationAdapter implements AvatarGenerationPort {
  async generateAvatars(): Promise<AvatarGenerationResult> {
    return {
      success: true,
      avatars: [
        { url: 'https://cdn.example.com/avatars/mock-avatar-1.png' },
        { url: 'https://cdn.example.com/avatars/mock-avatar-2.png' },
        { url: 'https://cdn.example.com/avatars/mock-avatar-3.png' },
      ],
    };
  }
}

class MockLogger implements Logger {
  debug(): void {}
  info(): void {}
  warn(): void {}
  error(): void {}
}

import { MediaGenerationService } from '@core/media/domain/services/MediaGenerationService';
import { MediaResolverAdapter } from '@adapters/media/MediaResolverAdapter';
import { FileSystemMediaStorageAdapter } from '@adapters/media/ports/FileSystemMediaStorageAdapter';

export const MediaProviders: Provider[] = [
  MediaGenerationService,
  {
    provide: MediaResolverAdapter,
    useFactory: () => new MediaResolverAdapter({}),
  },
  RequestAvatarGenerationPresenter,
  UploadMediaPresenter,
  GetMediaPresenter,
  DeleteMediaPresenter,
  GetAvatarPresenter,
  UpdateAvatarPresenter,
  {
    provide: FACE_VALIDATION_PORT_TOKEN,
    useClass: MockFaceValidationAdapter,
  },
  {
    provide: AVATAR_GENERATION_PORT_TOKEN,
    useClass: MockAvatarGenerationAdapter,
  },
  {
    provide: MEDIA_STORAGE_PORT_TOKEN,
    useFactory: () => new FileSystemMediaStorageAdapter({
      baseDir: process.env.MEDIA_STORAGE_DIR || '/data/media',
    }),
  },
  {
    provide: LOGGER_TOKEN,
    useClass: MockLogger,
  },
  // Output ports
  {
    provide: REQUEST_AVATAR_GENERATION_OUTPUT_PORT_TOKEN,
    useExisting: RequestAvatarGenerationPresenter,
  },
  {
    provide: UPLOAD_MEDIA_OUTPUT_PORT_TOKEN,
    useExisting: UploadMediaPresenter,
  },
  {
    provide: GET_MEDIA_OUTPUT_PORT_TOKEN,
    useExisting: GetMediaPresenter,
  },
  {
    provide: DELETE_MEDIA_OUTPUT_PORT_TOKEN,
    useExisting: DeleteMediaPresenter,
  },
  {
    provide: GET_AVATAR_OUTPUT_PORT_TOKEN,
    useExisting: GetAvatarPresenter,
  },
  {
    provide: UPDATE_AVATAR_OUTPUT_PORT_TOKEN,
    useExisting: UpdateAvatarPresenter,
  },
  // Use cases
  {
    provide: REQUEST_AVATAR_GENERATION_USE_CASE_TOKEN,
    useFactory: (avatarRepo: IAvatarGenerationRepository, faceValidation: FaceValidationPort, avatarGeneration: AvatarGenerationPort, output: UseCaseOutputPort<RequestAvatarGenerationResult>, logger: Logger) =>
      new RequestAvatarGenerationUseCase(avatarRepo, faceValidation, avatarGeneration, output, logger),
    inject: [AVATAR_GENERATION_REPOSITORY_TOKEN, FACE_VALIDATION_PORT_TOKEN, AVATAR_GENERATION_PORT_TOKEN, REQUEST_AVATAR_GENERATION_OUTPUT_PORT_TOKEN, LOGGER_TOKEN],
  },
  {
    provide: UPLOAD_MEDIA_USE_CASE_TOKEN,
    useFactory: (mediaRepo: IMediaRepository, mediaStorage: MediaStoragePort, output: UseCaseOutputPort<UploadMediaResult>, logger: Logger) =>
      new UploadMediaUseCase(mediaRepo, mediaStorage, output, logger),
    inject: [MEDIA_REPOSITORY_TOKEN, MEDIA_STORAGE_PORT_TOKEN, UPLOAD_MEDIA_OUTPUT_PORT_TOKEN, LOGGER_TOKEN],
  },
  {
    provide: GET_MEDIA_USE_CASE_TOKEN,
    useFactory: (mediaRepo: IMediaRepository, output: UseCaseOutputPort<GetMediaResult>, logger: Logger) =>
      new GetMediaUseCase(mediaRepo, output, logger),
    inject: [MEDIA_REPOSITORY_TOKEN, GET_MEDIA_OUTPUT_PORT_TOKEN, LOGGER_TOKEN],
  },
  {
    provide: DELETE_MEDIA_USE_CASE_TOKEN,
    useFactory: (mediaRepo: IMediaRepository, mediaStorage: MediaStoragePort, output: UseCaseOutputPort<DeleteMediaResult>, logger: Logger) =>
      new DeleteMediaUseCase(mediaRepo, mediaStorage, output, logger),
    inject: [MEDIA_REPOSITORY_TOKEN, MEDIA_STORAGE_PORT_TOKEN, DELETE_MEDIA_OUTPUT_PORT_TOKEN, LOGGER_TOKEN],
  },
  {
    provide: GET_AVATAR_USE_CASE_TOKEN,
    useFactory: (avatarRepo: IAvatarRepository, output: UseCaseOutputPort<GetAvatarResult>, logger: Logger) =>
      new GetAvatarUseCase(avatarRepo, output, logger),
    inject: [AVATAR_REPOSITORY_TOKEN, GET_AVATAR_OUTPUT_PORT_TOKEN, LOGGER_TOKEN],
  },
  {
    provide: UPDATE_AVATAR_USE_CASE_TOKEN,
    useFactory: (avatarRepo: IAvatarRepository, output: UseCaseOutputPort<UpdateAvatarResult>, logger: Logger) =>
      new UpdateAvatarUseCase(avatarRepo, output, logger),
    inject: [AVATAR_REPOSITORY_TOKEN, UPDATE_AVATAR_OUTPUT_PORT_TOKEN, LOGGER_TOKEN],
  },
];