import { Injectable, Logger, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import amqp from 'amqplib';

export interface RealtimeNotificationPayload {
  userId: string;
  type: string;
  title: string;
  message: string;
  payload?: Record<string, unknown>;
}

@Injectable()
export class NotificationPublisherService implements OnModuleInit, OnModuleDestroy {
  private readonly logger = new Logger(NotificationPublisherService.name);
  private connection: { createChannel: () => Promise<amqp.Channel>; close: () => Promise<void> } | null = null;
  private channel: amqp.ConfirmChannel | amqp.Channel | null = null;
  private readonly queueName = 'id.notifications';

  constructor(private readonly config: ConfigService) {}

  async onModuleInit() {
    await this.connect();
  }

  async onModuleDestroy() {
    try {
      await this.channel?.close();
    } catch {
      // ignore shutdown errors
    }
    try {
      await this.connection?.close();
    } catch {
      // ignore shutdown errors
    }
  }

  private async connect() {
    const url = this.config.get<string>('RABBITMQ_URL', 'amqp://lendry:lendry_password@localhost:5672/');
    try {
      this.connection = (await amqp.connect(url)) as {
        createChannel: () => Promise<amqp.Channel>;
        close: () => Promise<void>;
      };
      this.channel = await this.connection.createChannel();
      await this.channel.assertQueue(this.queueName, { durable: true });
      this.logger.log('Подключение к RabbitMQ для уведомлений установлено');
    } catch (error) {
      this.logger.warn(`RabbitMQ недоступен, push-уведомления будут только в БД: ${error instanceof Error ? error.message : error}`);
    }
  }

  async publish(notification: RealtimeNotificationPayload) {
    if (!this.channel) {
      await this.connect();
    }
    if (!this.channel) return;

    const body = Buffer.from(
      JSON.stringify({
        userId: notification.userId,
        type: notification.type,
        title: notification.title,
        message: notification.message,
        payload: notification.payload ?? {}
      })
    );

    try {
      this.channel.sendToQueue(this.queueName, body, { persistent: true });
    } catch (error) {
      this.logger.warn(`Не удалось отправить уведомление в RabbitMQ: ${error instanceof Error ? error.message : error}`);
    }
  }
}
