import { NOTIFICATION_RMQ_QUEUE } from '@app/contracts';
import { processEnvSource, resolveRabbitMqConfig } from '@app/common';
import { Logger, ShutdownSignal, ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { NotificationServiceModule, notificationServiceState } from './app.module';
import { assertNotificationTopology, notificationQueueArguments } from './rabbitmq-topology';

export async function bootstrapNotificationService(): Promise<void> {
  const app = await NestFactory.create(NotificationServiceModule, { bufferLogs: true });
  const logger = new Logger('NotificationServiceBootstrap');
  const rabbit = resolveRabbitMqConfig(processEnvSource(), 'notification-service', true);
  const port = Number(process.env.NOTIFICATION_SERVICE_PORT ?? 4001);

  app.enableShutdownHooks([ShutdownSignal.SIGINT, ShutdownSignal.SIGTERM]);
  app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
  const microservice = app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.RMQ,
    options: {
      urls: [rabbit.url],
      socketOptions: rabbit.socketOptions,
      queue: NOTIFICATION_RMQ_QUEUE,
      noAck: false,
      prefetchCount: Number(process.env.NOTIFICATION_RMQ_PREFETCH ?? 10),
      queueOptions: { durable: true, autoDelete: false, exclusive: false, arguments: notificationQueueArguments },
    },
  });
  const status = (microservice as unknown as { status: { subscribe: (callback: (value: string) => void) => void } }).status;
  status.subscribe((value) => {
    notificationServiceState.rabbitmqReady = value === 'connected' || value === 'unblocked';
  });

  const markDraining = () => { notificationServiceState.draining = true; };
  process.once('SIGTERM', markDraining);
  process.once('SIGINT', markDraining);

  await assertNotificationTopology(rabbit);
  await app.startAllMicroservices();
  notificationServiceState.rabbitmqReady = true;
  await app.listen(port, process.env.NOTIFICATION_SERVICE_HOST ?? '0.0.0.0');
  logger.log(`HTTP health endpoint listening on ${port}; consuming ${NOTIFICATION_RMQ_QUEUE}; broker=${rabbit.sanitizedEndpoint}`);
}

if (require.main === module) void bootstrapNotificationService();
