const axios = require('axios');
const crypto = require('crypto');
const path = require('path');
const fs = require('fs');
const { pool } = require('../../config/database');
const { logger } = require('../../config/logger');
const { sendMessage: queueMessage } = require('../MessageService');

class CloudFlowService {
  static safeJsonParse(value, fallback) {
    if (!value) return fallback;
    try {
      if (typeof value === 'object') return value;
      return JSON.parse(value);
    } catch (error) {
      logger.error('Error parsing flow JSON', { error: error.message });
      return fallback;
    }
  }

  static normalizeFlowText(text) {
    return String(text || '')
      .toLowerCase()
      .normalize('NFD')
      .replace(/[\u0300-\u036f]/g, '')
      .replace(/[^a-z0-9\s]/g, ' ')
      .replace(/\s+/g, ' ')
      .trim();
  }

  static isKeywordTriggerMatch(triggerValue, normalizedText, messageWords) {
    const normalizedTrigger = CloudFlowService.normalizeFlowText(triggerValue || '');
    if (!normalizedTrigger) return false;
    if (normalizedTrigger.includes(' ')) {
      return normalizedText.includes(normalizedTrigger);
    }
    return messageWords.includes(normalizedTrigger);
  }

  static async ensureFlowTables() {
    await pool.execute(`
      CREATE TABLE IF NOT EXISTS whatsapp_cloud_flows (
        id INT AUTO_INCREMENT PRIMARY KEY,
        flow_id VARCHAR(64) NOT NULL,
        tenant_id INT NOT NULL,
        account_id VARCHAR(64),
        name VARCHAR(255) NOT NULL,
        description TEXT,
        active BOOLEAN DEFAULT FALSE,
        trigger_type VARCHAR(50),
        trigger_value VARCHAR(255),
        nodes JSON,
        connections JSON,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uniq_flow (tenant_id, flow_id),
        INDEX idx_tenant (tenant_id),
        INDEX idx_account (account_id),
        INDEX idx_active (active)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    `);

    await pool.execute(`
      CREATE TABLE IF NOT EXISTS whatsapp_cloud_flow_sessions (
        id INT AUTO_INCREMENT PRIMARY KEY,
        tenant_id INT NOT NULL,
        account_id VARCHAR(64),
        contact_phone VARCHAR(30) NOT NULL,
        flow_id VARCHAR(64) NOT NULL,
        current_node_id VARCHAR(64),
        waiting_node_id VARCHAR(64),
        waiting_type VARCHAR(32),
        variables JSON,
        updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uniq_session (tenant_id, account_id, contact_phone, flow_id),
        INDEX idx_contact (contact_phone),
        INDEX idx_flow (flow_id)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    `);
  }

  static resolveWaitingNextNode(node, message, connections) {
    if (node.type === 'button_message') {
      const replyId = message?.interactive?.button_reply?.id || message?.button?.payload || message?.button?.text;
      const replyText = message?.interactive?.button_reply?.title || message?.button?.text || message?.text?.body || '';
      const buttons = node.config?.buttons || [];
      const matchIndex = buttons.findIndex((btn, idx) => {
        const expectedId = `btn_${node.id}_${idx}`;
        return replyId === expectedId || replyText === btn.text;
      });
      if (matchIndex >= 0) {
        const handle = `button-${matchIndex}`;
        const conn = connections.find(c => c.from === node.id && (c.fromHandle || 'default') === handle);
        return conn?.to || null;
      }
    }

    if (node.type === 'list_message') {
      const replyId = message?.interactive?.list_reply?.id;
      const items = node.config?.items || [];
      const matchIndex = items.findIndex((item, idx) => {
        const expectedId = item.id || `row_${node.id}_${idx}`;
        return replyId === expectedId;
      });
      if (matchIndex >= 0) {
        const conn = connections.find(c => c.from === node.id);
        return conn?.to || null;
      }
    }

    if (node.type === 'menu_options') {
      const replyId = message?.interactive?.list_reply?.id;
      const options = node.config?.options || [];
      const matchIndex = options.findIndex((opt, idx) => {
        const expectedId = opt.value || `row_${node.id}_${idx}`;
        return replyId === expectedId;
      });
      if (matchIndex >= 0) {
        const conn = connections.find(c => c.from === node.id);
        return conn?.to || null;
      }
    }

    return null;
  }

  static getStartNode(flow) {
    const targets = new Set((flow.connections || []).map(c => c.to));
    const start = (flow.nodes || []).find(n => !targets.has(n.id));
    return start || (flow.nodes || [])[0] || null;
  }

  static getNextNodeId(flow, nodeId, handle = 'default') {
    const conn = (flow.connections || []).find(c => c.from === nodeId && (c.fromHandle || 'default') === handle);
    return conn?.to || null;
  }

  static async processFlowAutoReply({
    tenantId,
    accountId,
    account,
    conversationId,
    contactPhone,
    contactName,
    message,
    textBody,
    retry = false
  }) {
    try {
      let flows = [];
      const accountIdValue = accountId !== undefined && accountId !== null ? String(accountId) : '';
      try {
        const [flowRows] = await pool.execute(
          `SELECT * FROM whatsapp_cloud_flows 
           WHERE tenant_id = ? 
             AND (active = 1 OR active IS NULL)
             AND (account_id = ? OR account_id IS NULL OR account_id = '' OR account_id = '0' OR account_id = 0)
           ORDER BY updated_at DESC`,
          [tenantId, accountIdValue]
        );
        flows = flowRows;
      } catch (error) {
        if (!retry && error.code === 'ER_NO_SUCH_TABLE') {
          await CloudFlowService.ensureFlowTables();
          return CloudFlowService.processFlowAutoReply({
            tenantId,
            accountId,
            account,
            conversationId,
            contactPhone,
            contactName,
            message,
            textBody,
            retry: true
          });
        }
        throw error;
      }

      if (!flows || flows.length === 0) {
        try {
          const [fallbackRows] = await pool.execute(
            `SELECT * FROM whatsapp_cloud_flows 
             WHERE tenant_id = ? AND (active = 1 OR active IS NULL)
             ORDER BY updated_at DESC`,
            [tenantId]
          );
          flows = fallbackRows;
        } catch (error) {
          throw error;
        }
      }

      if (!flows || flows.length === 0) {
        return false;
      }

      let sessions = [];
      try {
        const [sessionRows] = await pool.execute(
          `SELECT * FROM whatsapp_cloud_flow_sessions 
           WHERE tenant_id = ? AND contact_phone = ? AND (account_id = ? OR account_id IS NULL OR account_id = '' OR account_id = '0' OR account_id = 0)
           ORDER BY updated_at DESC LIMIT 1`,
          [tenantId, contactPhone, accountIdValue]
        );
        sessions = sessionRows;
      } catch (error) {
        if (!retry && error.code === 'ER_NO_SUCH_TABLE') {
          await CloudFlowService.ensureFlowTables();
          return CloudFlowService.processFlowAutoReply({
            tenantId,
            accountId,
            account,
            conversationId,
            contactPhone,
            contactName,
            message,
            textBody,
            retry: true
          });
        }
        throw error;
      }

      const activeSession = sessions?.[0] || null;
      let sessionVariables = activeSession
        ? CloudFlowService.safeJsonParse(activeSession.variables, {})
        : {};
      const normalizedText = CloudFlowService.normalizeFlowText(textBody || '');
      const messageWords = normalizedText.split(' ').filter(Boolean);

      let flowRow = null;
      let flow = null;
      for (const row of flows) {
        if (!row?.nodes) continue;
        const nodes = CloudFlowService.safeJsonParse(row.nodes, []);
        const connections = CloudFlowService.safeJsonParse(row.connections, []);
        if (!nodes || nodes.length === 0) continue;
        const triggerType = row.trigger_type || 'keyword';
        if (triggerType === 'welcome') {
          const now = Date.now();
          const windowMs = 10 * 60 * 1000;
          if (!activeSession?.variables) {
            flowRow = row;
            flow = { ...row, nodes, connections };
            break;
          }
          const existingVars = CloudFlowService.safeJsonParse(activeSession.variables, {});
          const lastSentAt = new Date(existingVars?.welcome?.lastSentAt || 0).getTime();
          if (!lastSentAt || (now - lastSentAt) > windowMs) {
            flowRow = row;
            flow = { ...row, nodes, connections };
            break;
          }
          continue;
        }
        const triggerValue = row.trigger_value || '';
        if (triggerValue === '*' || triggerValue === 'any' || triggerType === 'any') {
          flowRow = row;
          flow = { ...row, nodes, connections };
          break;
        }
        if (triggerType === 'keyword') {
          const matched = CloudFlowService.isKeywordTriggerMatch(triggerValue, normalizedText, messageWords);
          if (matched) {
            flowRow = row;
            flow = { ...row, nodes, connections };
            break;
          }
        }
      }

      if (!flowRow || !flow) return false;

      if (activeSession && activeSession.waiting_type === 'ai') {
        const aiSettings = sessionVariables.ai || {};
        if (!aiSettings.aiConfigId) {
          if (sessionVariables.ai) delete sessionVariables.ai;
          await pool.execute(
            `UPDATE whatsapp_cloud_flow_sessions 
             SET waiting_node_id = NULL, waiting_type = NULL, variables = ? 
             WHERE id = ?`,
            [JSON.stringify(sessionVariables), activeSession.id]
          );
        } else {
          const aiHandled = await CloudFlowService.processCloudAIResponse({
            tenantId,
            account,
            conversationId,
            contactPhone,
            message,
            textBody,
            aiSettings
          });
          return aiHandled;
        }
      }

      if (activeSession && activeSession.waiting_type) {
        const waitNode = flow.nodes.find(n => n.id === activeSession.waiting_node_id);
        if (waitNode) {
          const nextNodeId = CloudFlowService.resolveWaitingNextNode(waitNode, message, flow.connections);
          if (nextNodeId) {
            await pool.execute(
              `UPDATE whatsapp_cloud_flow_sessions 
               SET current_node_id = ?, waiting_node_id = NULL, waiting_type = NULL 
               WHERE id = ?`,
              [nextNodeId, activeSession.id]
            );
            await CloudFlowService.executeFlowFromNode({
              tenantId,
              accountId,
              account,
              conversationId,
              contactPhone,
              contactName,
              flow,
              startNodeId: nextNodeId,
              sessionId: activeSession.id,
              message,
              textBody
            });
            return true;
          }
          await pool.execute(
            `UPDATE whatsapp_cloud_flow_sessions 
             SET waiting_node_id = NULL, waiting_type = NULL 
             WHERE id = ?`,
            [activeSession.id]
          );
          activeSession.waiting_node_id = null;
          activeSession.waiting_type = null;
        }
      }

      const startNode = CloudFlowService.getStartNode(flow);
      if (!startNode) return false;

      let sessionId = activeSession?.id;
      const isWelcomeFlow = (flowRow.trigger_type || 'keyword') === 'welcome';
      if (isWelcomeFlow) {
        sessionVariables = {
          ...sessionVariables,
          welcome: {
            ...sessionVariables.welcome,
            lastSentAt: new Date().toISOString()
          }
        };
      }
      if (!sessionId) {
        const [result] = await pool.execute(
          `INSERT INTO whatsapp_cloud_flow_sessions 
           (tenant_id, account_id, contact_phone, flow_id, current_node_id, variables)
           VALUES (?, ?, ?, ?, ?, ?)`,
          [tenantId, String(accountId), contactPhone, flow.id, startNode.id, JSON.stringify(sessionVariables)]
        );
        sessionId = result.insertId;
      } else {
        await pool.execute(
          `UPDATE whatsapp_cloud_flow_sessions SET current_node_id = ?, variables = ? WHERE id = ?`,
          [startNode.id, JSON.stringify(sessionVariables), sessionId]
        );
      }

      await CloudFlowService.executeFlowFromNode({
        tenantId,
        accountId,
        account,
        conversationId,
        contactPhone,
        contactName,
        flow,
        startNodeId: startNode.id,
        sessionId,
        message,
        textBody
      });
      return true;
    } catch (error) {
      logger.error('Error processing flow auto-reply', {
        error: error.message,
        stack: error.stack,
        code: error.code,
        sqlMessage: error.sqlMessage
      });
      return false;
    }
  }

  static async executeFlowFromNode({
    tenantId,
    accountId,
    account,
    conversationId,
    contactPhone,
    contactName,
    flow,
    startNodeId,
    sessionId,
    message,
    textBody
  }) {
    let currentNodeId = startNodeId;
    let steps = 0;

    while (currentNodeId && steps < 10) {
      steps += 1;
      const node = (flow.nodes || []).find(n => n.id === currentNodeId);
      if (!node) break;

      if (node.type === 'send_message') {
        const body = node.config?.message || node.content || '';
        if (body) {
          const sent = await CloudFlowService.sendFlowTextMessage({
            tenantId,
            account,
            conversationId,
            contactPhone,
            message: body
          });
          if (!sent) {
            return;
          }
        }
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      if (node.type === 'button_message') {
        const sent = await CloudFlowService.sendFlowButtonsMessage({
          tenantId,
          account,
          conversationId,
          contactPhone,
          node
        });
        if (!sent) {
          return;
        }
        await pool.execute(
          `UPDATE whatsapp_cloud_flow_sessions 
           SET current_node_id = ?, waiting_node_id = ?, waiting_type = ? 
           WHERE id = ?`,
          [node.id, node.id, 'button_message', sessionId]
        );
        return;
      }

      if (node.type === 'list_message') {
        const sent = await CloudFlowService.sendFlowListMessage({
          tenantId,
          account,
          conversationId,
          contactPhone,
          node
        });
        if (!sent) {
          return;
        }
        await pool.execute(
          `UPDATE whatsapp_cloud_flow_sessions 
           SET current_node_id = ?, waiting_node_id = ?, waiting_type = ? 
           WHERE id = ?`,
          [node.id, node.id, 'list_message', sessionId]
        );
        return;
      }

      if (node.type === 'products') {
        const sent = await CloudFlowService.sendFlowProductsMessage({
          tenantId,
          account,
          conversationId,
          contactPhone,
          node
        });
        if (!sent) {
          return;
        }
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      if (node.type === 'cta_message') {
        const sent = await CloudFlowService.sendFlowCtaMessage({
          tenantId,
          account,
          conversationId,
          contactPhone,
          node
        });
        if (!sent) {
          return;
        }
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      if (node.type === 'send_media') {
        const sent = await CloudFlowService.sendFlowMediaMessage({
          tenantId,
          account,
          conversationId,
          contactPhone,
          node
        });
        if (!sent) {
          return;
        }
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      if (node.type === 'menu_options') {
        const sent = await CloudFlowService.sendFlowMenuOptionsMessage({
          tenantId,
          account,
          conversationId,
          contactPhone,
          node
        });
        if (!sent) {
          return;
        }
        await pool.execute(
          `UPDATE whatsapp_cloud_flow_sessions 
           SET current_node_id = ?, waiting_node_id = ?, waiting_type = ? 
           WHERE id = ?`,
          [node.id, node.id, 'menu_options', sessionId]
        );
        return;
      }

      if (node.type === 'ai_control') {
        const mode = node.config?.mode || 'enable';
        const [sessionRows] = await pool.execute(
          `SELECT variables FROM whatsapp_cloud_flow_sessions WHERE id = ?`,
          [sessionId]
        );
        const sessionVariables = CloudFlowService.safeJsonParse(sessionRows?.[0]?.variables, {});
        if (mode === 'disable') {
          if (sessionVariables.ai) delete sessionVariables.ai;
          await pool.execute(
            `UPDATE whatsapp_cloud_flow_sessions 
             SET waiting_node_id = NULL, waiting_type = NULL, variables = ? 
             WHERE id = ?`,
            [JSON.stringify(sessionVariables), sessionId]
          );
          currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
          continue;
        }
        const aiConfigId = node.config?.aiConfigId || '';
        if (!aiConfigId) {
          if (sessionVariables.ai) delete sessionVariables.ai;
          await pool.execute(
            `UPDATE whatsapp_cloud_flow_sessions 
             SET waiting_node_id = NULL, waiting_type = NULL, variables = ? 
             WHERE id = ?`,
            [JSON.stringify(sessionVariables), sessionId]
          );
          currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
          continue;
        }
        let welcomeMessage = (node.config?.welcomeMessage || '').trim();
        if (welcomeMessage) {
          let personaName = '';
          if (welcomeMessage.includes('{{persona')) {
            let configRows = [];
            if (aiConfigId) {
              [configRows] = await pool.execute(
                `SELECT persona_name, model_name 
                 FROM ai_configurations 
                 WHERE id = ? AND tenant_id = ? 
                 LIMIT 1`,
                [aiConfigId, tenantId]
              );
            }
            if (!configRows || configRows.length === 0) {
              [configRows] = await pool.execute(
                `SELECT persona_name, model_name 
                 FROM ai_configurations 
                 WHERE tenant_id = ? AND active = TRUE 
                 LIMIT 1`,
                [tenantId]
              );
            }
            const cfg = configRows?.[0] || null;
            personaName = cfg?.persona_name || cfg?.model_name || '';
            if (personaName) {
              welcomeMessage = welcomeMessage.replace(/\{\{\s*persona\s*\}\}/gi, personaName);
            }
          }
        }
        sessionVariables.ai = {
          aiConfigId,
          enabled: true,
          temperature: node.config?.temperature ?? '',
          maxTokens: node.config?.maxTokens ?? '',
          prompt: node.config?.prompt || node.config?.instructions || '',
          welcomeMessage
        };
        await pool.execute(
          `UPDATE whatsapp_cloud_flow_sessions 
           SET current_node_id = ?, waiting_node_id = ?, waiting_type = ?, variables = ? 
           WHERE id = ?`,
          [node.id, node.id, 'ai', JSON.stringify(sessionVariables), sessionId]
        );
        if (sessionVariables.ai.welcomeMessage) {
          await CloudFlowService.sendFlowTextMessage({
            tenantId,
            account,
            conversationId,
            contactPhone,
            message: sessionVariables.ai.welcomeMessage
          });
        }
        await CloudFlowService.processCloudAIResponse({
          tenantId,
          account,
          conversationId,
          contactPhone,
          message,
          textBody,
          aiSettings: sessionVariables.ai
        });
        return;
      }

      if (node.type === 'transfer') {
        const targetType = node.config?.targetType || 'store';
        const targetId = node.config?.targetId || '';
        if (targetId) {
          const storeId = targetType === 'store' ? targetId : null;
          const departmentId = targetType === 'department' ? targetId : null;
          const nextStoreId = storeId || null;
          const nextDepartmentId = null;
          const nextTransferredStore = storeId || null;
          const nextTransferredDepartment = departmentId || null;
          await pool.execute(
            `UPDATE whatsapp_cloud_conversations 
             SET store_id = ?, 
                 department_id = ?, 
                 transferred_to_store = ?, 
                 transferred_to_department = ?, 
                 transferred_at = NOW(), 
                 claimed_by_user_id = NULL, 
                 claimed_at = NULL, 
                 updated_at = NOW() 
             WHERE id = ?`,
            [nextStoreId, nextDepartmentId, nextTransferredStore, nextTransferredDepartment, conversationId]
          );
        }
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      if (node.type === 'delay') {
        const delaySeconds = Number(node.config?.delay || 0);
        const responseDelayMs = Math.max(7000, delaySeconds * 1000);
        const reactionDelayMs = 3000;
        const shouldReact = !!node.config?.reaction && !!message?.id;
        if (shouldReact) {
          await new Promise(resolve => setTimeout(resolve, reactionDelayMs));
          await CloudFlowService.sendFlowReaction({
            tenantId,
            account,
            contactPhone,
            messageId: message.id,
            emoji: node.config.reaction
          });
        }
        await new Promise(resolve => setTimeout(resolve, responseDelayMs));
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      if (node.type === 'end_chat') {
        await pool.execute(
          `UPDATE whatsapp_cloud_flow_sessions 
           SET current_node_id = NULL, waiting_node_id = NULL, waiting_type = NULL 
           WHERE id = ?`,
          [sessionId]
        );
        return;
      }

      if (node.type === 'conditions') {
        const conditions = node.config?.conditions || [];
        let nextNodeId = null;
        for (let i = 0; i < conditions.length; i += 1) {
          const condition = conditions[i];
          const conditionValue = condition?.value || '';
          const normalizedCondition = CloudFlowService.normalizeFlowText(conditionValue);
          if (normalizedCondition && CloudFlowService.normalizeFlowText(textBody || '').includes(normalizedCondition)) {
            nextNodeId = CloudFlowService.getNextNodeId(flow, node.id, `condition-${i}`);
            break;
          }
        }
        if (!nextNodeId) {
          nextNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        }
        if (!nextNodeId) return;
        currentNodeId = nextNodeId;
        continue;
      }

      if (node.type === 'collect_input') {
        await pool.execute(
          `UPDATE whatsapp_cloud_flow_sessions 
           SET current_node_id = ?, waiting_node_id = ?, waiting_type = ? 
           WHERE id = ?`,
          [node.id, node.id, 'collect_input', sessionId]
        );
        return;
      }

      if (node.type === 'update_contact') {
        const field = node.config?.field || '';
        const value = node.config?.value || '';
        if (field && value) {
          await pool.execute(
            `UPDATE whatsapp_cloud_contacts 
             SET ${field} = ?, updated_at = NOW() 
             WHERE tenant_id = ? AND phone = ?`,
            [value, tenantId, contactPhone]
          );
        }
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      if (node.type === 'save_contact') {
        const name = node.config?.name || contactName || 'Contato';
        await pool.execute(
          `INSERT INTO whatsapp_cloud_contacts (tenant_id, phone, name, created_at) 
           VALUES (?, ?, ?, NOW())
           ON DUPLICATE KEY UPDATE name = VALUES(name), updated_at = NOW()`,
          [tenantId, contactPhone, name]
        );
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      if (node.type === 'webhook') {
        const url = node.config?.url || '';
        if (url) {
          try {
            await axios.post(url, {
              tenantId,
              accountId,
              conversationId,
              contactPhone,
              contactName,
              message,
              textBody,
              flowId: flow?.id || flow?.flow_id || null
            }, { timeout: 10000 });
          } catch (webhookError) {
            logger.error('Flow webhook error', { error: webhookError.message });
          }
        }
        currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
        continue;
      }

      currentNodeId = CloudFlowService.getNextNodeId(flow, node.id);
    }
  }

  static async sendFlowTextMessage({ tenantId, account, conversationId, contactPhone, message }) {
    if (!message) return false;
    if (!account?.access_token || !account?.phone_number_id) {
      logger.error('Flow text message missing account credentials', { accountId: account?.id });
      return false;
    }
    try {
      const sendResult = await queueMessage({
        channel: 'cloud',
        tenantId,
        accountId: account?.id,
        to: contactPhone,
        messageType: 'text',
        content: message,
        awaitSend: true
      });

      if (!sendResult.success) {
        return false;
      }

      const messageId = sendResult.messageId || `flow_${Date.now()}`;
      await pool.execute(
        `INSERT INTO whatsapp_cloud_messages 
         (conversation_id, message_id, direction, message_type, text_content, status, timestamp, created_at)
         VALUES (?, ?, 'outbound', 'text', ?, 'sent', NOW(), NOW())`,
        [conversationId, messageId, message]
      );

      await pool.execute(
        `UPDATE whatsapp_cloud_conversations 
         SET last_message_text = ?, last_message_time = NOW(), last_message_from = 'business', updated_at = NOW()
         WHERE id = ?`,
        [message, conversationId]
      );
      return true;
    } catch (error) {
      logger.error('Error sending flow text message', {
        error: error.message,
        stack: error.stack,
        response: error.response?.data || null
      });
      return false;
    }
  }

  static async sendFlowMediaMessage({ tenantId, account, conversationId, contactPhone, node }) {
    try {
      if (!account?.access_token || !account?.phone_number_id) {
        logger.error('Media message missing account credentials', { accountId: account?.id });
        return false;
      }
      const mediaType = (node.config?.mediaType || 'document').toLowerCase();
      const mediaUrl = node.config?.mediaUrl || '';
      const caption = node.config?.caption || '';
      if (!mediaUrl.trim()) {
        logger.error('Media message missing media URL', { nodeId: node.id });
        return false;
      }

      const allowedTypes = new Set(['image', 'video', 'audio', 'document']);
      const type = allowedTypes.has(mediaType) ? mediaType : 'document';
      const payload = {
        messaging_product: 'whatsapp',
        to: contactPhone,
        type
      };

      let sendResult;
      if (/^https?:\/\//i.test(mediaUrl.trim())) {
        payload[type] = { link: mediaUrl.trim() };
        if (caption && type !== 'audio') {
          payload[type].caption = caption.trim();
        }
        sendResult = await queueMessage({
          channel: 'cloud',
          tenantId,
          accountId: account?.id,
          to: contactPhone,
          messageType: 'raw',
          awaitSend: true,
          metadata: {
            payload: { raw: payload }
          }
        });
      } else {
        let actualPath = mediaUrl.trim();
        if (actualPath.startsWith('/uploads/')) {
          actualPath = path.join(__dirname, '..', actualPath);
        } else if (!path.isAbsolute(actualPath)) {
          actualPath = path.join(__dirname, '..', actualPath);
        }
        if (!fs.existsSync(actualPath)) {
          logger.error('Media file not found for flow', { nodeId: node.id, path: actualPath });
          return false;
        }
        sendResult = await queueMessage({
          channel: 'cloud',
          tenantId,
          accountId: account?.id,
          to: contactPhone,
          messageType: 'media',
          awaitSend: true,
          metadata: {
            payload: {
              media: {
                mediaType: type,
                filePath: actualPath,
                fileName: path.basename(actualPath),
                mimeType: node.config?.mimeType || 'application/octet-stream',
                caption: caption?.trim() || null
              }
            }
          }
        });
      }

      if (!sendResult.success) {
        return false;
      }

      const messageId = sendResult.messageId || `flow_${Date.now()}`;
      const summary = caption?.trim() || `[${type}]`;
      await pool.execute(
        `INSERT INTO whatsapp_cloud_messages 
         (conversation_id, message_id, direction, message_type, text_content, media_url, status, timestamp, created_at)
         VALUES (?, ?, 'outbound', ?, ?, ?, 'sent', NOW(), NOW())`,
        [conversationId, messageId, type, summary, mediaUrl.trim()]
      );

      await pool.execute(
        `UPDATE whatsapp_cloud_conversations 
         SET last_message_text = ?, last_message_time = NOW(), last_message_from = 'business', updated_at = NOW()
         WHERE id = ?`,
        [summary, conversationId]
      );
      return true;
    } catch (error) {
      logger.error('Error sending flow media message', {
        error: error.message,
        stack: error.stack,
        response: error.response?.data || null
      });
      return false;
    }
  }

  static async sendFlowMenuOptionsMessage({ tenantId, account, conversationId, contactPhone, node }) {
    try {
      if (!account?.access_token || !account?.phone_number_id) {
        logger.error('Menu options message missing account credentials', { accountId: account?.id });
        return false;
      }
      const prompt = node.config?.prompt || '';
      const options = (node.config?.options || []).filter(opt => opt.label && opt.label.trim()).slice(0, 10);
      if (options.length === 0) {
        logger.error('Menu options has no valid options', { nodeId: node.id });
        return false;
      }
      const truncate = (text, max) => text.length > max ? text.slice(0, max - 1) : text;
      const bodyText = truncate((prompt && prompt.trim() ? prompt.trim() : 'Selecione uma opção'), 1024);

      const payload = {
        messaging_product: 'whatsapp',
        to: contactPhone,
        type: 'interactive',
        interactive: {
          type: 'list',
          body: { text: bodyText },
          action: {
            button: 'Selecionar',
            sections: [
              {
                title: 'Opções',
                rows: options.map((opt, index) => ({
                  id: truncate((opt.value || `row_${node.id}_${index}`).trim(), 200),
                  title: truncate(opt.label.trim(), 24)
                }))
              }
            ]
          }
        }
      };

      const sendResult = await queueMessage({
        channel: 'cloud',
        tenantId,
        accountId: account?.id,
        to: contactPhone,
        messageType: 'interactive',
        awaitSend: true,
        metadata: {
          payload: { interactive: payload.interactive }
        }
      });

      if (!sendResult.success) {
        return false;
      }

      const messageId = sendResult.messageId || `flow_${Date.now()}`;
      const summary = bodyText || options.map(opt => opt.label).join(', ');
      await pool.execute(
        `INSERT INTO whatsapp_cloud_messages 
         (conversation_id, message_id, direction, message_type, text_content, status, timestamp, created_at)
         VALUES (?, ?, 'outbound', 'interactive', ?, 'sent', NOW(), NOW())`,
        [conversationId, messageId, summary]
      );

      await pool.execute(
        `UPDATE whatsapp_cloud_conversations 
         SET last_message_text = ?, last_message_time = NOW(), last_message_from = 'business', updated_at = NOW()
         WHERE id = ?`,
        [summary, conversationId]
      );
      return true;
    } catch (error) {
      logger.error('Error sending menu options message', {
        error: error.message,
        stack: error.stack,
        response: error.response?.data || null
      });
      return false;
    }
  }

  static async sendFlowButtonsMessage({ tenantId, account, conversationId, contactPhone, node }) {
    if (!account?.access_token || !account?.phone_number_id) {
      logger.error('Button message missing account credentials', { accountId: account?.id });
      return false;
    }
    const body = node.config?.message || '';
    const footer = node.config?.footer || '';
    const rawButtons = Array.isArray(node.config?.buttons) ? node.config.buttons : [];
    const buttons = rawButtons
      .filter(btn => btn?.text && btn.text.trim())
      .slice(0, 3);
    if (buttons.length === 0) {
      logger.error('Button message has no valid buttons', { nodeId: node.id });
      return false;
    }
    const truncate = (text, max) => text.length > max ? text.slice(0, max - 1) : text;

    const payload = {
      messaging_product: 'whatsapp',
      to: contactPhone,
      type: 'interactive',
      interactive: {
        type: 'button',
        body: { text: truncate(body || ' ', 1024) },
        action: {
          buttons: buttons.map((btn, index) => ({
            type: 'reply',
            reply: { id: `btn_${node.id}_${index}`, title: truncate(btn.text.trim(), 20) }
          }))
        }
      }
    };

    if (footer) {
      payload.interactive.footer = { text: truncate(footer.trim(), 60) };
    }

    try {
      const sendResult = await queueMessage({
        channel: 'cloud',
        tenantId,
        accountId: account?.id,
        to: contactPhone,
        messageType: 'interactive',
        awaitSend: true,
        metadata: {
          payload: { interactive: payload.interactive }
        }
      });

      if (!sendResult.success) {
        return false;
      }

      const messageId = sendResult.messageId || `flow_${Date.now()}`;
      const summary = body || buttons.map(b => b.text).join(', ');
      await pool.execute(
        `INSERT INTO whatsapp_cloud_messages 
         (conversation_id, message_id, direction, message_type, text_content, status, timestamp, created_at)
         VALUES (?, ?, 'outbound', 'interactive', ?, 'sent', NOW(), NOW())`,
        [conversationId, messageId, summary]
      );

      await pool.execute(
        `UPDATE whatsapp_cloud_conversations 
         SET last_message_text = ?, last_message_time = NOW(), last_message_from = 'business', updated_at = NOW()
         WHERE id = ?`,
        [summary, conversationId]
      );
      return true;
    } catch (error) {
      logger.error('Error sending button message', {
        error: error.message,
        stack: error.stack,
        response: error.response?.data || null
      });
      return false;
    }
  }

  static async sendFlowListMessage({ tenantId, account, conversationId, contactPhone, node }) {
    try {
      if (!account?.access_token || !account?.phone_number_id) {
        logger.error('List message missing account credentials', { accountId: account?.id });
        return false;
      }
      const header = node.config?.header || '';
      const body = node.config?.body || '';
      const footer = node.config?.footer || '';
      const buttonText = node.config?.buttonText || 'Selecionar';
      const items = (node.config?.items || []).filter(item => item.title && item.title.trim()).slice(0, 10);
      if (items.length === 0) {
        logger.error('List message has no items with title', { nodeId: node.id });
        return false;
      }

      const truncate = (text, max) => text.length > max ? text.slice(0, max - 1) : text;
      const sectionTitle = truncate((header || 'Opções').trim(), 24);
      const buttonLabel = truncate(buttonText.trim(), 20);
      const bodyText = truncate((body && body.trim() ? body.trim() : 'Selecione uma opção'), 1024);

      const payload = {
        messaging_product: 'whatsapp',
        to: contactPhone,
        type: 'interactive',
        interactive: {
          type: 'list',
          body: { text: bodyText },
          action: {
            button: buttonLabel,
            sections: [
              {
                title: sectionTitle,
                rows: items.map((item, index) => ({
                  id: truncate((item.id || `row_${node.id}_${index}`).trim(), 200),
                  title: truncate(item.title.trim(), 24),
                  description: item.description ? truncate(item.description.trim(), 72) : undefined
                }))
              }
            ]
          }
        }
      };

      if (footer && footer.trim()) {
        payload.interactive.footer = { text: truncate(footer.trim(), 60) };
      }

      const sendResult = await queueMessage({
        channel: 'cloud',
        tenantId,
        accountId: account?.id,
        to: contactPhone,
        messageType: 'interactive',
        awaitSend: true,
        metadata: {
          payload: { interactive: payload.interactive }
        }
      });

      if (!sendResult.success) {
        return false;
      }

      const messageId = sendResult.messageId || `flow_${Date.now()}`;
      const summary = bodyText || items.map(i => i.title).join(', ');
      await pool.execute(
        `INSERT INTO whatsapp_cloud_messages 
         (conversation_id, message_id, direction, message_type, text_content, status, timestamp, created_at)
         VALUES (?, ?, 'outbound', 'interactive', ?, 'sent', NOW(), NOW())`,
        [conversationId, messageId, summary]
      );

      await pool.execute(
        `UPDATE whatsapp_cloud_conversations 
         SET last_message_text = ?, last_message_time = NOW(), last_message_from = 'business', updated_at = NOW()
         WHERE id = ?`,
        [summary, conversationId]
      );
      return true;
    } catch (error) {
      logger.error('Error sending list message', {
        error: error.message,
        stack: error.stack,
        response: error.response?.data || null
      });
      return false;
    }
  }

  static async sendFlowProductsMessage({ tenantId, account, conversationId, contactPhone, node }) {
    try {
      if (!account?.access_token || !account?.phone_number_id) {
        logger.error('Products message missing account credentials', { accountId: account?.id });
        return false;
      }
      const rawIds = node.config?.productIds || '';
      const limit = Math.max(1, parseInt(node.config?.limit, 10) || 5);
      const displayMode = node.config?.displayMode || 'list';
      const includePrice = node.config?.includePrice !== false;
      const message = node.config?.message || '';
      const ids = rawIds
        .split(/[\s,;]+/)
        .map(value => parseInt(value, 10))
        .filter(value => Number.isFinite(value));
      let products = [];
      if (ids.length > 0) {
        const uniqueIds = Array.from(new Set(ids));
        const placeholders = uniqueIds.map(() => '?').join(',');
        const [rows] = await pool.execute(
          `SELECT * FROM woocommerce_products WHERE tenant_id = ? AND wc_product_id IN (${placeholders}) AND is_active = TRUE`,
          [tenantId, ...uniqueIds]
        );
        const byId = new Map(rows.map(row => [String(row.wc_product_id), row]));
        products = ids.map(id => byId.get(String(id))).filter(Boolean);
      } else {
        const [rows] = await pool.execute(
          `SELECT * FROM woocommerce_products 
           WHERE tenant_id = ? AND is_active = TRUE 
           ORDER BY updated_at DESC 
           LIMIT ?`,
          [tenantId, limit]
        );
        products = rows;
      }
      if (products.length === 0) {
        logger.error('No WooCommerce products found for flow', { nodeId: node.id });
        return false;
      }
      const truncate = (text, max) => text.length > max ? text.slice(0, max - 1) : text;
      const formatPrice = (product) => {
        const price = product.sale_price || product.regular_price || product.price;
        if (!price) return 'Consulte';
        return `R$ ${parseFloat(price).toFixed(2).replace('.', ',')}`;
      };

      let payload;
      if (displayMode === 'carousel') {
        const eligibleProducts = products.filter(product => (
          (product.thumbnail_url || product.image_url) && (product.permalink || '').trim()
        ));
        if (eligibleProducts.length < 2) {
          return CloudFlowService.sendFlowProductsMessage({
            tenantId,
            account,
            conversationId,
            contactPhone,
            node: { ...node, config: { ...node.config, displayMode: 'list' } }
          });
        }
        const carouselBody = truncate(message && message.trim() ? message.trim() : 'Confira nossos produtos', 1024);
        const cards = eligibleProducts.slice(0, 10).map((product, index) => {
          const imageLink = product.thumbnail_url || product.image_url;
          const priceText = includePrice ? formatPrice(product) : '';
          const shortDesc = product.short_description || '';
          const bodyText = truncate(
            `${product.name || 'Produto'}${priceText ? `\n${priceText}` : ''}${shortDesc ? `\n${shortDesc}` : ''}`,
            160
          );
          return {
            card_index: index,
            type: 'cta_url',
            header: { type: 'image', image: { link: imageLink } },
            body: { text: bodyText },
            action: {
              name: 'cta_url',
              parameters: {
                display_text: truncate('Ver produto', 20),
                url: product.permalink
              }
            }
          };
        });
        payload = {
          messaging_product: 'whatsapp',
          to: contactPhone,
          type: 'interactive',
          interactive: {
            type: 'carousel',
            body: { text: carouselBody },
            action: { cards }
          }
        };
      } else {
        const buttonLabel = truncate('Selecionar', 20);
        const bodyText = truncate(message && message.trim() ? message.trim() : 'Selecione um produto', 1024);
        const rows = products.slice(0, 10).map(product => {
          const descriptionBase = product.short_description || '';
          const priceText = includePrice ? formatPrice(product) : '';
          const description = priceText
            ? `${priceText}${descriptionBase ? ` - ${descriptionBase}` : ''}`
            : descriptionBase;
          return {
            id: truncate(`product_${product.wc_product_id}`, 200),
            title: truncate((product.name || 'Produto').trim(), 24),
            description: description ? truncate(description.trim(), 72) : undefined
          };
        }).filter(row => row.title && row.title.trim());
        if (rows.length === 0) {
          logger.error('WooCommerce product list has no valid rows', { nodeId: node.id });
          return false;
        }
        payload = {
          messaging_product: 'whatsapp',
          to: contactPhone,
          type: 'interactive',
          interactive: {
            type: 'list',
            body: { text: bodyText },
            action: {
              button: buttonLabel,
              sections: [
                {
                  title: truncate('Produtos', 24),
                  rows
                }
              ]
            }
          }
        };
      }

      const sendResult = await queueMessage({
        channel: 'cloud',
        tenantId,
        accountId: account?.id,
        to: contactPhone,
        messageType: 'products',
        awaitSend: true,
        metadata: {
          payload: { interactive: payload.interactive }
        }
      });

      if (!sendResult.success) {
        return false;
      }

      const messageId = sendResult.messageId || `flow_${Date.now()}`;
      const summary = message && message.trim()
        ? message.trim()
        : products.map(product => product.name).join(', ');
      await pool.execute(
        `INSERT INTO whatsapp_cloud_messages 
         (conversation_id, message_id, direction, message_type, text_content, status, timestamp, created_at)
         VALUES (?, ?, 'outbound', 'interactive', ?, 'sent', NOW(), NOW())`,
        [conversationId, messageId, summary]
      );

      await pool.execute(
        `UPDATE whatsapp_cloud_conversations 
         SET last_message_text = ?, last_message_time = NOW(), last_message_from = 'business', updated_at = NOW()
         WHERE id = ?`,
        [summary, conversationId]
      );
      return true;
    } catch (error) {
      logger.error('Error sending WooCommerce products message', {
        error: error.message,
        stack: error.stack,
        response: error.response?.data || null
      });
      return false;
    }
  }

  static async sendFlowCtaMessage({ tenantId, account, conversationId, contactPhone, node }) {
    const header = node.config?.header || '';
    const body = node.config?.body || '';
    const footer = node.config?.footer || '';
    const buttonText = node.config?.buttonText || '';
    let ctaType = node.config?.ctaType || 'url';
    if (ctaType === 'cta_call' || ctaType === 'call') ctaType = 'phone';
    if (ctaType === 'cta_url') ctaType = 'url';
    if (ctaType !== 'url' && ctaType !== 'phone') ctaType = 'url';
    const ctaValue = node.config?.ctaValue || '';
    try {
      if (!account?.access_token || !account?.phone_number_id) {
        logger.error('CTA message missing account credentials', { accountId: account?.id });
        return false;
      }
      const truncate = (text, max) => text.length > max ? text.slice(0, max - 1) : text;
      const normalizeUrl = (value) => {
        const trimmed = value.trim();
        if (!trimmed) return '';
        const normalized = trimmed.startsWith('http://') || trimmed.startsWith('https://')
          ? trimmed
          : `https://${trimmed}`;
        try {
          const url = new URL(normalized);
          return url.href;
        } catch (error) {
          return '';
        }
      };
      const normalizePhone = (value) => {
        const digits = value.replace(/[^\d+]/g, '');
        if (!digits) return '';
        return digits.startsWith('+') ? digits : `+${digits}`;
      };
      const bodyText = body && body.trim() ? body.trim() : (header && header.trim() ? header.trim() : 'Clique abaixo');
      const resolvedButtonText = buttonText && buttonText.trim()
        ? buttonText.trim()
        : (ctaType === 'phone' ? 'Ligar' : 'Abrir');
      const normalizedUrl = ctaType === 'phone' ? '' : normalizeUrl(ctaValue);
      const normalizedPhone = ctaType === 'phone' ? normalizePhone(ctaValue) : '';
      const ctaUrl = ctaType === 'phone'
        ? (normalizedPhone ? `tel:${normalizedPhone}` : '')
        : normalizedUrl;
      if (!bodyText || !ctaUrl) {
        logger.error('CTA message missing body or value', { nodeId: node.id });
        throw new Error('Invalid CTA payload');
      }
      const basePayload = {
        messaging_product: 'whatsapp',
        to: contactPhone,
        recipient_type: 'individual',
        type: 'interactive',
        interactive: {
          type: 'cta_url',
          body: { text: truncate(bodyText, 1024) },
          action: {
            name: 'cta_url',
            parameters: {
              display_text: truncate(resolvedButtonText, 20),
              url: ctaUrl
            }
          }
        }
      };

      if (header && header.trim()) {
        basePayload.interactive.header = { type: 'text', text: truncate(header.trim(), 60) };
      }
      if (footer && footer.trim()) {
        basePayload.interactive.footer = { text: truncate(footer.trim(), 60) };
      }

      let sendResult = await queueMessage({
        channel: 'cloud',
        tenantId,
        accountId: account?.id,
        to: contactPhone,
        messageType: 'cta',
        awaitSend: true,
        metadata: {
          payload: { interactive: basePayload.interactive }
        }
      });

      if (!sendResult.success) {
        const trimmedPayload = {
          interactive: {
            type: basePayload.interactive.type,
            body: basePayload.interactive.body,
            action: basePayload.interactive.action
          }
        };
        sendResult = await queueMessage({
          channel: 'cloud',
          tenantId,
          accountId: account?.id,
          to: contactPhone,
          messageType: 'cta',
          awaitSend: true,
          metadata: {
            payload: trimmedPayload
          }
        });
      }

      if (!sendResult.success) {
        return false;
      }

      const messageId = sendResult.messageId || `flow_${Date.now()}`;
      const summary = bodyText;
      await pool.execute(
        `INSERT INTO whatsapp_cloud_messages 
         (conversation_id, message_id, direction, message_type, text_content, status, timestamp, created_at)
         VALUES (?, ?, 'outbound', 'interactive', ?, 'sent', NOW(), NOW())`,
        [conversationId, messageId, summary]
      );

      await pool.execute(
        `UPDATE whatsapp_cloud_conversations 
         SET last_message_text = ?, last_message_time = NOW(), last_message_from = 'business', updated_at = NOW()
         WHERE id = ?`,
        [summary, conversationId]
      );
      return true;
    } catch (error) {
      logger.error('Error sending CTA message', {
        error: error.message,
        stack: error.stack,
        response: error.response?.data || null
      });
      try {
        const fallbackBody = body && body.trim() ? body.trim() : (header && header.trim() ? header.trim() : 'Clique abaixo');
        const fallbackValue = ctaValue && ctaValue.trim() ? ctaValue.trim() : '';
        const fallbackText = fallbackValue ? `${fallbackBody}\n${fallbackValue}` : fallbackBody;
        await CloudFlowService.sendFlowTextMessage({
          tenantId,
          account,
          conversationId,
          contactPhone,
          message: fallbackText
        });
        return true;
      } catch (fallbackError) {
        logger.error('Error sending CTA fallback text', { error: fallbackError.message });
        return false;
      }
    }
  }

  static async sendFlowReaction({ tenantId, account, contactPhone, messageId, emoji }) {
    if (!messageId || !emoji) return false;
    try {
      const sendResult = await queueMessage({
        channel: 'cloud',
        tenantId,
        accountId: account?.id,
        to: contactPhone,
        messageType: 'reaction',
        awaitSend: true,
        metadata: {
          payload: {
            reaction: {
              message_id: messageId,
              emoji
            }
          }
        }
      });
      if (!sendResult.success) {
        return false;
      }
      return true;
    } catch (error) {
      logger.warn('Error sending reaction', { error: error.message });
      return false;
    }
  }

  static decryptApiKey(encryptedText) {
    try {
      const keyString = process.env.ENCRYPTION_KEY || 'default-key-change-in-production-32';
      const key = crypto.createHash('sha256').update(keyString).digest();
      const textParts = encryptedText.split(':');
      const iv = Buffer.from(textParts.shift(), 'hex');
      const encrypted = textParts.join(':');
      const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
      let decrypted = decipher.update(encrypted, 'hex', 'utf8');
      decrypted += decipher.final('utf8');
      return decrypted;
    } catch (error) {
      logger.error('Error decrypting API key', { error: error.message });
      return null;
    }
  }

  static async processCloudAIResponse({ tenantId, account, conversationId, contactPhone, message: _message, textBody, aiSettings }) {
    if (!textBody) return false;
    if (!aiSettings || !aiSettings.aiConfigId) {
      return false;
    }
    let connection;
    try {
      connection = await pool.getConnection();
      let config = null;
      const [configRows] = await connection.execute(
        `SELECT * FROM ai_configurations WHERE id = ? AND tenant_id = ? LIMIT 1`,
        [aiSettings.aiConfigId, tenantId]
      );
      if (configRows.length > 0) config = configRows[0];
      if (!config) {
        connection.release();
        return false;
      }
      const apiKey = CloudFlowService.decryptApiKey(config.api_key);
      if (!apiKey) {
        connection.release();
        return false;
      }
      if (config.business_hours_start && config.business_hours_end) {
        const now = new Date();
        const currentTime = now.toTimeString().slice(0, 5);
        const currentDay = now.toLocaleDateString('en-US', { weekday: 'long' }).toLowerCase();
        const businessDays = (config.business_days || '').toLowerCase().split(',').map(d => d.trim()).filter(Boolean);
        if (businessDays.length > 0 && !businessDays.includes(currentDay)) {
          connection.release();
          return false;
        }
        if (currentTime < String(config.business_hours_start).slice(0, 5) || currentTime > String(config.business_hours_end).slice(0, 5)) {
          connection.release();
          return false;
        }
      }
      const [history] = await connection.execute(
        `SELECT text_content, direction 
         FROM whatsapp_cloud_messages 
         WHERE conversation_id = ? 
         ORDER BY created_at DESC LIMIT 10`,
        [conversationId]
      );
      const messages = [];
      const systemPrompt = aiSettings?.prompt || aiSettings?.instructions || config.system_prompt || config.persona_description || 'You are a helpful assistant.';
      if (systemPrompt) {
        messages.push({ role: 'system', content: systemPrompt });
      }
      const reversedHistory = history.reverse();
      for (const msg of reversedHistory) {
        if (!msg?.text_content) continue;
        messages.push({
          role: msg.direction === 'inbound' ? 'user' : 'assistant',
          content: msg.text_content
        });
      }
      if (messages.length === 0 || messages[messages.length - 1].content !== textBody) {
        messages.push({ role: 'user', content: textBody });
      }
      const temperatureValue = Number.isFinite(parseFloat(aiSettings?.temperature))
        ? parseFloat(aiSettings.temperature)
        : parseFloat(config.temperature) || 0.7;
      const maxTokensValue = Number.isFinite(parseInt(aiSettings?.maxTokens, 10))
        ? parseInt(aiSettings.maxTokens, 10)
        : parseInt(config.max_tokens, 10) || 1000;
      const apiUrl = config.provider === 'deepseek'
        ? 'https://api.deepseek.com/v1/chat/completions'
        : 'https://api.openai.com/v1/chat/completions';
      const response = await axios.post(
        apiUrl,
        {
          model: config.model_name,
          messages,
          temperature: temperatureValue,
          max_tokens: maxTokensValue
        },
        {
          headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
          },
          timeout: 30000
        }
      );
      const aiResponse = response?.data?.choices?.[0]?.message?.content;
      if (!aiResponse) {
        connection.release();
        return false;
      }
      const delayMs = Math.max(0, Number(config.response_delay || 0) * 1000);
      if (delayMs) {
        await new Promise(resolve => setTimeout(resolve, delayMs));
      }
      await CloudFlowService.sendFlowTextMessage({
        tenantId,
        account,
        conversationId,
        contactPhone,
        message: aiResponse
      });
      connection.release();
      return true;
    } catch (error) {
      if (connection) connection.release();
      logger.error('Error processing cloud AI response', { error: error.message, tenantId });
      return false;
    }
  }
}

module.exports = { CloudFlowService };
