import { Module } from '@nestjs/common';
import { TypeOrmModule, getDataSourceToken } from '@nestjs/typeorm';
import type { DataSource } from 'typeorm';

import { UserOrmEntity } from '@adapters/identity/persistence/typeorm/entities/UserOrmEntity';
import { TypeOrmAuthRepository } from '@adapters/identity/persistence/typeorm/repositories/TypeOrmAuthRepository';
import { TypeOrmUserRepository } from '@adapters/identity/persistence/typeorm/repositories/TypeOrmUserRepository';
import { UserOrmMapper } from '@adapters/identity/persistence/typeorm/mappers/UserOrmMapper';
import { InMemoryPasswordHashingService } from '@adapters/identity/services/InMemoryPasswordHashingService';

import {
  AUTH_REPOSITORY_TOKEN,
  PASSWORD_HASHING_SERVICE_TOKEN,
  USER_REPOSITORY_TOKEN,
} from '../identity/IdentityPersistenceTokens';

const typeOrmFeatureImports = [TypeOrmModule.forFeature([UserOrmEntity])];

@Module({
  imports: [...typeOrmFeatureImports],
  providers: [
    { provide: UserOrmMapper, useFactory: () => new UserOrmMapper() },
    {
      provide: USER_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: UserOrmMapper) => new TypeOrmUserRepository(dataSource, mapper),
      inject: [getDataSourceToken(), UserOrmMapper],
    },
    {
      provide: AUTH_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: UserOrmMapper) => new TypeOrmAuthRepository(dataSource, mapper),
      inject: [getDataSourceToken(), UserOrmMapper],
    },
    {
      provide: PASSWORD_HASHING_SERVICE_TOKEN,
      useClass: InMemoryPasswordHashingService,
    },
  ],
  exports: [USER_REPOSITORY_TOKEN, AUTH_REPOSITORY_TOKEN, PASSWORD_HASHING_SERVICE_TOKEN],
})
export class PostgresIdentityPersistenceModule {}