<?php
/**
 * import_sport.php — Importador automático MULTI-DEPORTE (self-hosted).
 *
 * Corre EN EL SERVIDOR del panel: jala eventos reales de varias categorías desde
 * TheSportsDB (API gratis) para los próximos sport_days días y los guarda en
 * sport_events con source='auto' y su category. La app nunca habla con TheSportsDB:
 * solo lee la agenda de tu panel (webview.php?fetch=sport). Si la fuente muere, la
 * página sigue con lo último importado.
 *
 * Uso:  GET import_sport.php[?token=XXX][&days=N][&key=YYY]
 *   - token: si el ajuste sport_import_token está seteado, hay que mandarlo.
 *   - Programalo 1×/día por cron apuntando a esta URL.
 *
 * Preserva eventos cargados a mano (source='manual'): solo reemplaza los 'auto'.
 */

declare(strict_types=1);
require __DIR__ . '/lib/ibo.php';

// El import puede tardar (~2min con throttle). Que termine aunque el cron/curl corte.
ignore_user_abort(true);
@set_time_limit(0);

header('Content-Type: application/json; charset=utf-8');
ibo_nocache();

// Pequeño respiro entre pedidos (safety). Los runs se trocean por rango de días
// (from/count) para que cada uno sea corto (<= ~24 pedidos, ~15s) y no lo mate el
// timeout de LiteSpeed (~60s) ni el burst-limit de la key pública de TheSportsDB.
const SPORT_THROTTLE_US = 200000; // 0.2s

// --- Auth opcional por token -------------------------------------------------
$need = trim((string) settings_get('sport_import_token', ''));
if ($need !== '' && (string) ($_GET['token'] ?? '') !== $need) {
    http_response_code(403);
    echo json_encode(['ok' => false, 'error' => 'forbidden']);
    exit;
}

// --- Config ------------------------------------------------------------------
$key = trim((string) ($_GET['key'] ?? settings_get('sport_import_key', '3')));
if ($key === '') { $key = '3'; }                       // '3' = key pública v1 de TheSportsDB

// Rango de días a importar: [from, from+count).  'days' se mantiene como alias de count.
$from  = max(0, min(30, (int) ($_GET['from'] ?? 0)));
$count = (int) ($_GET['count'] ?? $_GET['days'] ?? settings_get('sport_days', '7'));
$count = max(1, min(14, $count));

// Categorías a importar: strSport de TheSportsDB => etiqueta que se muestra.
// Editable con el ajuste sport_categories (JSON {"Soccer":"Fútbol",...}).
// strSport (TheSportsDB) => clave canónica (la UI la traduce según el idioma).
// Fútbol y tenis los cubre ESPN (import_espn) con canales, así que acá NO van (evita
// duplicados). TheSportsDB aporta la variedad que ESPN no trae bien.
$defaultCats = [
    'Basketball'        => 'basketball',
    'Ice Hockey'        => 'icehockey',
    'Baseball'          => 'baseball',
    'American Football' => 'amfootball',
    'Motorsport'        => 'motorsport',
    'Fighting'          => 'fighting',
    'Rugby'             => 'rugby',
    'Cricket'           => 'cricket',
    'Volleyball'        => 'volleyball',
];
$cats = $defaultCats;
$rawCats = trim((string) settings_get('sport_categories', ''));
if ($rawCats !== '') {
    $decoded = json_decode($rawCats, true);
    if (is_array($decoded) && $decoded !== []) {
        $cats = $decoded;
    }
}

// --- Migración: columnas source + ext_id + category (idempotente) ------------
$cols = array_column(db()->query('PRAGMA table_info(sport_events)')->fetchAll(), 'name');
if (!in_array('source', $cols, true)) {
    db()->exec("ALTER TABLE sport_events ADD COLUMN source TEXT NOT NULL DEFAULT 'manual'");
}
if (!in_array('ext_id', $cols, true)) {
    db()->exec("ALTER TABLE sport_events ADD COLUMN ext_id TEXT NOT NULL DEFAULT ''");
}
if (!in_array('category', $cols, true)) {
    db()->exec("ALTER TABLE sport_events ADD COLUMN category TEXT NOT NULL DEFAULT ''");
}
foreach (['home_badge', 'away_badge', 'league_badge', 'status', 'score'] as $bcol) {
    if (!in_array($bcol, $cols, true)) {
        db()->exec("ALTER TABLE sport_events ADD COLUMN $bcol TEXT NOT NULL DEFAULT ''");
    }
}

// Ligas que ya trae ESPN (2da fuente, con canales/marcador): no las duplicamos.
$espnLeagues = [];
foreach (db()->query("SELECT DISTINCT league FROM sport_events WHERE source='espn'")->fetchAll() as $r) {
    $espnLeagues[(string) $r['league']] = true;
}

// --- HTTP GET JSON (curl si está, si no file_get_contents) -------------------
function sport_http_json(string $url): ?array
{
    $raw = false;
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_TIMEOUT        => 12,
            CURLOPT_CONNECTTIMEOUT => 8,
            CURLOPT_USERAGENT      => 'panel-sport-import/1.0',
        ]);
        $raw = curl_exec($ch);
        curl_close($ch);
    }
    if ($raw === false && ini_get('allow_url_fopen')) {
        $ctx = stream_context_create(['http' => ['timeout' => 12, 'header' => "User-Agent: panel-sport-import/1.0\r\n"]]);
        $raw = @file_get_contents($url, false, $ctx);
    }
    if (!is_string($raw) || $raw === '') {
        return null;
    }
    $j = json_decode($raw, true);
    return is_array($j) ? $j : null;
}

// --- Descarga por categoría y día (rango [from, from+count)) ------------------
$base     = 'https://www.thesportsdb.com/api/v1/json/' . rawurlencode($key) . '/eventsday.php';
$today    = gmdate('Y-m-d');
$rangeBeg = gmdate('Y-m-d', strtotime($today . ' +' . $from . ' day') ?: time());
$rangeEnd = gmdate('Y-m-d', strtotime($today . ' +' . ($from + $count - 1) . ' day') ?: time());
$rows     = [];
$errors   = 0;
$hits     = 0;
$attempts = 0;
$perCat   = [];
$firstReq = true;
foreach ($cats as $sportKey => $label) {
    $perCat[$label] = 0;
    for ($i = $from; $i < $from + $count; $i++) {
        $d = gmdate('Y-m-d', strtotime($today . ' +' . $i . ' day') ?: time());
        if (!$firstReq) { usleep(SPORT_THROTTLE_US); }   // throttle anti rate-limit
        $firstReq = false;
        $attempts++;
        $j = sport_http_json($base . '?d=' . $d . '&s=' . rawurlencode((string) $sportKey));
        if ($j === null) { $errors++; continue; }
        $hits++;
        foreach (($j['events'] ?? []) ?: [] as $e) {
            $home = trim((string) ($e['strHomeTeam'] ?? ''));
            $away = trim((string) ($e['strAwayTeam'] ?? ''));
            if ($home === '') {
                // Eventos sin equipos (F1, tenis, MMA): usar el nombre del evento.
                $home = trim((string) ($e['strEvent'] ?? ''));
                $away = '';
            }
            if ($home === '') { continue; }
            $rows[] = [
                'category'     => (string) $label,
                'league'       => trim((string) ($e['strLeague'] ?? '')),
                'home'         => $home,
                'away'         => $away,
                'date'         => trim((string) ($e['dateEvent'] ?? $d)) ?: $d,
                'time'         => substr(trim((string) ($e['strTime'] ?? '')), 0, 5), // HH:MM (UTC)
                'channels'     => trim((string) ($e['strTVStation'] ?? '')),
                'ext_id'       => (string) ($e['idEvent'] ?? ''),
                'home_badge'   => trim((string) ($e['strHomeTeamBadge'] ?? '')),
                'away_badge'   => trim((string) ($e['strAwayTeamBadge'] ?? '')),
                'league_badge' => trim((string) ($e['strLeagueBadge'] ?? '')),
            ];
            $perCat[$label]++;
        }
    }
}

// --- Guard: si el run falló mucho (rate-limit), NO pisar los datos buenos -----
// (un reemplazo con datos parciales dejaría la agenda a medias hasta el próximo cron)
$healthy = $attempts > 0 && ($hits / $attempts) >= 0.7;
if (!$healthy) {
    echo json_encode([
        'ok'         => true,
        'replaced'   => false,
        'reason'     => 'rate_limited_or_source_down',
        'imported'   => 0,
        'attempts'   => $attempts,
        'requests'   => $hits,
        'errors'     => $errors,
        'note'       => 'se conservan los eventos previos; reintenta con menos days o key premium',
        'at'         => gmdate('c'),
    ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    exit;
}

// --- Reemplazar SOLO lo auto DE ESTE RANGO (preserva manual y otros días) -----
$n = 0;
db()->beginTransaction();
$del = db()->prepare("DELETE FROM sport_events WHERE source='auto' AND event_date >= ? AND event_date <= ?");
$del->execute([$rangeBeg, $rangeEnd]);
$ins = db()->prepare(
    "INSERT INTO sport_events(league,home,away,event_date,event_time,channels,sort,created_at,source,ext_id,category,home_badge,away_badge,league_badge)
     VALUES(?,?,?,?,?,?,?,?, 'auto', ?, ?, ?, ?, ?)"
);
foreach ($rows as $r) {
    // Solo lo que cae dentro del rango pedido (por si la API devuelve fechas extra).
    if ($r['date'] < $rangeBeg || $r['date'] > $rangeEnd) { continue; }
    // Sin duplicar ligas que ya cubre ESPN (con canales/marcador).
    if (isset($espnLeagues[$r['league']])) { continue; }
    $ins->execute([$r['league'], $r['home'], $r['away'], $r['date'], $r['time'], $r['channels'], $n, gmdate('c'), $r['ext_id'], $r['category'], $r['home_badge'], $r['away_badge'], $r['league_badge']]);
    $n++;
}
db()->commit();

settings_set('sport_last_import', gmdate('c'));
settings_set('sport_enabled', '1');

echo json_encode([
    'ok'         => true,
    'replaced'   => true,
    'range'      => [$rangeBeg, $rangeEnd],
    'imported'   => $n,
    'categories' => array_filter($perCat),
    'attempts'   => $attempts,
    'requests'   => $hits,
    'errors'     => $errors,
    'key'        => $key,
    'at'         => gmdate('c'),
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
