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

export const BOT_INBOUND_QUEUE = 'chat.message.bot_inbound';

export interface BotInboundQueueMessage {
  eventType: 'message' | 'callback_query';
  botId: string;
  senderUserId: string;
  text?: string | null;
  botChatId: string;
  telegramChatId: string;
  telegramMessageId: number;
  updateId: number;
  createdAt: string;
  callbackQueryId?: string;
  callbackData?: string;
  sourceBotMessageId?: number;
}

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

  constructor(private readonly config: ConfigService) {}

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

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

  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(BOT_INBOUND_QUEUE, { durable: true });
      this.logger.log(`Очередь ${BOT_INBOUND_QUEUE} готова к публикации`);
    } catch (error) {
      this.logger.warn(
        `RabbitMQ недоступен для bot inbound: ${error instanceof Error ? error.message : error}`
      );
    }
  }

  async publish(message: BotInboundQueueMessage) {
    if (!this.channel) {
      await this.connect();
    }
    if (!this.channel) return false;

    try {
      this.channel.sendToQueue(BOT_INBOUND_QUEUE, Buffer.from(JSON.stringify(message)), { persistent: true });
      return true;
    } catch (error) {
      this.logger.warn(`Не удалось опубликовать bot inbound: ${error instanceof Error ? error.message : error}`);
      return false;
    }
  }
}
