#!/usr/bin/env node

const fs = require('fs-extra');
const path = require('path');

console.log('🔧 Pamsika WhatsApp Bot - Quick Fix for xml-not-well-formed Error');
console.log('='.repeat(70));

async function applyQuickFix() {
  try {
    const botPath = path.join(__dirname, 'bot.js');

    if (!await fs.pathExists(botPath)) {
      console.error('❌ bot.js not found. Please run this script from the project root directory.');
      process.exit(1);
    }

    console.log('📖 Reading current bot.js...');
    let botContent = await fs.readFile(botPath, 'utf8');

    // Backup the original file
    const backupPath = path.join(__dirname, 'bot.js.backup');
    await fs.writeFile(backupPath, botContent);
    console.log('💾 Created backup at bot.js.backup');

    // Apply fixes
    console.log('🔄 Applying xml-not-well-formed error handling fixes...');

    // Fix 1: Add better error handling in message processing
    const messageProcessingFix = `
              // Check if socket is still connected before processing
              if (sock && sock.ws && sock.ws.readyState === sock.ws.OPEN) {
                console.log(\`✅ Socket ready, processing message\`);

                try {
                  await handleIncomingMessage(sock, sender, messageContent, m);
                  console.log(\`✅ Message processed successfully\`);
                } catch (processingError) {
                  console.error(\`❌ Error processing message:\`, processingError);

                  // Handle xml-not-well-formed errors specifically
                  if (processingError.message &&
                      (processingError.message.includes("xml-not-well-formed") ||
                       processingError.message.includes("Stream Errored"))) {
                    console.log(\`⚠️ Connection error detected, forcing reconnection\`);

                    // Don't try to send response - connection is broken
                    if (sock && sock.end) {
                      try { sock.end(); } catch (e) { console.log('Socket already closed'); }
                    }
                    sock = null;

                    // Restart bot after short delay
                    setTimeout(() => {
                      console.log(\`🔄 Restarting bot after connection error\`);
                      startBot();
                    }, 3000);
                    return;
                  }

                  // For other errors, try to send user-friendly message
                  try {
                    if (sock && sock.ws && sock.ws.readyState === sock.ws.OPEN) {
                      await sock.sendMessage(sender, {
                        text: "⚠️ I encountered an issue. Please try again or type *menu* for the main menu.",
                      });
                    }
                  } catch (sendError) {
                    console.error("Failed to send error response:", sendError);
                  }
                }`;

    // Find and replace the message processing section
    const messageProcessingPattern = /if \(sock && sock\.ws && sock\.ws\.readyState === sock\.ws\.OPEN\) \{\s*console\.log\(\`✅ Socket ready, processing message\`\);\s*await handleIncomingMessage\(sock, sender, messageContent, m\);\s*console\.log\(\`✅ Message processed successfully\`\);/s;

    if (messageProcessingPattern.test(botContent)) {
      botContent = botContent.replace(messageProcessingPattern, messageProcessingFix.trim());
      console.log('✅ Applied message processing error handling fix');
    } else {
      console.log('⚠️  Could not find exact message processing pattern, applying alternative fix...');

      // Alternative fix - add error handling around handleIncomingMessage calls
      botContent = botContent.replace(
        /await handleIncomingMessage\(sock, sender, messageContent, m\);/g,
        `try {
                  await handleIncomingMessage(sock, sender, messageContent, m);
                } catch (processingError) {
                  console.error("❌ Message processing error:", processingError);
                  if (processingError.message &&
                      (processingError.message.includes("xml-not-well-formed") ||
                       processingError.message.includes("Stream Errored"))) {
                    console.log("🔄 Connection error - restarting bot");
                    if (sock) { try { sock.end(); } catch(e) {} }
                    sock = null;
                    setTimeout(() => startBot(), 3000);
                    return;
                  }
                }`
      );
    }

    // Fix 2: Add better connection error handling
    const connectionErrorFix = `
      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);

        if (shouldReconnect) {
          reconnectAttempts++;
          console.log(
            \`Attempting to reconnect (attempt \${reconnectAttempts})...\`,
          );

          sock = null;

          // Wait longer for stream/XML errors
          const delay = isXmlError ?
            Math.min(reconnectInterval * 2, 30000) : // 30s max for XML errors
            Math.min(reconnectInterval * Math.pow(2, Math.min(reconnectAttempts - 1, 4)), 60000);

          setTimeout(() => {
            startBot();
            reconnectInterval = Math.min(reconnectInterval * 1.5, 60000);
          }, delay);
        } else {
          console.log("Connection closed due to logout. Please restart manually.");
          await cleanupSession();
          process.exit(1);
        }
      }`;

    // Replace connection close handling
    const connectionClosePattern = /if \(connection === "close"\) \{[\s\S]*?process\.exit\(1\);\s*\}/;
    if (connectionClosePattern.test(botContent)) {
      botContent = botContent.replace(connectionClosePattern, connectionErrorFix.trim());
      console.log('✅ Applied connection error handling fix');
    }

    // Fix 3: Add stream error handler
    const streamErrorHandler = `
    // Add specific handler for stream errors
    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) { console.log('Socket cleanup error:', e.message); }
      }
      sock = null;

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

    // Add stream error handler before the existing error handler
    const errorHandlerPattern = /sock\.ev\.on\("error"/;
    if (errorHandlerPattern.test(botContent)) {
      botContent = botContent.replace(errorHandlerPattern, streamErrorHandler + '\n\n    sock.ev.on("error"');
      console.log('✅ Added stream error handler');
    }

    // Fix 4: Improve sendTextMessage error handling
    const sendMessageFix = `
async function sendTextMessage(phone, message, retries = 3) {
  if (!sock) {
    throw new Error("WhatsApp connection is not established");
  }

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

  for (let i = 0; i < retries; i++) {
    try {
      // Check connection health before sending
      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 - let the main handler deal with it
      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)));
    }
  }
}`;

    // Replace sendTextMessage function
    const sendMessagePattern = /async function sendTextMessage\(phone, message, retries = 3\) \{[\s\S]*?\n\}/;
    if (sendMessagePattern.test(botContent)) {
      botContent = botContent.replace(sendMessagePattern, sendMessageFix.trim());
      console.log('✅ Improved sendTextMessage error handling');
    }

    // Write the fixed content back
    await fs.writeFile(botPath, botContent);
    console.log('💾 Applied all fixes to bot.js');

    // Create a restart script
    const restartScript = `#!/bin/bash
echo "🔄 Restarting Pamsika WhatsApp Bot..."

# Kill any existing node processes running the bot
pkill -f "node.*bot.js" || true
pkill -f "node.*server.js" || true

# Wait a moment
sleep 2

# Start the bot
echo "🚀 Starting bot..."
node bot.js

echo "✅ Bot restart complete"
`;

    await fs.writeFile(path.join(__dirname, 'restart-bot.sh'), restartScript);
    await fs.chmod(path.join(__dirname, 'restart-bot.sh'), '755');
    console.log('✅ Created restart-bot.sh script');

    console.log('\n' + '='.repeat(70));
    console.log('🎉 Quick Fix Applied Successfully!');
    console.log('='.repeat(70));
    console.log('\n📋 What was fixed:');
    console.log('  ✅ Added xml-not-well-formed error detection and handling');
    console.log('  ✅ Improved connection error recovery');
    console.log('  ✅ Added stream error handler');
    console.log('  ✅ Enhanced message sending error handling');
    console.log('  ✅ Created automatic restart mechanisms');

    console.log('\n🚀 Next Steps:');
    console.log('  1. Restart your bot: npm start (or node bot.js)');
    console.log('  2. Test quantity selection again');
    console.log('  3. If issues persist, use: ./restart-bot.sh');

    console.log('\n💡 The bot will now:');
    console.log('  • Automatically detect xml-not-well-formed errors');
    console.log('  • Restart connection when stream errors occur');
    console.log('  • Provide better error messages to users');
    console.log('  • Recover gracefully from connection issues');

    console.log('\n📝 Files modified:');
    console.log('  • bot.js (fixes applied)');
    console.log('  • bot.js.backup (original backup)');
    console.log('  • restart-bot.sh (restart script)');

    console.log('\n⚠️  If you need to revert changes:');
    console.log('    cp bot.js.backup bot.js');

  } catch (error) {
    console.error('❌ Error applying fixes:', error);
    console.log('\n🔄 You can try restoring from backup:');
    console.log('    cp bot.js.backup bot.js');
    process.exit(1);
  }
}

// Run the fix
applyQuickFix().catch(console.error);
