<?php
/**
 * Sincronizador de EVENTOS Fanatiz para FUTBOL PY.
 * Solo elimina canales creados por este script (webview='yes' + Referer fanatiz).
 * Adaptado para: http://192.168.100.119/fanatiz/
 * ⮕ Agregar SOLO eventos disponibles y eliminar cuando desaparecen.
 */
require_once __DIR__ . '/../includes/config.php';

$config = [
    'json_url'  => 'https://yaetv.com/fanatiz/eventos_tigo.json',
    'log_file'  => __DIR__ . '/eventos_fanatiz.log',
    'category_name' => 'FUTBOL PY EVENTOS',
    'timeout' => 60, // Aumentado porque se toma unos segundos
    'max_retries' => 3,
    'retry_delay' => 2, // segundos entre intentos
];

ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(0);

// Conexión centralizada
$pdo = pdo();

// Validar conexión PDO
if (!$pdo) {
    echo "ERROR: No se pudo conectar a la base de datos" . PHP_EOL;
    exit(1);
}

// Log
function writeLog($m, $file) {
    $ts = date('Y-m-d H:i:s');
    $line = "[$ts] $m" . PHP_EOL;
    file_put_contents($file, $line, FILE_APPEND | LOCK_EX);
    echo $line;
}

/**
 * Obtiene JSON de Fanatiz con reintentos automáticos
 * porque la respuesta puede tardar unos segundos
 */
function getEventsFromFanatiz($url, $maxRetries = 3, $retryDelay = 2) {
    $attempt = 0;
    
    while ($attempt < $maxRetries) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36',
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false
        ]);
        
        $resp = curl_exec($ch);
        $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($http === 200 && $resp) {
            $arr = json_decode($resp, true);
            if (is_array($arr) && !empty($arr)) {
                return $arr;
            }
        }
        
        $attempt++;
        if ($attempt < $maxRetries) {
            sleep($retryDelay);
        }
    }
    
    return false;
}

// DB helpers
function getOrCreateCategory(PDO $pdo, $name) {
    $st = $pdo->prepare("SELECT id FROM categories WHERE name = ?");
    $st->execute([$name]);
    $id = $st->fetchColumn();
    if (!$id) {
        $st = $pdo->prepare("INSERT INTO categories (name) VALUES (?)");
        $st->execute([$name]);
        $id = $pdo->lastInsertId();
    }
    return (int)$id;
}

function getExistingChannelsByCategory(PDO $pdo, $categoryId) {
    $st = $pdo->prepare("SELECT id, name, uri FROM channels WHERE category_id = ?");
    $st->execute([$categoryId]);
    return $st->fetchAll(PDO::FETCH_ASSOC);
}

function addChannel(PDO $pdo, array $ev, int $categoryId) {
    $headers = json_encode($ev['headers'] ?? ['Referer' => 'https://watch.fanatiz.com/channels'], JSON_UNESCAPED_SLASHES);
    
    if ($headers === false) {
        return false;
    }
    
    $st = $pdo->prepare("
        INSERT INTO channels (name, uri, category_id, logo, headers, webview, isMagis, adultos)
        VALUES (?, ?, ?, ?, ?, 'yes', 0, 0)
    ");
    
    return $st->execute([
        mb_strtoupper(trim($ev['name']), 'UTF-8'),
        trim($ev['uri']),
        $categoryId,
        trim($ev['logo'] ?? ''),
        $headers
    ]);
}

/**
 * Borrado SEGURO: solo elimina dentro de una categoría y únicamente
 * canales marcados como creados por este sync (webview='yes' + Referer fanatiz)
 */
function safeDeleteChannelById(PDO $pdo, int $channelId, int $categoryId) {
    $st = $pdo->prepare("
        DELETE FROM channels
        WHERE id = ?
          AND category_id = ?
          AND webview = 'yes'
          AND (headers LIKE '%fanatiz%' OR headers LIKE '%watch.fanatiz%')
    ");
    return $st->execute([$channelId, $categoryId]);
}

/**
 * Limpia canales que desaparecieron del JSON en la categoría específica
 */
function cleanupMissingChannels(PDO $pdo, int $categoryId) {
    $st = $pdo->prepare("
        DELETE FROM channels
        WHERE category_id = ?
          AND webview = 'yes'
          AND (headers LIKE '%fanatiz%' OR headers LIKE '%watch.fanatiz%')
    ");
    return $st->execute([$categoryId]);
}

function cleanOldLogs($logFile, $daysToKeep = 7) {
    if (!file_exists($logFile)) return;
    $lines = file($logFile, FILE_IGNORE_NEW_LINES);
    $cutoff = date('Y-m-d', strtotime("-$daysToKeep days"));
    $out = [];
    foreach ($lines as $line) {
        if (preg_match('/^\[(\d{4}-\d{2}-\d{2})/', $line, $m)) {
            if ($m[1] >= $cutoff) $out[] = $line;
        }
    }
    if (count($out) < count($lines)) {
        file_put_contents($logFile, implode(PHP_EOL, $out) . PHP_EOL);
        writeLog("Logs antiguos limpiados, mantenidas " . count($out) . " líneas", $logFile);
    }
}

// --- Principal ---
try {
    cleanOldLogs($config['log_file'], 3);

    writeLog("=== Sync EVENTOS FANATIZ (FUTBOL PY) ===", $config['log_file']);
    writeLog("Conectando a: " . $config['json_url'] . " (timeout: " . $config['timeout'] . "s)", $config['log_file']);
    
    $events = getEventsFromFanatiz($config['json_url'], $config['max_retries'], $config['retry_delay']);
    
    if ($events === false || !is_array($events)) {
        writeLog("ERROR: No se pudo obtener los eventos de Fanatiz después de " . $config['max_retries'] . " intentos", $config['log_file']);
        exit(1);
    }
    
    if (empty($events)) {
        writeLog("ADVERTENCIA: JSON recibido pero está vacío", $config['log_file']);
        exit(0);
    }
    
    writeLog("✓ JSON ok. Eventos recibidos: " . count($events), $config['log_file']);

    // Validar y normalizar eventos
    $current = [];
    $valid = 0;
    
    foreach ($events as $ev) {
        if (empty($ev['name']) || empty($ev['uri'])) {
            writeLog("⚠ Evento sin name o uri, ignorado", $config['log_file']);
            continue;
        }
        
        $k = mb_strtoupper(trim($ev['name']), 'UTF-8') . '|' . trim($ev['uri']);
        $current[$k] = $ev;
        $valid++;
    }
    
    writeLog("✓ Eventos validados: " . $valid, $config['log_file']);

    // Procesamiento de categoría
    $categoryName = $config['category_name'];
    writeLog("--- Categoría: " . $categoryName . " ---", $config['log_file']);
    
    $catId = getOrCreateCategory($pdo, $categoryName);
    writeLog("✓ Category ID: " . $catId, $config['log_file']);

    // Existentes en DB (solo los marcados por este script)
    $existing = getExistingChannelsByCategory($pdo, $catId);
    $existingMap = [];
    foreach ($existing as $ch) {
        $k = $ch['name'] . '|' . $ch['uri'];
        $existingMap[$k] = $ch;
    }

    // Diferencias
    $toAdd = array_diff_key($current, $existingMap);
    $toDel = array_diff_key($existingMap, $current);

    writeLog("→ A agregar: " . count($toAdd) . ", A eliminar: " . count($toDel), $config['log_file']);

    // Iniciar transacción
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    $pdo->beginTransaction();
    
    $added = 0; 
    $addErr = 0; 
    $deleted = 0; 
    $delErr = 0;

    // Agregar nuevos eventos
    foreach ($toAdd as $ev) {
        writeLog("  [+] " . $ev['name'], $config['log_file']);
        if (addChannel($pdo, $ev, $catId)) {
            $added++;
        } else {
            $addErr++;
            writeLog("    ✗ Error al agregar", $config['log_file']);
        }
    }

    // Borrado SEGURO: respeta categoría y marca
    foreach ($toDel as $ch) {
        writeLog("  [-] " . $ch['name'], $config['log_file']);
        if (safeDeleteChannelById($pdo, (int)$ch['id'], $catId)) {
            $deleted++;
        } else {
            $delErr++;
            writeLog("    ✗ Error/omitido (no cumple marca o categoría)", $config['log_file']);
        }
    }

    // Commit o Rollback
    if ($addErr === 0 && $delErr === 0) {
        $pdo->commit();
        writeLog("✓ Commit " . $categoryName, $config['log_file']);
    } else {
        if (($addErr + $delErr) < max(1, (count($toAdd) + count($toDel)) / 2)) {
            $pdo->commit();
            writeLog("⚠ Commit parcial " . $categoryName, $config['log_file']);
        } else {
            $pdo->rollBack();
            writeLog("✗ Rollback " . $categoryName, $config['log_file']);
        }
    }

    $active = count($current);
    
    writeLog("=== FIN SYNC ===", $config['log_file']);
    writeLog("📊 RESUMEN → +" . $added . " (err " . $addErr . ") | -" . $deleted . " (err " . $delErr . ") | Activos " . $active, $config['log_file']);
    exit(0);

} catch (Throwable $e) {
    if ($pdo && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    writeLog("💥 EXCEPCIÓN: " . $e->getMessage(), $config['log_file']);
    writeLog($e->getTraceAsString(), $config['log_file']);
    exit(1);
}