<?php
// stream.php - REDIRECIONAMENTO PURO E DIRETO (VOD E LIVE)
ob_start();
error_reporting(0);
ini_set('display_errors', 0);

require_once 'config.php';

$token = $_GET['token'] ?? '';
$user  = $_GET['user'] ?? '';
$pass  = $_GET['pass'] ?? '';
$id    = $_GET['id'] ?? '';
$ext   = $_GET['ext'] ?? ''; 
$type  = $_GET['type'] ?? ''; // Recupera o tipo injetado pelo .htaccess

// DETECTA SE É VOD LOGO NO INÍCIO PARA ISENTAR DO BLOQUEIO
$is_vod = ($type === 'movie' || $type === 'series' || (!empty($ext) && in_array(strtolower($ext), ['mp4', 'mkv', 'avi'])));

// 1. DESCRIPTOGRAFA O TOKEN NBR
if (!empty($token) && strpos($token, 'NBR_') === 0) {
    $base64 = substr($token, 4);
    $decoded = base64_decode(strtr($base64, '-_', '+/'));
    if ($decoded && strpos($decoded, ':') !== false) {
        list($user, $pass) = explode(':', $decoded);
    } else {
        header("HTTP/1.0 403 Forbidden"); die("Token Invalido");
    }
}

if (empty($user) || empty($pass) || empty($id)) {
    header("HTTP/1.0 400 Bad Request"); die("Parametros ausentes");
}

$pdo = getConexaoAtiva();
$pdo_int = getConexaoInterna();

$modo_ativo = 'interno';
try { $modo_ativo = $pdo_int->query("SELECT modo_ativo FROM configuracoes LIMIT 1")->fetchColumn() ?: 'interno'; } catch(Exception $e){}

// =======================================================================
// RASTREADOR HÍBRIDO KOFFICE
// =======================================================================
try {
    // CAPTURA E LIMPEZA BLINDADA DE IP (Remove Portas e Proxies)
    $ip_bruto = $_SERVER['HTTP_CLIENT_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
    $ip_partes = explode(',', $ip_bruto);
    $ip_cliente = trim($ip_partes[0]);
    $ip_cliente = preg_replace('/:\d+$/', '', $ip_cliente); // Corta a porta para não bloquear o mesmo Wi-Fi
    
    $agora = time();
    $tabela_clientes = ($modo_ativo === 'xui') ? '`lines`' : '`users`';
    
    // =======================================================================
    // TABELA AUXILIAR BLINDADA NO BANCO INTERNO (Garante o salvamento)
    // =======================================================================
    try {
        $pdo_int->exec("CREATE TABLE IF NOT EXISTS antifraude_ips (uid INT PRIMARY KEY, last_ip VARCHAR(255), last_activity INT)");
    } catch(Exception $e){}
    // =======================================================================

    // =======================================================================
    // AUTO-CORREÇÃO DE BANCO DE DADOS (GARANTE O BLOQUEIO NO MODO INTERNO)
    // =======================================================================
    if ($modo_ativo !== 'xui') {
        try {
            $chk1 = $pdo->query("SHOW COLUMNS FROM `users` LIKE 'last_ip'");
            if (!$chk1->fetch()) { $pdo->exec("ALTER TABLE `users` ADD COLUMN `last_ip` VARCHAR(255) NULL"); }
            
            $chk2 = $pdo->query("SHOW COLUMNS FROM `users` LIKE 'last_activity'");
            if (!$chk2->fetch()) { $pdo->exec("ALTER TABLE `users` ADD COLUMN `last_activity` INT(11) DEFAULT 0"); }
            
            $chk3 = $pdo->query("SHOW COLUMNS FROM `users` LIKE 'current_channel'");
            if (!$chk3->fetch()) { $pdo->exec("ALTER TABLE `users` ADD COLUMN `current_channel` INT(11) DEFAULT NULL"); }
        } catch(Exception $e){}
    }
    // =======================================================================

    $stmtU = $pdo->prepare("SELECT id, max_connections, last_ip, last_activity FROM $tabela_clientes WHERE username = ? LIMIT 1");
    $stmtU->execute([$user]);
    $userData = $stmtU->fetch(PDO::FETCH_ASSOC);
    $uid = $userData['id'] ?? null;

    // =======================================================================
    // TRAVA DE TELAS COM REDIRECIONAMENTO PARA VÍDEO (ISENTO PARA VOD)
    // =======================================================================
    if ($uid) {
        $max_cons = (int)($userData['max_connections'] ?? 1);
        $last_ip_db = $userData['last_ip'] ?? '';
        $last_activity_db = (int)($userData['last_activity'] ?? 0);

        // PUXA DO BANCO INTERNO (Garante que a trava funciona se o Xtream recusar a coluna)
        try {
            $stmtAF = $pdo_int->prepare("SELECT last_ip, last_activity FROM antifraude_ips WHERE uid = ?");
            $stmtAF->execute([$uid]);
            if ($rowAF = $stmtAF->fetch(PDO::FETCH_ASSOC)) {
                if (!empty($rowAF['last_ip'])) {
                    $last_ip_db = $rowAF['last_ip'];
                    $last_activity_db = (int)$rowAF['last_activity'];
                }
            }
        } catch(Exception $e){}

        // Se NÃO FOR VOD, o cliente tem apenas 1 tela e o IP atual for diferente do último IP salvo
        // E a última atividade dele foi há menos de 3 HORAS (10800 segundos)
        if (!$is_vod && $max_cons <= 1 && !empty($last_ip_db) && $last_ip_db !== $ip_cliente) {
            $tempo_passado = $agora - $last_activity_db;
            if ($tempo_passado < 10800) { 
                
                // ==============================================================
                // COLOQUE O LINK DO SEU VÍDEO DE BLOQUEIO AQUI EMBAIXO
                // ==============================================================
                $video_bloqueio = "https://koffice.tvsbr.top/video_de_bloqueio.mp4";
                
                header("Location: " . $video_bloqueio, true, 302);
                exit;
            }
        }
    }
    // =======================================================================

    // =======================================================================
    // TRAVA BLINDADA DE BOUQUET (CORRIGIDA PARA XUI.ONE E JSON QUEBRADO)
    // =======================================================================
    if ($uid) {
        $acesso_permitido = false;
        try {
            $stmtBqUser = $pdo->prepare("SELECT bouquet FROM $tabela_clientes WHERE id = ?");
            $stmtBqUser->execute([$uid]);
            $userBouquet = $stmtBqUser->fetchColumn();

            if (!empty($userBouquet)) {
                // Extrator seguro de IDs do Bouquet do cliente
                preg_match_all('/\d+/', $userBouquet, $m_user_bq);
                
                if (!empty($m_user_bq[0])) {
                    $bq_ids = implode(',', $m_user_bq[0]);
                    
                    // Verifica se o ID solicitado é um episódio de série para checar a "Série Mãe"
                    $master_series_id = null;
                    $tabela_ep = ($modo_ativo === 'xui') ? 'streams_episodes' : 'series_episodes';
                    try {
                        $stmtSerieMaster = $pdo->prepare("SELECT series_id FROM $tabela_ep WHERE stream_id = ? LIMIT 1");
                        $stmtSerieMaster->execute([$id]);
                        $master_series_id = $stmtSerieMaster->fetchColumn();
                    } catch(Exception $e){}

                    // VERIFICA SE O PAINEL (XUI ONE) SEPARA FILMES EM OUTRA COLUNA
                    $has_movies_col = false;
                    try { $pdo->query("SELECT bouquet_movies FROM bouquets LIMIT 1"); $has_movies_col = true; } catch(Exception $e){}
                    
                    $col_query = $has_movies_col ? "bouquet_channels, bouquet_series, bouquet_movies" : "bouquet_channels, bouquet_series";

                    $stmtBq = $pdo->query("SELECT $col_query FROM bouquets WHERE id IN ($bq_ids)");
                    
                    while ($bq = $stmtBq->fetch(PDO::FETCH_ASSOC)) {
                        // 1. Verifica Canais (Extrator Seguro)
                        preg_match_all('/\d+/', $bq['bouquet_channels'] ?? '', $m_ch);
                        if (!empty($m_ch[0]) && in_array($id, $m_ch[0])) { 
                            $acesso_permitido = true; 
                            break; 
                        }
                        
                        // 1.5. Verifica Filmes XUI ONE (Extrator Seguro)
                        if ($has_movies_col) {
                            preg_match_all('/\d+/', $bq['bouquet_movies'] ?? '', $m_mv);
                            if (!empty($m_mv[0]) && in_array($id, $m_mv[0])) { 
                                $acesso_permitido = true; 
                                break; 
                            }
                        }
                        
                        // 2. Se for episódio, verifica se a Série Mãe está no pacote (Extrator Seguro)
                        if ($master_series_id) {
                            preg_match_all('/\d+/', $bq['bouquet_series'] ?? '', $m_sr);
                            if (!empty($m_sr[0]) && in_array($master_series_id, $m_sr[0])) { 
                                $acesso_permitido = true; 
                                break; 
                            }
                        }
                    }
                }
            }
        } catch(Exception $e){}

        if (!$acesso_permitido) {
            header("HTTP/1.0 403 Forbidden");
            die("Conteudo bloqueado. Nao faz parte do seu pacote.");
        }
    }
    // =======================================================================
    // FIM DA TRAVA DE BOUQUET
    // =======================================================================
    
    if ($uid) {
        try {
            // Atualiza banco auxiliar blindado
            if ($is_vod) {
                $pdo_int->prepare("UPDATE antifraude_ips SET last_activity = ? WHERE uid = ?")->execute([$agora, $uid]);
            } else {
                $pdo_int->prepare("REPLACE INTO antifraude_ips (uid, last_ip, last_activity) VALUES (?, ?, ?)")->execute([$uid, $ip_cliente, $agora]);
            }
        } catch(Exception $e) {}

        try {
            // Se for Filme/Série, NÃO ATUALIZA o IP para não roubar a vaga do Canal Ao Vivo
            if ($is_vod) {
                $pdo->prepare("UPDATE $tabela_clientes SET last_activity = ? WHERE id = ?")->execute([$agora, $uid]);
            } else {
                $pdo->prepare("UPDATE $tabela_clientes SET last_activity = ?, last_ip = ?, current_channel = ? WHERE id = ?")->execute([$agora, $ip_cliente, $id, $uid]);
            }
        } catch(Exception $e) {
            if ($is_vod) {
                $pdo->prepare("UPDATE $tabela_clientes SET last_activity = ? WHERE id = ?")->execute([$agora, $uid]);
            } else {
                $pdo->prepare("UPDATE $tabela_clientes SET last_activity = ?, last_ip = ? WHERE id = ?")->execute([$agora, $ip_cliente, $uid]);
            }
        }
    }
} catch(Exception $e){}

$link_real = "";

// =======================================================================
// BUSCANDO A FONTE ORIGINAL DO CONTEÚDO NO BANCO DE DADOS
// =======================================================================
try {
    $stmtSrc = $pdo->prepare("SELECT stream_source FROM streams WHERE id = ? LIMIT 1");
    $stmtSrc->execute([$id]);
    $source = $stmtSrc->fetchColumn();
    
    if (empty($source)) {
        $tabela_ep = ($modo_ativo === 'xui') ? 'streams_episodes' : 'series_episodes';
        $stmtSrcS = $pdo->prepare("SELECT stream_source FROM $tabela_ep WHERE stream_id = ? LIMIT 1");
        $stmtSrcS->execute([$id]);
        $source = $stmtSrcS->fetchColumn();
    }

    if (!empty($source)) {
        $source_clean = trim(str_replace(['[', ']', '"', '\\', "'"], '', $source));
        $source_parts = explode(',', $source_clean);
        
        foreach ($source_parts as $candidato) {
            $candidato = trim($candidato);
            // Ignora links locais/loopback
            if (strpos($candidato, 'http') === 0 && strpos($candidato, '127.0.0.1') === false && strpos($candidato, 'localhost') === false) { 
                $link_real = $candidato; 
                break;
            }
        }
    }
} catch(Exception $e){}

// Se não achou no banco, devolve 404 em vez de criar um Link de Fallback infinito
if (empty($link_real)) {
    header("HTTP/1.0 404 Not Found"); 
    die("Stream nao encontrado no servidor.");
}

// =======================================================================
// SEPARAÇÃO INTELIGENTE: FILMES/SÉRIES (VOD) x TV AO VIVO
// =======================================================================
while (ob_get_level()) { ob_end_clean(); } // Limpa qualquer sujeira da tela para o header funcionar

if ($is_vod) {
    // -------------------------------------------------------------
    // FILMES E SÉRIES
    // -------------------------------------------------------------
    $link_real = str_replace([' ', '[', ']', '{', '}'], ['%20', '%5B', '%5D', '%7B', '%7D'], $link_real);

    // VOD precisa permitir algum cache para o SS IPTV conseguir avançar/retroceder
    header("Cache-Control: public, max-age=3600");
    header("Location: " . trim($link_real), true, 302);
    exit;

} else {
    // -------------------------------------------------------------
    // TV AO VIVO
    // -------------------------------------------------------------
    if (!preg_match('/(backblaze|b2|amazonaws|google|drive|telegram|t\.me|api)/i', $link_real)) {
        // Tenta rodar canais ao vivo via HTTP (mais leve para TVs velhas com SS IPTV que falham no SSL)
        $link_real = str_replace('https://', 'http://', $link_real);
    }
    $link_real = str_replace(' ', '%20', $link_real);

    header("X-LiteSpeed-Cache-Control: no-cache");
    header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
    header("Cache-Control: post-check=0, pre-check=0", false);
    header("Pragma: no-cache");
    
    header("Location: " . trim($link_real), true, 302);
    exit;
}
?>
