import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Logger } from '@nestjs/common';
import { Job } from 'bullmq';
import { PrismaService } from '../../../prisma/prisma.service';
import { BotManagerService } from '../services/bot-manager.service';
import { TelegramApiService } from '../services/telegram-api.service';
import { MessageButton } from '../interfaces/scenario.interface';

export interface DelayNodeJobData {
  botId: string;
  subscriberId: string;
  chatId: string;
  nodeId: string;
  nextNodeId: string | null;
  cancelOn: string | null;
  message: { text: string; buttons?: MessageButton[] } | null;
  variables: Record<string, string | number | boolean>;
}

@Processor('telegram-bot-delay')
export class DelayNodeProcessor extends WorkerHost {
  private readonly logger = new Logger(DelayNodeProcessor.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly botManager: BotManagerService,
    private readonly telegramApi: TelegramApiService,
  ) {
    super();
  }

  async process(job: Job<DelayNodeJobData>): Promise<void> {
    const { botId, subscriberId, chatId, nodeId, nextNodeId, cancelOn, message, variables } =
      job.data;

    // Check if subscriber is still at this delay node
    const subscriber = await this.prisma.tgBotSubscriber.findUnique({
      where: { id: subscriberId },
    });
    if (!subscriber || subscriber.currentNodeId !== nodeId) {
      this.logger.log(`Subscriber ${subscriberId} moved away from delay node, skipping`);
      return;
    }

    // Check cancelOn condition
    if (cancelOn) {
      const currentVars = (subscriber.variables as Record<string, unknown>) ?? {};
      const merged = { ...variables, ...currentVars };
      // Simple eval — reuse from engine (for now do inline check)
      const match = cancelOn.match(/^(\w+)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
      if (match) {
        const left = Number(merged[match[1]] ?? 0);
        const right = Number(match[3]);
        let cancelled = false;
        switch (match[2]) {
          case '>=':
            cancelled = left >= right;
            break;
          case '<=':
            cancelled = left <= right;
            break;
          case '>':
            cancelled = left > right;
            break;
          case '<':
            cancelled = left < right;
            break;
          case '==':
            cancelled = left === right;
            break;
          case '!=':
            cancelled = left !== right;
            break;
        }
        if (cancelled) {
          this.logger.log(`Delay node cancelled for subscriber ${subscriberId}: ${cancelOn}`);
          return;
        }
      }
    }

    // Send reminder message if configured
    const bot = await this.botManager.getWithToken(botId);
    if (message?.text) {
      let reply_markup: Record<string, unknown> | undefined;
      if (message.buttons?.length) {
        reply_markup = this.telegramApi.buildInlineKeyboard(
          message.buttons.map((b) => ({
            text: b.text,
            ...(b.action === 'goto' ? { callback_data: `goto:${b.target}` } : {}),
            ...(b.action === 'url' ? { url: b.target ?? '' } : {}),
          })),
        );
      }

      await this.telegramApi.sendMessage(bot.token, {
        chat_id: chatId,
        text: message.text,
        parse_mode: 'HTML',
        reply_markup,
      });
    }

    // If nextNodeId — advance subscriber state
    if (nextNodeId) {
      await this.prisma.tgBotSubscriber.update({
        where: { id: subscriberId },
        data: { currentNodeId: nextNodeId },
      });
    }
  }
}
