import { Module } from '@nestjs/common';
import { PrismaModule } from './persistence/prisma/prisma.module';
import { UnitOfWork } from './persistence/unit-of-work/unit-of-work';
import {
  ContributionAccountRepository,
  ContributionRecordRepository,
  SyncedDataRepository,
  UnallocatedContributionRepository,
  SystemAccountRepository,
  OutboxRepository,
} from './persistence/repositories';
import { KafkaModule } from './kafka/kafka.module';
import { KafkaProducerService } from './kafka/kafka-producer.service';
import { CDCConsumerService } from './kafka/cdc-consumer.service';
import { RedisModule } from './redis/redis.module';
import { SYNCED_DATA_REPOSITORY } from '../domain/repositories/synced-data.repository.interface';

// Repository injection tokens
export const CONTRIBUTION_ACCOUNT_REPOSITORY = 'CONTRIBUTION_ACCOUNT_REPOSITORY';
export const CONTRIBUTION_RECORD_REPOSITORY = 'CONTRIBUTION_RECORD_REPOSITORY';

@Module({
  imports: [PrismaModule, KafkaModule, RedisModule],
  providers: [
    UnitOfWork,
    // Repositories
    ContributionAccountRepository,
    ContributionRecordRepository,
    SyncedDataRepository,
    UnallocatedContributionRepository,
    SystemAccountRepository,
    OutboxRepository,
    // Repository interface bindings
    {
      provide: CONTRIBUTION_ACCOUNT_REPOSITORY,
      useClass: ContributionAccountRepository,
    },
    {
      provide: CONTRIBUTION_RECORD_REPOSITORY,
      useClass: ContributionRecordRepository,
    },
    {
      provide: SYNCED_DATA_REPOSITORY,
      useClass: SyncedDataRepository,
    },
    // Kafka
    KafkaProducerService,
    CDCConsumerService,
  ],
  exports: [
    UnitOfWork,
    ContributionAccountRepository,
    ContributionRecordRepository,
    SyncedDataRepository,
    UnallocatedContributionRepository,
    SystemAccountRepository,
    OutboxRepository,
    CONTRIBUTION_ACCOUNT_REPOSITORY,
    CONTRIBUTION_RECORD_REPOSITORY,
    SYNCED_DATA_REPOSITORY,
    KafkaProducerService,
    CDCConsumerService,
    RedisModule,
  ],
})
export class InfrastructureModule {}
