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

/**
 * Proxy leve para PopPlay.
 *
 * IMPORTANTE:
 * - Streams/listas grandes continuam por redirect 302 para não consumir banda do painel.
 * - APIs pequenas podem ser testadas em sequência para escolher um DNS ativo.
 * - Inclui validação de endpoint/path para evitar chamada estranha e erro em URL.
 */

function proxy_allowed_endpoints(){
    return [
        'live.php',
        'movie.php',
        'series.php',
        'timeshift.php',
        'get.php',
        'xmltv.php',
        'player_api.php',
        'panel_api.php'
    ];
}

function proxy_direct_endpoints(){
    return ['live.php', 'movie.php', 'series.php', 'timeshift.php', 'get.php', 'xmltv.php'];
}

function proxy_json_error($message, $httpCode = 200){
    http_response_code($httpCode);
    header('Content-Type: application/json; charset=utf-8');
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    echo json_encode(['user_info' => ['auth' => 0], 'message' => $message], JSON_UNESCAPED_UNICODE);
    exit;
}

function build_query_without_path(){
    $params = $_GET;
    unset($params['path']);

    $query = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
    $post  = $_POST ? http_build_query($_POST, '', '&', PHP_QUERY_RFC3986) : '';

    return trim($post . ($post && $query ? '&' : '') . $query, '&');
}

function proxy_clean_path(){
    $path = trim((string)($_GET['path'] ?? ''), '/');

    if ($path === '') {
        return '';
    }

    $decoded = rawurldecode($path);

    // Bloqueia tentativa de sair do caminho ou injetar URL externa.
    if (
        strpos($decoded, '..') !== false ||
        strpos($decoded, "\0") !== false ||
        preg_match('~(^|/)(https?:)?//~i', $decoded) ||
        preg_match('~[\r\n]~', $decoded)
    ) {
        proxy_json_error('Caminho inválido', 400);
    }

    // Codifica cada pedaço e preserva as barras do caminho.
    $parts = array_map('rawurlencode', explode('/', $decoded));
    return implode('/', $parts);
}

function make_target_url($portal, $endpoint, $fullQuery){
    $endpoint = basename((string)$endpoint);

    if (!in_array($endpoint, proxy_allowed_endpoints(), true)) {
        proxy_json_error('Endpoint não permitido', 403);
    }

    $portal = rtrim((string)$portal, '/');
    $path   = proxy_clean_path();

    if ($path !== '') {
        $base = preg_replace('/\.php$/', '', $endpoint);
        $url  = $portal . '/' . $base . '/' . $path;
    } else {
        $url = $portal . '/' . $endpoint;
    }

    if ($fullQuery !== '') {
        $url .= '?' . $fullQuery;
    }

    return $url;
}

function proxy_url_looks_alive($url){
    if (!function_exists('curl_init')) {
        return true;
    }

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADER         => false,
        CURLOPT_NOBODY         => true,
        CURLOPT_CONNECTTIMEOUT => 3,
        CURLOPT_TIMEOUT        => 5,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_USERAGENT      => $_SERVER['HTTP_USER_AGENT'] ?? 'PopPlay',
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
    ]);

    curl_exec($ch);
    $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    // Alguns servidores não aceitam HEAD. Nesse caso não bloqueia o redirect.
    if ($code === 0 || $code === 405) {
        return true;
    }

    return ($code >= 200 && $code < 500 && $code !== 404);
}

function redirect_best_dns($endpoint, $fullQuery){
    $portals = get_portals();

    if (!$portals) {
        return false;
    }

    $fallbackUrl = make_target_url($portals[0], $endpoint, $fullQuery);

    foreach ($portals as $portal) {
        $url = make_target_url($portal, $endpoint, $fullQuery);
        if (proxy_url_looks_alive($url)) {
            header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
            header('Pragma: no-cache');
            header('X-Accel-Buffering: no');
            header('Location: ' . $url, true, 302);
            exit;
        }
    }

    // Se todos falharem no teste, mantém comportamento antigo para não quebrar player exigente.
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    header('Pragma: no-cache');
    header('X-Accel-Buffering: no');
    header('Location: ' . $fallbackUrl, true, 302);
    exit;
}

function proxy_endpoint($endpoint){
    $endpoint = basename((string)$endpoint);

    if (!in_array($endpoint, proxy_allowed_endpoints(), true)) {
        proxy_json_error('Endpoint não permitido', 403);
    }

    $fullQuery = build_query_without_path();

    // Streams e listas grandes ficam em redirect para não passar tráfego pesado pelo painel.
    if (in_array($endpoint, proxy_direct_endpoints(), true) || !empty($_GET['path'])) {
        if (redirect_best_dns($endpoint, $fullQuery) === false) {
            proxy_json_error('Nenhum DNS cadastrado');
        }
    }

    // APIs pequenas: testa DNS em sequência e redireciona para o primeiro que responder bem.
    foreach (get_portals() as $portal) {
        $url = make_target_url($portal, $endpoint, $fullQuery);
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER         => false,
            CURLOPT_CONNECTTIMEOUT => 5,
            CURLOPT_TIMEOUT        => 8,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_USERAGENT      => $_SERVER['HTTP_USER_AGENT'] ?? 'PopPlay',
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
        ]);

        $body = curl_exec($ch);
        $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $text = trim((string)$body);
        $bad = $body === false || $text === '' || $code === 404 || $code === 401 || strpos($text, '"auth":0') !== false;

        if (!$bad) {
            header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
            header('Pragma: no-cache');
            header('X-Accel-Buffering: no');
            header('Location: ' . $url, true, 302);
            exit;
        }
    }

    proxy_json_error('Nenhum DNS respondeu');
}
?>
