<?php
require_once __DIR__ . '/config.php';

// =============================================================
// MAPEO DE FILTROS A CATEGORÍAS
// IDs obtenidos de /control/filtering/status de AdGuard
// =============================================================
function getFilterCategories(): array {
    return [
        // --- Phishing / Scam / Fraude ---
        1697844998 => ['name' => 'Phishing',         'color' => '#FF6B35', 'icon' => 'bi-fish',              'group' => 'Phishing & Fraude'],
        1697845001 => ['name' => 'Estafas',           'color' => '#FF6B35', 'icon' => 'bi-exclamation-triangle','group' => 'Phishing & Fraude'],
        1704763752 => ['name' => 'Phishing',          'color' => '#FF6B35', 'icon' => 'bi-fish',              'group' => 'Phishing & Fraude'],
        1707305372 => ['name' => 'Phishing',          'color' => '#FF6B35', 'icon' => 'bi-fish',              'group' => 'Phishing & Fraude'],
        1721499312 => ['name' => 'Phishing',          'color' => '#FF6B35', 'icon' => 'bi-fish',              'group' => 'Phishing & Fraude'],
        1730981236 => ['name' => 'Fraude',            'color' => '#FF6B35', 'icon' => 'bi-exclamation-triangle','group' => 'Phishing & Fraude'],
        1730981239 => ['name' => 'Phishing',          'color' => '#FF6B35', 'icon' => 'bi-fish',              'group' => 'Phishing & Fraude'],
        1730981244 => ['name' => 'Estafas',           'color' => '#FF6B35', 'icon' => 'bi-exclamation-triangle','group' => 'Phishing & Fraude'],

        // --- Malware ---
        1697844999 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1697845002 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1697845003 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1697845004 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1697845006 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1704763753 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1713656436 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1721499311 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1730981238 => ['name' => 'Malware',           'color' => '#DC3545', 'icon' => 'bi-bug',               'group' => 'Malware & Amenazas'],
        1730981242 => ['name' => 'Ransomware',        'color' => '#B02A37', 'icon' => 'bi-lock-fill',         'group' => 'Malware & Amenazas'],
        1730981233 => ['name' => 'Abuso',             'color' => '#DC3545', 'icon' => 'bi-hand-thumbs-down',  'group' => 'Malware & Amenazas'],

        // --- Threat Intelligence ---
        1697845012 => ['name' => 'Amenazas Intel.',   'color' => '#495057', 'icon' => 'bi-shield-exclamation','group' => 'Inteligencia de Amenazas'],
        1697845013 => ['name' => 'Amenazas Intel.',   'color' => '#495057', 'icon' => 'bi-shield-exclamation','group' => 'Inteligencia de Amenazas'],
        1704763751 => ['name' => 'Amenazas Intel.',   'color' => '#495057', 'icon' => 'bi-shield-exclamation','group' => 'Inteligencia de Amenazas'],
        1710270331 => ['name' => 'Amenazas Intel.',   'color' => '#495057', 'icon' => 'bi-shield-exclamation','group' => 'Inteligencia de Amenazas'],
        1730981248 => ['name' => 'Amenazas Intel.',   'color' => '#495057', 'icon' => 'bi-shield-exclamation','group' => 'Inteligencia de Amenazas'],

        // --- Cryptomining ---
        1697845000 => ['name' => 'Cryptomining',      'color' => '#FFC107', 'icon' => 'bi-currency-bitcoin',  'group' => 'Crypto & Mining'],
        1721499306 => ['name' => 'Cryptomining',      'color' => '#FFC107', 'icon' => 'bi-currency-bitcoin',  'group' => 'Crypto & Mining'],
        1721499307 => ['name' => 'Cryptomining',      'color' => '#FFC107', 'icon' => 'bi-currency-bitcoin',  'group' => 'Crypto & Mining'],
        1730981234 => ['name' => 'Crypto',            'color' => '#FFC107', 'icon' => 'bi-currency-bitcoin',  'group' => 'Crypto & Mining'],
        1730981250 => ['name' => 'Cryptomining',      'color' => '#FFC107', 'icon' => 'bi-currency-bitcoin',  'group' => 'Crypto & Mining'],

        // --- Pornografía / Adultos ---
        1730981241 => ['name' => 'Pornografía',       'color' => '#E91E63', 'icon' => 'bi-eye-slash',         'group' => 'Contenido Adulto'],
        1730981247 => ['name' => 'Contenido Adulto',  'color' => '#E91E63', 'icon' => 'bi-eye-slash',         'group' => 'Contenido Adulto'],
        1740227253 => ['name' => 'Pornografía',       'color' => '#E91E63', 'icon' => 'bi-eye-slash',         'group' => 'Contenido Adulto'],

        // --- Juegos de Azar ---
        1730981237 => ['name' => 'Juegos de Azar',    'color' => '#9C27B0', 'icon' => 'bi-dice-5',            'group' => 'Juegos de Azar'],
        1740227251 => ['name' => 'Juegos de Azar',    'color' => '#9C27B0', 'icon' => 'bi-dice-5',            'group' => 'Juegos de Azar'],
        1740227252 => ['name' => 'Juegos de Azar',    'color' => '#9C27B0', 'icon' => 'bi-dice-5',            'group' => 'Juegos de Azar'],

        // --- VPN / Proxy / Bypass ---
        1704763754 => ['name' => 'VPN/Proxy/TOR',     'color' => '#20C997', 'icon' => 'bi-lock',              'group' => 'VPN & Bypass'],
        1713656438 => ['name' => 'VPN/Proxy/TOR',     'color' => '#20C997', 'icon' => 'bi-lock',              'group' => 'VPN & Bypass'],
        1721499309 => ['name' => 'DoH Bypass',        'color' => '#20C997', 'icon' => 'bi-lock',              'group' => 'VPN & Bypass'],
        1721499314 => ['name' => 'Proxy Residencial', 'color' => '#20C997', 'icon' => 'bi-lock',              'group' => 'VPN & Bypass'],
        1721499317 => ['name' => 'VPN',               'color' => '#20C997', 'icon' => 'bi-lock',              'group' => 'VPN & Bypass'],

        // --- Piratería ---
        1730981240 => ['name' => 'Piratería',         'color' => '#6C757D', 'icon' => 'bi-pirate',            'group' => 'Piratería'],
        1730981245 => ['name' => 'Torrents',          'color' => '#6C757D', 'icon' => 'bi-pirate',            'group' => 'Piratería'],
        1721499318 => ['name' => 'Warez',             'color' => '#6C757D', 'icon' => 'bi-pirate',            'group' => 'Piratería'],
        1740227250 => ['name' => 'Piratería',         'color' => '#6C757D', 'icon' => 'bi-pirate',            'group' => 'Piratería'],

        // --- Rastreo / Ads ---
        1730981246 => ['name' => 'Rastreo',           'color' => '#0DCAF0', 'icon' => 'bi-cursor',            'group' => 'Rastreo & Publicidad'],
        1730981249 => ['name' => 'Rastreo',           'color' => '#0DCAF0', 'icon' => 'bi-cursor',            'group' => 'Rastreo & Publicidad'],
        1713656437 => ['name' => 'Spam/TLD',          'color' => '#6C757D', 'icon' => 'bi-envelope-x',        'group' => 'Rastreo & Publicidad'],

        // --- Redirección ---
        1721499315 => ['name' => 'Redirección',       'color' => '#6C757D', 'icon' => 'bi-arrow-repeat',      'group' => 'Redirección'],
        1730981243 => ['name' => 'Redirección',       'color' => '#6C757D', 'icon' => 'bi-arrow-repeat',      'group' => 'Redirección'],

        // --- Drogas ---
        1730981235 => ['name' => 'Drogas',            'color' => '#795548', 'icon' => 'bi-capsule',           'group' => 'Drogas'],
        1740227255 => ['name' => 'Drogas',            'color' => '#795548', 'icon' => 'bi-capsule',           'group' => 'Drogas'],

        // --- Violencia ---
        1740227254 => ['name' => 'Violencia',         'color' => '#B71C1C', 'icon' => 'bi-exclamation-octagon','group' => 'Violencia'],

        // --- Hacking / DDoS ---
        1721499310 => ['name' => 'Hacking',           'color' => '#198754', 'icon' => 'bi-terminal',          'group' => 'Seguridad'],
        1721499308 => ['name' => 'DDoS',              'color' => '#DC3545', 'icon' => 'bi-lightning',         'group' => 'Seguridad'],

        // --- Stalkerware ---
        1697845005 => ['name' => 'Stalkerware',       'color' => '#6F42C1', 'icon' => 'bi-eye',               'group' => 'Stalkerware'],
        1721499316 => ['name' => 'Stalkerware',       'color' => '#6F42C1', 'icon' => 'bi-eye',               'group' => 'Stalkerware'],

        // --- Otros ---
        1742560595 => ['name' => 'Trampas',           'color' => '#6C757D', 'icon' => 'bi-patch-exclamation', 'group' => 'Otros'],
        1742560596 => ['name' => 'Videojuegos',       'color' => '#198754', 'icon' => 'bi-controller',        'group' => 'Otros'],
        1742560597 => ['name' => 'Control Remoto',    'color' => '#6C757D', 'icon' => 'bi-pc-display',        'group' => 'Otros'],
        1721499304 => ['name' => 'Lista Personalizada','color' => '#0D6EFD', 'icon' => 'bi-list-check',        'group' => 'Otros'],
    ];
}

function getCategoryForFilter(?int $filterId): array {
    if ($filterId === null) {
        return ['name' => 'Desconocido', 'color' => '#6C757D', 'icon' => 'bi-question-circle', 'group' => 'Otros'];
    }
    $categories = getFilterCategories();
    return $categories[$filterId] ?? ['name' => 'Otro Bloqueo', 'color' => '#6C757D', 'icon' => 'bi-slash-circle', 'group' => 'Otros'];
}

function getReasonLabel(string $reason): string {
    return match($reason) {
        'FilteredBlackList'     => 'Lista de Bloqueo',
        'FilteredSafeBrowsing'  => 'Navegación Segura',
        'FilteredParental'      => 'Control Parental',
        'FilteredSafeSearch'    => 'Búsqueda Segura',
        'NotFilteredWhiteList'  => 'Lista Blanca',
        'NotFilteredNotFound'   => 'Permitido',
        'Rewrite'               => 'Reescritura DNS',
        default                 => $reason,
    };
}

function isBlocked(string $reason): bool {
    return str_starts_with($reason, 'Filtered');
}

// Llamada a la API de AdGuard con autenticación básica (usa cURL).
// $server = ['url'=>..., 'user'=>..., 'pass'=>...] o null para usar el primer servidor.
function adguardGet(string $path, array $params = [], ?array $server = null): ?array {
    $baseUrl = $server['url']  ?? ADGUARD_SERVERS[0]['url'];
    $user    = $server['user'] ?? ADGUARD_USER;
    $pass    = $server['pass'] ?? ADGUARD_PASS;

    $url = $baseUrl . $path;
    if (!empty($params)) {
        $url .= '?' . http_build_query($params);
    }

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_USERPWD        => $user . ':' . $pass,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 3,
        CURLOPT_HTTPHEADER     => ['Accept: application/json'],
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlErr  = curl_error($ch);
    curl_close($ch);

    if ($response === false || $httpCode !== 200) {
        // Log al error_log de PHP para diagnóstico
        error_log("adguardGet FAIL [$httpCode] $url" . ($curlErr ? " — $curlErr" : ''));
        return null;
    }
    return json_decode($response, true);
}

// =============================================================
// EXPLICACIÓN DE DOMINIOS BLOQUEADOS (OpenAI + caché en DB)
// =============================================================

// Asegura que exista la tabla de caché. Se llama de forma perezosa.
function ensureDomainExplanationsTable(PDO $pdo): void {
    static $done = false;
    if ($done) return;
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS domain_explanations (
            domain     VARCHAR(255) NOT NULL PRIMARY KEY,
            que_es     TEXT,
            por_que    TEXT,
            riesgo     VARCHAR(10),
            consejo    TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
    ");
    $done = true;
}

// Normaliza/valida un dominio (defensa básica contra inyección de prompt y abuso).
function sanitizeDomain(string $domain): ?string {
    $domain = strtolower(trim($domain));
    $domain = rtrim($domain, '.');
    if ($domain === '' || strlen($domain) > 253) return null;
    // Solo caracteres válidos de hostname
    if (!preg_match('/^[a-z0-9._-]+$/', $domain)) return null;
    if (strpos($domain, '.') === false) return null;
    return $domain;
}

// Llama a OpenAI para explicar un dominio en lenguaje simple. Devuelve array o null.
function openaiExplainDomain(string $domain, string $category): ?array {
    if (!OPENAI_ENABLED || OPENAI_API_KEY === '') {
        error_log('openaiExplainDomain: OpenAI no configurado');
        return null;
    }

    $sys = 'Sos un asistente de ciberseguridad de una empresa que ofrece protección DNS. '
         . 'Tu trabajo es explicarle a un usuario SIN conocimientos técnicos por qué su sistema '
         . 'de protección bloqueó un dominio de internet. Usá español rioplatense, claro y tranquilizador. '
         . 'No inventes datos específicos si no conocés el dominio: en ese caso explicá de forma general '
         . 'según la categoría. Respondé SIEMPRE en JSON con esta forma exacta: '
         . '{"que_es": "1-2 oraciones sobre qué es ese dominio", '
         . '"por_que": "1-2 oraciones sobre por qué se bloqueó", '
         . '"riesgo": "bajo|medio|alto", '
         . '"consejo": "1 oración breve y tranquilizadora para el usuario"}';

    $usr = "Dominio bloqueado: {$domain}\nCategoría asignada por el filtro: {$category}";

    $payload = json_encode([
        'model'           => OPENAI_MODEL,
        'temperature'     => 0.3,
        'max_tokens'      => 350,
        'response_format' => ['type' => 'json_object'],
        'messages'        => [
            ['role' => 'system', 'content' => $sys],
            ['role' => 'user',   'content' => $usr],
        ],
    ]);

    $ch = curl_init('https://api.openai.com/v1/chat/completions');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $payload,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_HTTPHEADER     => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . OPENAI_API_KEY,
        ],
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlErr  = curl_error($ch);
    curl_close($ch);

    if ($response === false || $httpCode !== 200) {
        error_log("openaiExplainDomain FAIL [$httpCode]" . ($curlErr ? " — $curlErr" : " — $response"));
        return null;
    }

    $data    = json_decode($response, true);
    $content = $data['choices'][0]['message']['content'] ?? '';
    $parsed  = json_decode($content, true);
    if (!is_array($parsed)) {
        error_log('openaiExplainDomain: respuesta no parseable — ' . $content);
        return null;
    }

    $riesgo = strtolower($parsed['riesgo'] ?? 'medio');
    if (!in_array($riesgo, ['bajo', 'medio', 'alto'])) $riesgo = 'medio';

    return [
        'que_es'  => trim($parsed['que_es']  ?? ''),
        'por_que' => trim($parsed['por_que'] ?? ''),
        'riesgo'  => $riesgo,
        'consejo' => trim($parsed['consejo'] ?? ''),
    ];
}

// Devuelve la explicación de un dominio, usando caché en DB. Genera y guarda si no existe.
function getDomainExplanation(PDO $pdo, string $domain, string $category): ?array {
    ensureDomainExplanationsTable($pdo);

    $stmt = $pdo->prepare("SELECT domain, que_es, por_que, riesgo, consejo, created_at FROM domain_explanations WHERE domain = ?");
    $stmt->execute([$domain]);
    $cached = $stmt->fetch();
    if ($cached) {
        $cached['cached'] = true;
        return $cached;
    }

    $exp = openaiExplainDomain($domain, $category);
    if (!$exp) return null;

    $ins = $pdo->prepare("
        INSERT INTO domain_explanations (domain, que_es, por_que, riesgo, consejo)
        VALUES (?, ?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE que_es=VALUES(que_es), por_que=VALUES(por_que),
                                riesgo=VALUES(riesgo), consejo=VALUES(consejo)
    ");
    $ins->execute([$domain, $exp['que_es'], $exp['por_que'], $exp['riesgo'], $exp['consejo']]);

    $exp['domain'] = $domain;
    $exp['cached'] = false;
    return $exp;
}

function formatNumber(int $num): string {
    if ($num >= 1000000) return number_format($num / 1000000, 1) . 'M';
    if ($num >= 1000)    return number_format($num / 1000, 1) . 'K';
    return (string)$num;
}

function percentOf(int $part, int $total): string {
    if ($total === 0) return '0%';
    return round(($part / $total) * 100, 1) . '%';
}
