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

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

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

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

@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,
    },
    {
      provide: MAGIC_LINK_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, logger: Logger) => new TypeOrmMagicLinkRepository(dataSource, logger),
      inject: [getDataSourceToken(), 'Logger'],
    },
    {
      provide: COMPANY_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: CompanyOrmMapper) => new TypeOrmCompanyRepository(dataSource, mapper),
      inject: [getDataSourceToken(), CompanyOrmMapper],
    },
    { provide: CompanyOrmMapper, useFactory: () => new CompanyOrmMapper() },
  ],
  exports: [USER_REPOSITORY_TOKEN, AUTH_REPOSITORY_TOKEN, PASSWORD_HASHING_SERVICE_TOKEN, MAGIC_LINK_REPOSITORY_TOKEN, COMPANY_REPOSITORY_TOKEN],
})
export class PostgresIdentityPersistenceModule {}