<?php
/**
 * Discord Bot Daemon - New Version
 */

// Cargar dependencias
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/discord/src/DiscordSender.php';
require_once __DIR__ . '/discord/src/HtmlToDiscordMarkdownConverter.php';
require_once __DIR__ . '/discord/src/Translate.php';
require_once __DIR__ . '/discord/src/CommandLocker.php';

// --- Cargar variables de entorno ---
if (file_exists(__DIR__ . '/.env')) {
    $lines = file(__DIR__ . '/.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    foreach ($lines as $line) {
        if (strpos(trim($line), '#') === 0) continue;
        if (strpos($line, '=') === false) continue;
        list($key, $value) = explode('=', $line, 2);
        $_ENV[trim($key)] = trim($value);
    }
}

// Importar clases necesarias de DiscordPHP
use Discord\Discord;
use Discord\WebSockets\Intents;
use Discord\WebSockets\Event;
use Discord\Parts\Channel\Message;
use Discord\Parts\Interactions\Interaction;
use Discord\Builders\MessageBuilder;
use Discord\Parts\Embed\Embed;
use Discord\Parts\Guild\Member;
use Discord\Builders\Components\ActionRow;
use Discord\Builders\Components\Button;

// --- Logger y Conexión a BD ---
$logInteraction = function($message, $data = []) {
    $pid = getmypid();
    $logMessage = date('[Y-m-d H:i:s] ') . "[PID: {$pid}] " . $message . "\n";
    if (!empty($data)) {
        $logMessage .= "Datos: " . json_encode($data, JSON_PRETTY_PRINT) . "\n";
    }
    error_log($logMessage, 3, __DIR__ . '/logs/discord_bot_new.log');
};

function getDBConnection(): PDO {
    $host = $_ENV['DB_HOST'] ?? '127.0.0.1';
    $dbName = $_ENV['DB_NAME'] ?? 'db';
    $user = $_ENV['DB_USER'] ?? 'root';
    $pass = $_ENV['DB_PASS'] ?? '';
    $port = $_ENV['DB_PORT'] ?? '3306';
    $charset = 'utf8mb4';
    $dsn = "mysql:host=$host;port=$port;dbname=$dbName;charset=$charset";
    $options = [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    return new PDO($dsn, $user, $pass, $options);
}

$logInteraction("Iniciando bot de Discord...");

try {
    $db = getDBConnection();
    $logInteraction("Conexión a la base de datos establecida.");
} catch (\Throwable $e) {
    $logInteraction("Error fatal al conectar a la base de datos", ['error' => $e->getMessage()]);
    die("Error de base de datos.");
}

if (empty($_ENV['DISCORD_BOT_TOKEN'])) {
    $logInteraction("Error Fatal: La variable de entorno DISCORD_BOT_TOKEN no está definida o está vacía.");
    die();
}

function saveRecipientIfNotExists(PDO $db, callable $logInteraction, string $type, string $discordId, ?string $name): void {
    $logInteraction("[Registro BD] Verificando destinatario...", ['type' => $type, 'id' => $discordId, 'name' => $name]);

    if (empty($discordId) || empty($name)) {
        $logInteraction("Se omitió guardar destinatario por ID o nombre vacío.", ['type' => $type, 'id' => $discordId, 'name' => $name]);
        return;
    }

    try {
        $stmt = $db->prepare("SELECT id FROM destinatarios_discord WHERE discord_id = ?");
        $stmt->execute([$discordId]);

        if ($stmt->rowCount() === 0) {
            $insertStmt = $db->prepare(
                "INSERT INTO destinatarios_discord (tipo, discord_id, nombre) VALUES (?, ?, ?)"
            );
            $insertStmt->execute([$type, $discordId, $name]);
            $logInteraction("Nuevo destinatario guardado", ['tipo' => $type, 'discord_id' => $discordId, 'nombre' => $name]);
        }
    } catch (Throwable $e) {
        $logInteraction("Error al guardar destinatario: " . $e->getMessage(), [
            'discord_id' => $discordId,
            'nombre' => $name,
            'trace' => $e->getTraceAsString()
        ]);
    }
}


try {
    $discord = new Discord([
        'token' => $_ENV['DISCORD_BOT_TOKEN'],
        'intents' => Intents::GUILDS | Intents::GUILD_MESSAGES | Intents::DIRECT_MESSAGES | Intents::GUILD_MEMBERS | Intents::GUILD_MESSAGE_REACTIONS | Intents::MESSAGE_CONTENT,
        'logger' => null
    ]);

    $discord->on('ready', function (Discord $discord) use ($logInteraction) {
        $logInteraction("==================================================");
        $logInteraction("Bot conectado y listo para escuchar!");
        $logInteraction("Usuario: {$discord->user->username}#{$discord->user->discriminator}");
        $logInteraction("==================================================");
    });

    $discord->on(Event::GUILD_MEMBER_ADD, function ($member, Discord $discord) use ($db, $logInteraction) {
        $logInteraction("[NUEVO MIEMBRO] Usuario {$member->user->username} ({$member->id}) se ha unido al servidor.");
        saveRecipientIfNotExists($db, $logInteraction, 'user', $member->id, $member->user->username);

        try {
            $stmt = $db->query("SELECT codigo as language_code, nombre as language_name, bandera as flag_emoji FROM idiomas WHERE activo = 1 ORDER BY nombre ASC");
            $activeLangs = $stmt->fetchAll(PDO::FETCH_ASSOC);

            if (empty($activeLangs)) {
                $logInteraction("ADVERTENCIA: [BIENVENIDA] No se envió mensaje de bienvenida porque no hay idiomas activos.");
                return;
            }

            $translator = new Translate();
            $baseTitle = "👋 ¡Hola, {$member->user->username}! Bienvenido/a a el Discord de Cereal Kiiller.";
            $baseDescription = "Por favor, selecciona tu idioma preferido:";
            
            $fullDescription = "";
            foreach($activeLangs as $lang) {
                $langCode = $lang['language_code'];
                $flag = $lang['flag_emoji'] ? $lang['flag_emoji'] . ' ' : '';
                
                $translatedDesc = ($langCode === 'es') 
                    ? $baseDescription 
                    : $translator->translateText($baseDescription, 'es', $langCode);
                
                if ($translatedDesc) {
                    $fullDescription .= $flag . $translatedDesc . "\n\n";
                }
            }

            $embed = new Embed($discord);
            $embed->setTitle($baseTitle);
            $embed->setDescription(trim($fullDescription));
            $embed->setColor("#5865F2");
            if ($member->user && $member->user->avatar) {
                $embed->setThumbnail($member->user->getAvatar());
            }

            $builder = MessageBuilder::new()->addEmbed($embed);

            $actionRows = [];
            $currentRow = ActionRow::new();
            $buttonCount = 0;

            foreach ($activeLangs as $lang) {
                $button = Button::new(Button::STYLE_SECONDARY, 'set_lang_' . $lang['language_code'])
                    ->setLabel($lang['language_name']);
                if (!empty($lang['flag_emoji'])) {
                    $button->setEmoji($lang['flag_emoji']);
                }
                $currentRow->addComponent($button);
                $buttonCount++;

                if ($buttonCount > 0 && $buttonCount % 5 === 0) {
                    $actionRows[] = $currentRow;
                    $currentRow = ActionRow::new();
                }
            }
            if ($buttonCount % 5 !== 0) {
                $actionRows[] = $currentRow;
            }
            foreach ($actionRows as $row) {
                $builder->addComponent($row);
            }

            $member->sendMessage($builder)->then(
                function () use ($logInteraction, $member) {
                    $logInteraction("[BIENVENIDA] Mensaje de selección de idioma enviado por DM a {$member->user->username}.");
                },
                function ($error) use ($logInteraction, $member) {
                    $logInteraction("ERROR: [BIENVENIDA] No se pudo enviar DM de bienvenida a {$member->user->username}.", ['error' => $error]);
                }
            );
            return;

        } catch (Throwable $e) {
            $logInteraction("ERROR: [BIENVENIDA] Error fatal al procesar nuevo miembro.", ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
        }
    });

    $discord->on(Event::INTERACTION_CREATE, function (Interaction $interaction, Discord $discord) use ($db, $logInteraction) {
        saveRecipientIfNotExists($db, $logInteraction, 'user', $interaction->user->id, $interaction->user->username);
        
        $channelName = 'Canal Desconocido';
        if ($interaction->channel) {
            $channelName = $interaction->channel->name;
            if ($interaction->channel->guild) {
                $channelName = $interaction->channel->guild->name . ' - ' . $channelName;
            } elseif ($interaction->channel->is_private) {
                $channelName = 'DM con ' . $interaction->user->username;
            }
        }
        saveRecipientIfNotExists($db, $logInteraction, 'channel', $interaction->channel_id, $channelName);

        $type = (int) ($interaction->type ?? 0);
        $componentType = (int) ($interaction->data->component_type ?? 0);
        if ($type !== 3 || $componentType !== 2) return;

        $customId = $interaction->data->custom_id;
        $userId = $interaction->user->id;
        $logInteraction("[INTERACCION] Usuario $userId hizo clic en el botón: $customId");

        try {
            if (strpos($customId, 'set_lang_') === 0) {
                $langCode = substr($customId, strlen('set_lang_'));
                $stmt = $db->prepare("UPDATE destinatarios_discord SET idioma_detectado = ? WHERE discord_id = ?");
                $stmt->execute([$langCode, $userId]);
                
                $langNameStmt = $db->prepare("SELECT nombre FROM idiomas WHERE codigo = ?");
                $langNameStmt->execute([$langCode]);
                $langName = $langNameStmt->fetchColumn() ?: strtoupper($langCode);

                $confirmEmbed = new Embed($discord);
                $confirmEmbed->setTitle("✅ Idioma Configurado");
                $confirmEmbed->setDescription("Tu idioma ha sido establecido a: **" . htmlspecialchars($langName) . "**");
                $confirmEmbed->setColor("#57F287");
                
                $builder = MessageBuilder::new()->addEmbed($confirmEmbed);
                
                $interaction->acknowledge()->then(function() use ($interaction, $builder, $logInteraction, $langCode, $userId) {
                    $interaction->message->edit($builder)->then(function() use ($logInteraction, $langCode, $userId) {
                        $logInteraction("[BIENVENIDA] El usuario $userId ha establecido su idioma a '$langCode' y el mensaje fue editado.");
                    }, function ($error) use ($logInteraction, $langCode, $userId) {
                        $logInteraction("ERROR: [BIENVENIDA] Error al editar el mensaje original para {$userId}.", ['lang' => $langCode, 'error' => $error]);
                    });
                });
                return;
            }

            if (strpos($customId, 'translate_auto:') === 0) {
                $originalMessageId = substr($customId, strlen('translate_auto:'));
                $stmt = $db->prepare("SELECT idioma_detectado FROM destinatarios_discord WHERE discord_id = ?");
                $stmt->execute([$userId]);
                $targetLang = $stmt->fetchColumn() ?: 'es';
                
                $interaction->channel->messages->fetch($originalMessageId)->then(
                    function ($originalMessage) use ($interaction, $discord, $db, $logInteraction, $userId, $targetLang) {
                        $originalContent = trim((string) ($originalMessage->content ?? ''));
                        if (empty($originalContent)) {
                            $interaction->respondWithMessage(MessageBuilder::new()->setContent("❌ No se encontró contenido para traducir."), true);
                            return;
                        }
                        
                        $translator = new Translate();
                        $sourceLang = $translator->detectLanguage($originalContent) ?? 'es';
                        
                        if ($sourceLang === $targetLang) {
                            $interaction->respondWithMessage(MessageBuilder::new()->setContent("⚠️ El mensaje ya está en tu idioma ({$targetLang})."), true);
                            return;
                        }
                        
                        $translatedText = $translator->translateText($originalContent, $sourceLang, $targetLang);

                        if (!empty($translatedText)) {
                            $stmt = $db->prepare("SELECT bandera, nombre FROM idiomas WHERE codigo = ? AND activo = 1");
                            $stmt->execute([$targetLang]);
                            $langInfo = $stmt->fetch(PDO::FETCH_ASSOC);
                            $flag = $langInfo['bandera'] ?? '🏳️';
                            $langName = $langInfo['nombre'] ?? strtoupper($targetLang);
                            
                            $embed = new Embed($discord);
                            $embed->setTitle("{$flag} Traducción a {$langName}");
                            $embed->setDescription($translatedText);
                            $embed->setColor("#5865F2");
                            $embed->setFooter("Traducido de {$sourceLang} • Solo tú puedes ver esto");
                            
                            if (count($originalMessage->attachments) > 0) {
                                $firstAttachment = $originalMessage->attachments->first();
                                if ($firstAttachment && isset($firstAttachment->url) && strpos($firstAttachment->content_type ?? '', 'image/') === 0) {
                                    $embed->setImage($firstAttachment->url);
                                }
                            }
                            
                            $builder = MessageBuilder::new()
                                ->setContent("Aquí tienes tu traducción (solo visible para ti):")
                                ->addEmbed($embed);
                            $interaction->respondWithMessage($builder, true);
                            $logInteraction("[TRANSLATION] Usuario {$userId} tradujo mensaje de {$sourceLang} a {$targetLang}");
                        } else {
                            $interaction->respondWithMessage(MessageBuilder::new()->setContent("⚠️ No se pudo traducir el mensaje."), true);
                        }
                    },
                    function ($error) use ($interaction, $logInteraction) {
                        $logInteraction("ERROR: [TRANSLATION] Error al obtener mensaje original", ['error' => $error->getMessage()]);
                        $interaction->respondWithMessage(MessageBuilder::new()->setContent("❌ No se pudo obtener el mensaje original para traducir."), true);
                    }
                );
                return;
            }

            if (strpos($customId, 'translate_template:') === 0) {
                // Not implemented in this merge for now to keep it simple
            }

            if ($customId === 'platicar_bot' || $customId === 'usar_ia') {
                $newMode = ($customId === 'platicar_bot') ? 'bot' : 'ia';
                $stmt = $db->prepare("UPDATE destinatarios_discord SET chat_mode = ? WHERE discord_id = ?");
                $stmt->execute([$newMode, $userId]);
                $responseText = $newMode === 'bot' 
                    ? "🤖 Modo cambiado a 'Platicar con bot'. Ahora puedes usar los comandos normales como `/comandos`."
                    : "🧠 Modo cambiado a 'Usar IA'. Todo lo que escribas será procesado por la IA.\n\nEscribe `/agente` para volver a este menú.";
                $interaction->respondWithMessage(MessageBuilder::new()->setContent($responseText), true);
                $logInteraction("[MODO AGENTE] Usuario $userId cambió al modo: $newMode");
            }
        } catch (Throwable $e) {
            $logInteraction("ERROR: [INTERACCION] Error al procesar un botón.", ['customId' => $customId, 'error' => $e->getMessage()]);
            $interaction->respondWithMessage(MessageBuilder::new()->setContent("Hubo un error al procesar esta acción."), true);
        }
    });

    $discord->on(Event::MESSAGE_CREATE, function (Message $message, Discord $discord) use ($db, $logInteraction) {
        if ($message->author->bot) return;

        saveRecipientIfNotExists($db, $logInteraction, 'user', $message->author->id, $message->author->username);
        $channelName = $message->channel->is_private ? 'DM con ' . $message->author->username : $message->channel->name;
        if (!$message->channel->is_private && $message->channel->guild) {
             $channelName = $message->channel->guild->name . ' - ' . $channelName;
        }
        saveRecipientIfNotExists($db, $logInteraction, 'channel', $message->channel->id, $channelName);
        $logInteraction("[Mensaje Recibido] En canal '{$channelName}' de @{$message->author->username}: {$message->content}");
        
        $isPrivateChat = $message->channel->is_private;
        $userId = $message->author->id;
        $content = $message->content;

        try {
            if ($isPrivateChat) {
                $stmt = $db->prepare("SELECT chat_mode FROM destinatarios_discord WHERE discord_id = ?");
                $stmt->execute([$userId]);
                $userChatMode = $stmt->fetchColumn();

                if ($userChatMode === false) {
                    $updateStmt = $db->prepare("UPDATE destinatarios_discord SET chat_mode = 'agent' WHERE discord_id = ?");
                    $updateStmt->execute([$userId]);
                    $userChatMode = 'agent';
                }

                if (trim($content) === '/agente') {
                    $stmt = $db->prepare("UPDATE destinatarios_discord SET chat_mode = 'agent' WHERE discord_id = ?");
                    $stmt->execute([$userId]);
                    $userChatMode = 'agent';
                }

                switch ($userChatMode) {
                    case 'agent':
                        $builder = MessageBuilder::new()->setContent("👋 Hola! ¿Cómo quieres interactuar?");
                        $actionRow = ActionRow::new()
                            ->addComponent(Button::new(Button::STYLE_PRIMARY, 'platicar_bot')->setLabel('🤖 Platicar con bot'))
                            ->addComponent(Button::new(Button::STYLE_SUCCESS, 'usar_ia')->setLabel('🧠 Usar IA'));
                        $builder->addComponent($actionRow);
                        $message->channel->sendMessage($builder);
                        return;

                    case 'ia':
                        $n8nWebhookUrl = $_ENV['N8N_IA_WEBHOOK_URL_DISCORD'] ?? null;
                        if ($n8nWebhookUrl) {
                            $postData = ['chat_id' => $message->channel_id, 'user_id' => $userId, 'message' => $content, 'name' => $message->author->username];
                            $ch = curl_init($n8nWebhookUrl);
                            curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($postData), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_TIMEOUT => 10 ]);
                            curl_exec($ch);
                            curl_close($ch);
                        }
                        return;

                    case 'bot':
                        break;
                }
            }

            if (strpos($content, '#') === 0 || strpos($content, '/') === 0) {
                handleDiscordCommand($message, $db, $logInteraction);
            } else if (strtolower($content) === '!ping') {
                $message->reply('pong!');
            } else {
                handleDiscordTranslation($message, $db, $logInteraction);
            }

        } catch (Throwable $e) {
            $logInteraction("ERROR FATAL CAPTURADO", ['error' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    });

    $discord->run();

} catch (Throwable $e) {
    $logInteraction("CRITICAL: ERROR FATAL AL INICIAR", ['error' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
    die();
}

function handleDiscordCommand(Message $message, PDO $db, $logInteraction)
{
    $text = trim($message->content);
    
    if (strpos($text, '#') === 0) {
        $command = ltrim($text, '#'); // Command is "Saludos"
        $logInteraction("[Comando] Usuario @{$message->author->username} solicitó: #{$command}");
        try {
            // Step 1: Look up command in comandos_discord to get plantilla_id
            $stmt = $db->prepare("SELECT plantilla_id FROM comandos_discord WHERE comando = ?");
            $stmt->execute([$command]);
            $command_data = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($command_data && $command_data['plantilla_id']) {
                $plantilla_id = $command_data['plantilla_id'];
                // Step 2: Get template content from plantillas_discord
                $stmt = $db->prepare("SELECT contenido FROM plantillas_discord WHERE id = ?");
                $stmt->execute([$plantilla_id]);
                $template = $stmt->fetch(PDO::FETCH_ASSOC);

                if ($template) {
                    $sender = new DiscordSender($_ENV['DISCORD_BOT_TOKEN']);
                    $sender->sendMessage($message->channel_id, $template['contenido']);
                } else {
                    $message->reply("El comando `#{$command}` fue encontrado, pero la plantilla asociada (ID: {$plantilla_id}) no existe.");
                }
            } else {
                $message->reply("El comando `#{$command}` no fue encontrado.");
            }
        } catch (Throwable $e) {
            $logInteraction("ERROR: [Comando] Procesando #{$command}", ['error' => $e->getMessage()]);
            $message->reply("Ocurrió un error inesperado al procesar tu comando.");
        }
    } elseif (strpos($text, '/comandos') === 0) {
        $stmt = $db->query("SELECT comando, nombre FROM plantillas_discord WHERE comando IS NOT NULL AND comando != '' ORDER BY nombre ASC");
        $commands = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if (empty($commands)) {
            $message->reply("ℹ️ No hay comandos personalizados disponibles.");
        } else {
            $response = "**LISTA DE COMANDOS DISPONIBLES (Modo Debug)**\n\n";
            foreach ($commands as $cmd) {
                $raw_command = $cmd['comando']; // The raw value from DB
                $display_command = trim($raw_command);
                if (strpos($display_command, '#') !== 0 && strpos($display_command, '/') !== 0) {
                    $display_command = '#' . $display_command;
                }
                $response .= "`" . $display_command . "` (DB: `" . $raw_command . "`) - " . trim($cmd['nombre']) . "\n";
            }
            $message->channel->sendMessage($response);
        }
    }
}

function handleDiscordTranslation(Message $message, PDO $db, $logInteraction)
{
    try {
        $langStmt = $db->query("SELECT codigo FROM idiomas WHERE activo = 1");
        $activeLangsCount = $langStmt->rowCount();
        
        if ($activeLangsCount < 2) return;

        $button = Button::new(Button::STYLE_PRIMARY, 'translate_auto:' . $message->id)
            ->setLabel('Traducir / Translate')
            ->setEmoji('🌐');
        
        $actionRow = ActionRow::new()->addComponent($button);
        
        $builder = MessageBuilder::new()->addComponent($actionRow);
        
        $message->reply($builder);

    } catch (Throwable $e) {
        $logInteraction("ERROR: [TRANSLATION_BUTTONS]", ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
    }
}