import { Provider } from '@nestjs/common';
import { EnsureInitialData } from '../../../../../adapters/bootstrap/EnsureInitialData';
import { SignupWithEmailUseCase } from '@core/identity/application/use-cases/SignupWithEmailUseCase';
import { CreateAchievementUseCase } from '@core/identity/application/use-cases/achievement/CreateAchievementUseCase';
import type { IUserRepository } from '@core/identity/domain/repositories/IUserRepository';
import type { IAchievementRepository } from '@core/identity/application/use-cases/achievement/CreateAchievementUseCase';
import type { IdentitySessionPort } from '@core/identity/application/ports/IdentitySessionPort';
import type { Logger } from '@core/shared/application';
import { InMemoryUserRepository } from '../../../../../adapters/identity/persistence/inmemory/InMemoryUserRepository';
import { InMemoryAchievementRepository } from '../../../../../adapters/persistence/inmemory/achievement/InMemoryAchievementRepository';
import { CookieIdentitySessionAdapter } from '../../../../../adapters/identity/session/CookieIdentitySessionAdapter';

// Define tokens
export const USER_REPOSITORY_TOKEN = 'IUserRepository_Bootstrap';
export const ACHIEVEMENT_REPOSITORY_TOKEN = 'IAchievementRepository_Bootstrap';
export const IDENTITY_SESSION_PORT_TOKEN = 'IdentitySessionPort_Bootstrap';
export const SIGNUP_USE_CASE_TOKEN = 'SignupWithEmailUseCase_Bootstrap';
export const CREATE_ACHIEVEMENT_USE_CASE_TOKEN = 'CreateAchievementUseCase_Bootstrap';

export const BootstrapProviders: Provider[] = [
  {
    provide: USER_REPOSITORY_TOKEN,
    useFactory: (logger: Logger) => new InMemoryUserRepository(logger),
    inject: ['Logger'],
  },
  {
    provide: ACHIEVEMENT_REPOSITORY_TOKEN,
    useClass: InMemoryAchievementRepository,
  },
  {
    provide: IDENTITY_SESSION_PORT_TOKEN,
    useFactory: (logger: Logger) => new CookieIdentitySessionAdapter(logger),
    inject: ['Logger'],
  },
  {
    provide: SIGNUP_USE_CASE_TOKEN,
    useFactory: (userRepository: IUserRepository, sessionPort: IdentitySessionPort) => {
      return new SignupWithEmailUseCase(userRepository, sessionPort);
    },
    inject: [USER_REPOSITORY_TOKEN, IDENTITY_SESSION_PORT_TOKEN],
  },
  {
    provide: CREATE_ACHIEVEMENT_USE_CASE_TOKEN,
    useFactory: (achievementRepository: IAchievementRepository) => {
      return new CreateAchievementUseCase(achievementRepository);
    },
    inject: [ACHIEVEMENT_REPOSITORY_TOKEN],
  },
  {
    provide: EnsureInitialData,
    useFactory: (signupUseCase: SignupWithEmailUseCase, createAchievementUseCase: CreateAchievementUseCase, logger: Logger) => {
      return new EnsureInitialData(signupUseCase, createAchievementUseCase, logger);
    },
    inject: [SIGNUP_USE_CASE_TOKEN, CREATE_ACHIEVEMENT_USE_CASE_TOKEN, 'Logger'],
  },
];