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

import { AvatarGenerationRequestOrmEntity } from '@adapters/media/persistence/typeorm/entities/AvatarGenerationRequestOrmEntity';
import { AvatarOrmEntity } from '@adapters/media/persistence/typeorm/entities/AvatarOrmEntity';
import { MediaOrmEntity } from '@adapters/media/persistence/typeorm/entities/MediaOrmEntity';

import { TypeOrmAvatarGenerationRepository } from '@adapters/media/persistence/typeorm/repositories/TypeOrmAvatarGenerationRepository';
import { TypeOrmAvatarRepository } from '@adapters/media/persistence/typeorm/repositories/TypeOrmAvatarRepository';
import { TypeOrmMediaRepository } from '@adapters/media/persistence/typeorm/repositories/TypeOrmMediaRepository';

import { AvatarGenerationRequestOrmMapper } from '@adapters/media/persistence/typeorm/mappers/AvatarGenerationRequestOrmMapper';
import { AvatarOrmMapper } from '@adapters/media/persistence/typeorm/mappers/AvatarOrmMapper';
import { MediaOrmMapper } from '@adapters/media/persistence/typeorm/mappers/MediaOrmMapper';

import {
    AVATAR_GENERATION_REPOSITORY_TOKEN,
    AVATAR_REPOSITORY_TOKEN,
    MEDIA_REPOSITORY_TOKEN,
} from '../media/MediaPersistenceTokens';

const typeOrmFeatureImports = [
  TypeOrmModule.forFeature([
    MediaOrmEntity,
    AvatarOrmEntity,
    AvatarGenerationRequestOrmEntity,
  ]),
];

@Module({
  imports: [...typeOrmFeatureImports],
  providers: [
    { provide: MediaOrmMapper, useFactory: () => new MediaOrmMapper() },
    { provide: AvatarOrmMapper, useFactory: () => new AvatarOrmMapper() },
    { provide: AvatarGenerationRequestOrmMapper, useFactory: () => new AvatarGenerationRequestOrmMapper() },
    {
      provide: MEDIA_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: MediaOrmMapper) => new TypeOrmMediaRepository(dataSource, mapper),
      inject: [getDataSourceToken(), MediaOrmMapper],
    },
    {
      provide: AVATAR_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: AvatarOrmMapper) => new TypeOrmAvatarRepository(dataSource, mapper),
      inject: [getDataSourceToken(), AvatarOrmMapper],
    },
    {
      provide: AVATAR_GENERATION_REPOSITORY_TOKEN,
      useFactory: (dataSource: DataSource, mapper: AvatarGenerationRequestOrmMapper) => 
        new TypeOrmAvatarGenerationRepository(dataSource, mapper),
      inject: [getDataSourceToken(), AvatarGenerationRequestOrmMapper],
    },
  ],
  exports: [AVATAR_GENERATION_REPOSITORY_TOKEN, MEDIA_REPOSITORY_TOKEN, AVATAR_REPOSITORY_TOKEN],
})
export class PostgresMediaPersistenceModule {}
