const { default: makeWASocket, DisconnectReason, useMultiFileAuthState } = require('@whiskeysockets/baileys');
const qrcode = require('qrcode-terminal');
const fs = require('fs-extra');
const path = require('path');
const { handleIncomingMessage } = require('./features/menu-quantity-fix');
const { initializeSafeSender, updateSafeSenderSocket } = require('./utils/safeMessageSender');

let sock;
let reconnectAttempts = 0;
let isConnecting = false;
let safeSender = null;

const INITIAL_RECONNECT_INTERVAL = 5000;
let reconnectInterval = INITIAL_RECONNECT_INTERVAL;
const MAX_RECONNECT_ATTEMPTS = 15;

// Message queue for when connection is unstable
const messageQueue = [];
let isProcessingQueue = false;

async function processMessageQueue() {
  if (isProcessingQueue || messageQueue.length === 0) return;

  isProcessingQueue = true;
  console.log(`📨 Processing ${messageQueue.length} queued messages`);

  while (messageQueue.length > 0) {
    const messageTask = messageQueue.shift();

    try {
      if (sock && sock.user && sock.ws && sock.ws.readyState === sock.ws.OPEN) {
        await handleIncomingMessage(sock, messageTask.sender, messageTask.messageContent, messageTask.messageObj);
        console.log(`✅ Processed queued message from ${messageTask.sender}`);

        // Small delay between processing queued messages
        await new Promise(resolve => setTimeout(resolve, 1000));
      } else {
        // Re-queue if connection is still not ready
        messageQueue.unshift(messageTask);
        break;
      }
    } catch (error) {
      console.error(`❌ Error processing queued message:`, error);

      // Don't re-queue if it's a connection error
      if (!error.message || !error.message.includes('xml-not-well-formed')) {
        // Could retry later, but for now just skip
      }
    }
  }

  isProcessingQueue = false;
  console.log(`✅ Message queue processing complete`);
}

async function cleanupSession() {
  try {
    const sessionDir = path.join(__dirname, 'sessions', 'auth_info_baileys');
    if (await fs.pathExists(sessionDir)) {
      await fs.remove(sessionDir);
      console.log('🧹 Cleaned up session files');
    }
  } catch (error) {
    console.error('❌ Error cleaning up session:', error);
  }
}

async function startBot() {
  if (isConnecting) {
    console.log('⏳ Already attempting to connect...');
    return;
  }

  isConnecting = true;

  try {
    console.log('🚀 Starting WhatsApp bot with FIXED handlers...');

    const sessionDir = path.join(__dirname, 'sessions');
    await fs.ensureDir(sessionDir);

    const { state, saveCreds } = await useMultiFileAuthState(path.join(sessionDir, 'auth_info_baileys'));

    sock = makeWASocket({
      auth: state,
      printQRInTerminal: false,
      browser: ['Pamsika Bot', 'Safari', '10.0.0'],

      // Enhanced stability options
      connectTimeoutMs: 60000,
      defaultQueryTimeoutMs: 60000,
      keepAliveIntervalMs: 25000,
      retryRequestDelayMs: 4000,

      // Message handling
      getMessage: async (key) => {
        return { conversation: 'Message not available' };
      },

      // User agent
      userAgent: {
        platform: 'WEB',
        appVersion: {
          primary: 2,
          secondary: 3000,
          tertiary: 1023223821,
        },
        mcc: '000',
        mnc: '000',
        osVersion: '0.1',
        device: 'Desktop',
        osBuildNumber: '0.1',
        releaseChannel: 'RELEASE',
        localeLanguageIso6391: 'en',
        localeCountryIso31661Alpha2: 'US',
      },

      // WebSocket options
      ws: {
        headers: {
          'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        },
      },

      // Transaction options - more conservative
      transactionOpts: {
        maxCommitRetries: 2,
        delayBetweenTriesMs: 8000,
      },
    });

    // Initialize safe message sender
    safeSender = initializeSafeSender(sock);
    console.log('✅ Safe message sender initialized');

    // Connection event handling
    sock.ev.on('connection.update', async (update) => {
      const { connection, lastDisconnect, qr } = update;

      if (qr) {
        console.log('📱 QR Code generated. Please scan with WhatsApp:');
        qrcode.generate(qr, { small: true });
      }

      if (connection === 'close') {
        const statusCode = lastDisconnect?.error?.output?.statusCode;
        const errorMessage = lastDisconnect?.error?.message || 'Unknown error';

        console.log(`❌ Connection closed - Status: ${statusCode}, Error: ${errorMessage}`);

        // Handle xml-not-well-formed and stream errors specifically
        const isXmlError = errorMessage.includes('xml-not-well-formed') ||
                          errorMessage.includes('Stream Errored');

        const shouldReconnect = !(
          statusCode === DisconnectReason.loggedOut ||
          statusCode === 401 ||
          statusCode === 403
        );

        console.log('Should reconnect:', shouldReconnect);
        isConnecting = false;

        if (shouldReconnect && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
          reconnectAttempts++;
          console.log(`🔄 Attempting to reconnect (attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})...`);

          sock = null;
          safeSender = null;

          // Wait longer for XML/stream errors
          const delay = isXmlError ?
            Math.min(reconnectInterval * 3, 60000) : // Up to 1 minute for XML errors
            Math.min(reconnectInterval * Math.pow(1.5, Math.min(reconnectAttempts - 1, 4)), 30000);

          setTimeout(() => {
            startBot();
            reconnectInterval = Math.min(reconnectInterval * 1.2, 30000);
          }, delay);
        } else {
          console.log('❌ Connection closed permanently or max attempts reached.');

          if (statusCode === DisconnectReason.loggedOut) {
            await cleanupSession();
          }

          if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
            console.log('📞 Please restart the bot manually.');
            process.exit(1);
          }
        }

      } else if (connection === 'open') {
        console.log('✅ WhatsApp connection established!');
        console.log('📡 Bot ready to receive messages');

        isConnecting = false;
        reconnectAttempts = 0;
        reconnectInterval = INITIAL_RECONNECT_INTERVAL;

        // Update safe sender with new socket
        updateSafeSenderSocket(sock);

        // Process any queued messages
        if (messageQueue.length > 0) {
          console.log(`📨 Processing ${messageQueue.length} queued messages`);
          setTimeout(processMessageQueue, 2000);
        }

      } else if (connection === 'connecting') {
        console.log('⏳ Connecting to WhatsApp...');

      } else if (connection === 'refused' || connection === 'timeout') {
        console.log(`⚠️ Connection ${connection}. Will retry...`);
        isConnecting = false;

        setTimeout(() => {
          if (!sock || !sock.user) {
            startBot();
          }
        }, INITIAL_RECONNECT_INTERVAL);
      }
    });

    // Credentials update
    sock.ev.on('creds.update', async () => {
      try {
        await saveCreds();
        console.log('💾 Credentials updated successfully');
      } catch (error) {
        console.error('❌ Error saving credentials:', error);
      }
    });

    // Enhanced message handling with connection safety
    sock.ev.on('messages.upsert', async (messageUpdate) => {
      try {
        for (const message of messageUpdate.messages) {
          if (!message.key.fromMe && message.message) {
            const sender = message.key.remoteJid;
            let messageContent = '';

            // Extract message content
            if (message.message.conversation) {
              messageContent = message.message.conversation;
            } else if (message.message.extendedTextMessage) {
              messageContent = message.message.extendedTextMessage.text;
            } else if (message.message.imageMessage && message.message.imageMessage.caption) {
              messageContent = message.message.imageMessage.caption;
            }

            if (messageContent && messageContent.trim()) {
              console.log(`📩 New message from ${sender}: "${messageContent}"`);
              console.log(`📡 Connection state: ${connection}`);

              // Check connection health before processing
              if (sock && sock.user && sock.ws && sock.ws.readyState === sock.ws.OPEN) {
                try {
                  console.log('✅ Connection healthy, processing message immediately');
                  await handleIncomingMessage(sock, sender, messageContent.trim(), 'text');
                  console.log('✅ Message processed successfully');

                } catch (processingError) {
                  console.error('❌ Error processing message:', processingError);

                  // Handle critical connection errors
                  if (processingError.message &&
                      (processingError.message.includes('xml-not-well-formed') ||
                       processingError.message.includes('Stream Errored') ||
                       processingError.message.includes('Connection Closed'))) {

                    console.log('🚨 Critical connection error detected - forcing reconnection');

                    // Don't try to send error messages
                    if (sock && sock.end) {
                      try {
                        sock.end();
                      } catch (e) {
                        console.log('Socket cleanup error:', e.message);
                      }
                    }
                    sock = null;
                    safeSender = null;

                    setTimeout(() => {
                      console.log('🔄 Restarting after critical error');
                      startBot();
                    }, 5000);
                    return;
                  }

                  // For non-critical errors, queue the message
                  console.log('📥 Queuing message due to processing error');
                  messageQueue.push({
                    sender,
                    messageContent: messageContent.trim(),
                    messageObj: message,
                    timestamp: new Date().toISOString(),
                  });
                }
              } else {
                console.log('⚠️ Connection not ready, queuing message');
                messageQueue.push({
                  sender,
                  messageContent: messageContent.trim(),
                  messageObj: message,
                  timestamp: new Date().toISOString(),
                });
                console.log(`📥 Message queued (queue size: ${messageQueue.length})`);
              }
            }
          }
        }
      } catch (error) {
        console.error('❌ Error in messages.upsert handler:', error);

        // If this is a connection error, restart
        if (error.message && error.message.includes('xml-not-well-formed')) {
          console.log('🔄 Message handler error - restarting bot');
          if (sock) {
            try { sock.end(); } catch (e) {}
          }
          sock = null;
          safeSender = null;
          setTimeout(() => startBot(), 5000);
        }
      }
    });

    // Stream error handler
    sock.ev.on('stream:error', (error) => {
      console.error('❌ Stream error occurred:', error);
      console.log('🔄 Stream error - forcing reconnection');

      if (sock) {
        try { sock.end(); } catch (e) {}
      }
      sock = null;
      safeSender = null;
      isConnecting = false;

      setTimeout(() => {
        console.log('🔄 Restarting after stream error');
        startBot();
      }, 8000);
    });

    // General error handler
    sock.ev.on('error', async (error) => {
      console.error('❌ Socket error:', error);

      // Don't restart for every error, only critical ones
      if (error.message && (
          error.message.includes('xml-not-well-formed') ||
          error.message.includes('Stream Errored') ||
          error.message.includes('Connection reset'))) {
        console.log('🔄 Critical socket error - restarting');
        isConnecting = false;
        setTimeout(() => startBot(), 5000);
      }
    });

  } catch (error) {
    console.error('❌ Error starting bot:', error);
    isConnecting = false;

    // Retry with exponential backoff
    const delay = Math.min(reconnectInterval * Math.pow(2, Math.min(reconnectAttempts, 4)), 60000);
    setTimeout(() => {
      if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
        reconnectAttempts++;
        startBot();
      } else {
        console.log('❌ Max reconnection attempts reached. Please restart manually.');
        process.exit(1);
      }
    }, delay);
  }
}

// Enhanced message sending with connection health checks
async function sendTextMessage(phone, message, retries = 3) {
  if (!sock) {
    throw new Error('WhatsApp connection is not established');
  }

  // Use safe sender if available
  if (safeSender && safeSender.isConnectionHealthy()) {
    try {
      await safeSender.sendText(phone, message);
      return;
    } catch (error) {
      console.error('SafeSender failed, falling back to direct send:', error);
    }
  }

  // Fallback to direct sending
  const formattedPhone = phone.includes('@s.whatsapp.net')
    ? phone
    : `${phone.replace(/[^0-9]/g, '')}@s.whatsapp.net`;

  for (let i = 0; i < retries; i++) {
    try {
      // Extra connection check
      if (!sock.ws || sock.ws.readyState !== sock.ws.OPEN) {
        throw new Error('WebSocket connection not open');
      }

      await sock.sendMessage(formattedPhone, { text: message });
      return;
    } catch (error) {
      console.error(`Send attempt ${i + 1} failed:`, error.message);

      // Don't retry on connection errors
      if (error.message.includes('xml-not-well-formed') ||
          error.message.includes('Stream Errored') ||
          error.message.includes('Connection Closed')) {
        throw error;
      }

      if (i === retries - 1) throw error;
      await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
}

// Enhanced media message sending
async function sendMediaMessage(phone, mediaUrl, caption = '', retries = 3) {
  if (!sock) {
    throw new Error('WhatsApp connection is not established');
  }

  // Use safe sender if available
  if (safeSender && safeSender.isConnectionHealthy()) {
    try {
      const fileExtension = path.extname(mediaUrl).toLowerCase();
      let messageData = {};

      if (['.jpg', '.jpeg', '.png'].includes(fileExtension)) {
        messageData = { image: { url: mediaUrl }, caption };
      } else if (['.mp4', '.mov'].includes(fileExtension)) {
        messageData = { video: { url: mediaUrl }, caption };
      } else {
        messageData = { document: { url: mediaUrl }, mimetype: 'application/octet-stream', caption };
      }

      await safeSender.sendMedia(phone, messageData);
      return;
    } catch (error) {
      console.error('SafeSender media failed, falling back to direct send:', error);
    }
  }

  // Fallback logic similar to sendTextMessage...
  const formattedPhone = phone.includes('@s.whatsapp.net')
    ? phone
    : `${phone.replace(/[^0-9]/g, '')}@s.whatsapp.net`;

  const fileExtension = path.extname(mediaUrl).toLowerCase();
  let messageData = {};

  if (['.jpg', '.jpeg', '.png'].includes(fileExtension)) {
    messageData = { image: { url: mediaUrl }, caption };
  } else if (['.mp4', '.mov'].includes(fileExtension)) {
    messageData = { video: { url: mediaUrl }, caption };
  } else {
    messageData = { document: { url: mediaUrl }, mimetype: 'application/octet-stream', caption };
  }

  for (let i = 0; i < retries; i++) {
    try {
      if (!sock.ws || sock.ws.readyState !== sock.ws.OPEN) {
        throw new Error('WebSocket connection not open');
      }

      await sock.sendMessage(formattedPhone, messageData);
      return;
    } catch (error) {
      console.error(`Media send attempt ${i + 1} failed:`, error.message);

      if (error.message.includes('xml-not-well-formed') ||
          error.message.includes('Stream Errored')) {
        throw error;
      }

      if (i === retries - 1) throw error;
      await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
}

// Graceful shutdown
process.on('SIGINT', async () => {
  console.log('📤 Received SIGINT, shutting down gracefully...');

  if (safeSender) {
    await safeSender.shutdown();
  }

  if (sock) {
    try {
      sock.end();
    } catch (error) {
      console.error('Error ending socket:', error);
    }
  }

  process.exit(0);
});

process.on('SIGTERM', async () => {
  console.log('📤 Received SIGTERM, shutting down gracefully...');

  if (safeSender) {
    await safeSender.shutdown();
  }

  if (sock) {
    try {
      sock.end();
    } catch (error) {
      console.error('Error ending socket:', error);
    }
  }

  process.exit(0);
});

// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
  console.error('❌ Uncaught Exception:', error);

  // Try to reconnect if it's a connection-related error
  if (error.message && (
      error.message.includes('xml-not-well-formed') ||
      error.message.includes('Stream Errored') ||
      error.message.includes('Connection'))) {
    console.log('🔄 Uncaught connection exception - attempting recovery');
    if (sock) {
      try { sock.end(); } catch (e) {}
    }
    sock = null;
    safeSender = null;
    isConnecting = false;
    setTimeout(() => startBot(), 3000);
  }
});

console.log('🚀 Pamsika WhatsApp Bot - FIXED VERSION');
console.log('✅ Enhanced with connection stability and safe message handling');
console.log('🔧 Includes xml-not-well-formed error prevention');
console.log('📝 Uses improved quantity selection handler');
console.log('');

module.exports = {
  startBot,
  sendTextMessage,
  sendMediaMessage
};
