<?php

class Translate
{
    private $apiUrl;

    public function __construct()
    {
        $this->apiUrl = rtrim($_ENV['LIBRETRANSLATE_URL'], '/');
    }

    public function detectLanguage($text)
    {
        if (empty(trim($text))) {
            return null;
        }

        $response = $this->request('/detect', ['q' => $text]);

        if (isset($response[0]['language'])) {
            return $response[0]['language'];
        }

        return null;
    }

    public function translateText($text, $source, $target)
    {
        if (empty(trim($text))) {
            return null;
        }

        $response = $this->request('/translate', [
            'q' => $text,
            'source' => $source,
            'target' => $target,
            'format' => 'text'
        ]);

        return $response['translatedText'] ?? null;
    }

    public function translateHtml($html, $source, $target)
    {
        if (empty(trim($html))) {
            return null;
        }

        $maxLength = 4000; // Límite de caracteres para LibreTranslate
        $translatedHtml = '';

        custom_log("translateHtml: Original HTML length: " . mb_strlen($html));
        // Dividir el HTML en bloques para evitar exceder el límite de LibreTranslate
        $chunks = $this->splitHtmlIntoChunks($html, $maxLength);
        custom_log("translateHtml: Number of chunks: " . count($chunks));

        foreach ($chunks as $index => $chunk) {
            custom_log("translateHtml: Processing chunk " . ($index + 1) . "/" . count($chunks) . ", length: " . mb_strlen($chunk));
            $response = $this->request('/translate', [
                'q' => $chunk,
                'source' => $source,
                'target' => $target,
                'format' => 'html'
            ]);

            $translatedChunk = $response['translatedText'] ?? null;
            if ($translatedChunk) {
                $translatedHtml .= $translatedChunk;
                custom_log("translateHtml: Chunk " . ($index + 1) . " translated successfully.");
            } else {
                // Si una parte falla, devolver la parte original para no perder contenido
                $translatedHtml .= $chunk;
                custom_log("translateHtml: Chunk " . ($index + 1) . " failed to translate. Appending original chunk.");
            }
        }

        return $translatedHtml;
    }

    private function splitHtmlIntoChunks($html, $maxLength)
    {
        $chunks = [];
        $currentChunk = '';
        $dom = new DOMDocument();
        // Suprimir errores de HTML mal formado
        @$dom->loadHTML('<div>' . $html . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        $xpath = new DOMXPath($dom);

        // Query all direct children of the body (or the implied div)
        $nodes = $xpath->query('//body/*');
        if ($nodes->length === 0) {
            // If no block-level elements, treat the whole HTML as one chunk
            $nodes = $xpath->query('//body/text()');
            if ($nodes->length === 0) {
                // Fallback if no text nodes either, just return the original HTML as one chunk
                return [$html];
            }
        }

        foreach ($nodes as $node) {
            $nodeHtml = $dom->saveHTML($node);
            custom_log("splitHtmlIntoChunks: Processing node, length: " . mb_strlen($nodeHtml) . ", HTML: " . substr($nodeHtml, 0, 100) . "...");

            if (mb_strlen($currentChunk . $nodeHtml) <= $maxLength) {
                $currentChunk .= $nodeHtml;
            } else {
                if (!empty($currentChunk)) {
                    $chunks[] = $currentChunk;
                    custom_log("splitHtmlIntoChunks: Added chunk, length: " . mb_strlen($currentChunk));
                }
                $currentChunk = $nodeHtml;
            }
        }
        if (!empty($currentChunk)) {
            $chunks[] = $currentChunk;
            custom_log("splitHtmlIntoChunks: Added final chunk, length: " . mb_strlen($currentChunk));
        }
        return $chunks;
    }

    public function translateTextBatch($texts, $source, $target)
    {
        if (empty($texts)) {
            return null;
        }

        $response = $this->request('/translate', [
            'q' => $texts,
            'source' => $source,
            'target' => $target,
            'format' => 'text'
        ]);

        return $response['translatedText'] ?? null;
    }

    public function getSupportedLanguages()
    {
        $response = $this->request('/languages', [], 'GET');
        return $response ?? [];
    }

    private function request($endpoint, $data, $method = 'POST')
    {
        $url = $this->apiUrl . $endpoint;
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Considera la seguridad de esto

        if ($method === 'POST') {
            custom_log("LibreTranslate POST Request: URL=" . $url . " | Data=" . json_encode($data));
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        } else {
            custom_log("LibreTranslate GET Request: URL=" . $url);
            // Para GET, los datos (si los hubiera) se añadirían a la URL, pero /languages no requiere
        }

        $response_body = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        custom_log("LibreTranslate Response: HTTP Code=" . $http_code . " | Body=" . $response_body);

        if ($http_code >= 400) {
            return null; // Devolver null si hay un error de cliente o servidor
        }

        return json_decode($response_body, true);
    }
}