import { Module } from '@nestjs/common';

import { LoggingModule } from '../../domain/logging/LoggingModule';

import type { Logger } from '@core/shared/application/Logger';

import type { INotificationRepository } from '@core/notifications/domain/repositories/INotificationRepository';
import type { INotificationPreferenceRepository } from '@core/notifications/domain/repositories/INotificationPreferenceRepository';
import type { NotificationService } from '@core/notifications/application/ports/NotificationService';
import type { NotificationGatewayRegistry } from '@core/notifications/application/ports/NotificationGateway';

import { InMemoryNotificationRepository } from '@adapters/notifications/persistence/inmemory/InMemoryNotificationRepository';
import { InMemoryNotificationPreferenceRepository } from '@adapters/notifications/persistence/inmemory/InMemoryNotificationPreferenceRepository';
import { NotificationServiceAdapter } from '@adapters/notifications/ports/NotificationServiceAdapter';
import { InMemoryNotificationGatewayRegistry } from '@adapters/notifications/ports/InMemoryNotificationGatewayRegistry';

import { NOTIFICATION_REPOSITORY_TOKEN, NOTIFICATION_PREFERENCE_REPOSITORY_TOKEN } from '../notifications/NotificationsPersistenceTokens';

export const NOTIFICATION_SERVICE_TOKEN = 'INotificationService';
export const NOTIFICATION_GATEWAY_REGISTRY_TOKEN = 'INotificationGatewayRegistry';

@Module({
  imports: [LoggingModule],
  providers: [
    {
      provide: NOTIFICATION_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): INotificationRepository =>
        new InMemoryNotificationRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: NOTIFICATION_PREFERENCE_REPOSITORY_TOKEN,
      useFactory: (logger: Logger): INotificationPreferenceRepository =>
        new InMemoryNotificationPreferenceRepository(logger),
      inject: ['Logger'],
    },
    {
      provide: NOTIFICATION_GATEWAY_REGISTRY_TOKEN,
      useFactory: (): NotificationGatewayRegistry =>
        new InMemoryNotificationGatewayRegistry(),
      inject: [],
    },
    {
      provide: NOTIFICATION_SERVICE_TOKEN,
      useFactory: (
        notificationRepo: INotificationRepository,
        preferenceRepo: INotificationPreferenceRepository,
        gatewayRegistry: NotificationGatewayRegistry,
        logger: Logger,
      ): NotificationService =>
        new NotificationServiceAdapter(notificationRepo, preferenceRepo, gatewayRegistry, logger),
      inject: [
        NOTIFICATION_REPOSITORY_TOKEN,
        NOTIFICATION_PREFERENCE_REPOSITORY_TOKEN,
        NOTIFICATION_GATEWAY_REGISTRY_TOKEN,
        'Logger',
      ],
    },
  ],
  exports: [
    NOTIFICATION_REPOSITORY_TOKEN,
    NOTIFICATION_PREFERENCE_REPOSITORY_TOKEN,
    NOTIFICATION_SERVICE_TOKEN,
    NOTIFICATION_GATEWAY_REGISTRY_TOKEN,
  ],
})
export class InMemoryNotificationsPersistenceModule {}