<?php
// SPANDAMAN tmdbbase cached series route.
// Keeps XC/IBO episode routes lightweight by redirecting verified cached media directly.

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, OPTIONS');
header('Access-Control-Allow-Headers: Range, Origin, Accept, Content-Type, User-Agent');
header('Access-Control-Expose-Headers: Content-Length, Content-Range, Content-Type, Location');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');

if (strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'OPTIONS') {
    http_response_code(204);
    exit;
}

function spandaman_series_json_file($path) {
    if (!is_file($path)) {
        return [];
    }
    $raw = @file_get_contents($path);
    if ($raw === false || trim($raw) === '') {
        return [];
    }
    $decoded = json_decode($raw, true);
    return is_array($decoded) ? $decoded : [];
}

function spandaman_series_episode_data($episodeId) {
    $episodeId = (string)$episodeId;
    $files = [
        __DIR__ . '/spandaman_series_episode_map.json',
        __DIR__ . '/channels/spandaman_series_episode_map.json',
    ];
    foreach ($files as $file) {
        $map = spandaman_series_json_file($file);
        if (!isset($map[$episodeId]) || !is_string($map[$episodeId]) || $map[$episodeId] === '') {
            continue;
        }
        $decoded = base64_decode($map[$episodeId], true);
        if (is_string($decoded) && strpos($decoded, ':') !== false) {
            return $decoded;
        }
    }
    return '';
}

function spandaman_series_cache_entry($keys) {
    $files = [
        __DIR__ . '/spandaman_playable_tmdb_cache.json',
        __DIR__ . '/channels/spandaman_playable_tmdb_cache.json',
    ];
    foreach ($files as $file) {
        $cache = spandaman_series_json_file($file);
        if (!$cache) {
            continue;
        }
        foreach ($keys as $key) {
            if (!isset($cache[$key])) {
                continue;
            }
            $entry = $cache[$key];
            if (is_string($entry) && $entry !== '' && $entry !== '_failed_' && $entry !== '_running_') {
                return ['url' => $entry, 'key' => $key];
            }
            if (is_array($entry)) {
                $url = $entry['url'] ?? $entry['proxy_url'] ?? $entry['raw_url'] ?? '';
                if (is_string($url) && $url !== '' && $url !== '_failed_' && $url !== '_running_') {
                    return ['url' => $url, 'key' => $key];
                }
            }
        }
    }
    return null;
}

function spandaman_series_extract_direct_url($url) {
    $url = trim((string)$url);
    if ($url === '') {
        return '';
    }
    if (preg_match('~^(?:https?://[^/]+/[^?]+/)?(?:hls_proxy|video_proxy)\.php~i', $url) || preg_match('~^(?:hls_proxy|video_proxy)\.php~i', $url)) {
        $parts = parse_url($url);
        if (isset($parts['query'])) {
            parse_str($parts['query'], $query);
            foreach (['url', 'u'] as $name) {
                if (!empty($query[$name]) && is_string($query[$name]) && preg_match('~^https?://~i', $query[$name])) {
                    return $query[$name];
                }
            }
        }
    }
    return $url;
}

function spandaman_series_base_url() {
    $https = (!empty($_SERVER['HTTPS']) && strtolower((string)$_SERVER['HTTPS']) !== 'off')
        || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower((string)$_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https');
    $scheme = $https ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'apps.spandaman.co.uk';
    $script = $_SERVER['SCRIPT_NAME'] ?? '/spandaman/tmdbbase/series_play.php';
    return $scheme . '://' . $host . rtrim(str_replace('\\', '/', dirname($script)), '/') . '/';
}

function spandaman_series_route_url($url) {
    $url = trim((string)$url);
    if ($url === '') {
        return '';
    }
    // Keep tmdbbase proxy URLs intact because they carry required Referer/Origin/User-Agent data.
    if (preg_match('~^(?:hls_proxy|video_proxy)\.php(?:/|\?)~i', $url)) {
        return spandaman_series_base_url() . ltrim($url, '/');
    }
    if (preg_match('~^/(?:hls_proxy|video_proxy)\.php(?:/|\?)~i', $url)) {
        return spandaman_series_base_url() . ltrim($url, '/');
    }
    if (preg_match('~^https?://[^/]+/.*/(?:hls_proxy|video_proxy)\.php(?:/|\?)~i', $url)) {
        return $url;
    }
    return spandaman_series_extract_direct_url($url);
}

function spandaman_series_send_redirect($url, $key) {
    $url = spandaman_series_route_url($url);
    if ($url === '' || !preg_match('~^https?://~i', $url)) {
        http_response_code(404);
        echo 'Series cached route has no valid media URL.';
        exit;
    }
    while (ob_get_level() > 0) {
        @ob_end_clean();
    }
    header('X-SPANDAMAN-Route: series-cache-direct');
    header('X-SPANDAMAN-Cache-Key: ' . preg_replace('/[^a-zA-Z0-9_:-]/', '', (string)$key));
    header('HTTP/1.1 302 Found');
    header('Location: ' . $url);
    exit;
}

function spandaman_series_dynamic_fallback($episodeId, $ext) {
    $episodeId = preg_replace('/[^0-9]/', '', (string)$episodeId);
    $ext = preg_replace('/[^a-zA-Z0-9]/', '', (string)$ext);
    if ($episodeId === '') {
        http_response_code(404);
        echo 'Series dynamic fallback missing episode id.';
        exit;
    }
    if ($ext === '') {
        $ext = 'm3u8';
    }
    while (ob_get_level() > 0) {
        @ob_end_clean();
    }
    header('X-SPANDAMAN-Route: series-dynamic-fallback');
    header('HTTP/1.1 302 Found');
    header('Location: ' . spandaman_series_base_url() . 'play.php?movieId=' . rawurlencode($episodeId) . '&type=series&ext=' . rawurlencode($ext));
    exit;
}

$episodeId = preg_replace('/[^0-9]/', '', (string)($_GET['episodeId'] ?? $_GET['movieId'] ?? ''));
if ($episodeId === '') {
    http_response_code(400);
    echo 'Missing episode id.';
    exit;
}

$episodeData = spandaman_series_episode_data($episodeId);
if ($episodeData === '') {
    http_response_code(404);
    echo 'Series episode map entry not found.';
    exit;
}

$parts = explode(':', $episodeData, 2);
$path = explode('/', $parts[1] ?? '');
if (count($path) < 5) {
    http_response_code(404);
    echo 'Invalid series episode map entry.';
    exit;
}

$tmdbId = preg_replace('/[^0-9]/', '', (string)$path[0]);
$season = str_pad(preg_replace('/[^0-9]/', '', (string)$path[2]), 2, '0', STR_PAD_LEFT);
$episode = str_pad(preg_replace('/[^0-9]/', '', (string)$path[4]), 2, '0', STR_PAD_LEFT);
if ($tmdbId === '' || $season === '00' || $episode === '00') {
    http_response_code(404);
    echo 'Invalid series episode identifiers.';
    exit;
}

$keys = [
    $tmdbId . '_series_' . $episodeId . '_url',
    $tmdbId . '_series_s' . $season . 'e' . $episode . '_url',
];

// Older cache builds store only the first playable episode at series level.
if ($season === '01' && $episode === '01') {
    $keys[] = $tmdbId;
    $keys[] = $tmdbId . '_tmdb_url';
}

$entry = spandaman_series_cache_entry($keys);
if ($entry !== null) {
    spandaman_series_send_redirect($entry['url'], $entry['key']);
}

spandaman_series_dynamic_fallback($episodeId, $_GET['ext'] ?? 'm3u8');
