<?php
// Oculta erros para não quebrar a estrutura JSON retornada aos aplicativos
ini_set('display_errors', 0);
error_reporting(0);

// --- CABEÇALHOS CORS AVANÇADOS (Puxados do script de referência) ---
header('Content-Type: application/json; charset=utf-8');
if (isset($_SERVER["HTTP_ORIGIN"])) {
    header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
    header("Access-Control-Allow-Credentials: true");
} else {
    header('Access-Control-Allow-Origin: *');
}

require_once 'config.php';
$pdo = getConexaoAtiva();
$pdo_int = getConexaoInterna();
$pdo->exec("SET NAMES utf8mb4");

// ====================================================================
// INTELIGÊNCIA ARTIFICIAL: DETECTA SE É XUI ONE OU XTREAM UI
// ====================================================================
$modo_ativo = 'interno';
try { $modo_ativo = $pdo_int->query("SELECT modo_ativo FROM configuracoes LIMIT 1")->fetchColumn() ?: 'interno'; } catch (Exception $e) {}

$tabela_clientes = ($modo_ativo === 'xui') ? '`lines`' : '`users`';
$tabela_categorias = 'stream_categories';
$tabela_series = 'series';
$tabela_episodios = 'series_episodes';
$col_sort = 'sort';

if ($modo_ativo === 'xui') {
    $col_sort = 'episode_num';
    try { $pdo->query("SELECT 1 FROM streams_categories LIMIT 1"); $tabela_categorias = 'streams_categories'; } catch (Exception $e) {}
    try { $pdo->query("SELECT 1 FROM streams_series LIMIT 1"); $tabela_series = 'streams_series'; } catch (Exception $e) {}
    try { $pdo->query("SELECT 1 FROM streams_episodes LIMIT 1"); $tabela_episodios = 'streams_episodes'; } catch (Exception $e) {}
}

$username = $_GET['username'] ?? '';
$password = $_GET['password'] ?? '';
$action   = $_GET['action'] ?? '';
$token    = $_GET['token'] ?? ''; // Suporte para Enigma2

// Identificação do cliente
$ip_cliente = $_SERVER['HTTP_CLIENT_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
$user_agent = trim($_SERVER["HTTP_USER_AGENT"] ?? '');

// ====================================================================
// AUTENTICAÇÃO (Suporte a Usuário/Senha e Enigma2 Token)
// ====================================================================
if (!empty($token)) {
    // Autenticação via MAC/Token (Ex: Aparelhos Enigma2)
    try {
        $stmtEnigma = $pdo->prepare("SELECT * FROM enigma2_devices WHERE token = ? AND public_ip = ? LIMIT 1");
        $stmtEnigma->execute([$token, $ip_cliente]);
        // Aqui você definiria o $user baseado no dispositivo, caso utilize.
    } catch (Exception $e) {}
}

if (empty($username) || empty($password)) {
    die(json_encode(['user_info' => ['auth' => 0]]));
}

$stmtUser = $pdo->prepare("SELECT * FROM $tabela_clientes WHERE username = ? AND password = ? LIMIT 1");
$stmtUser->execute([$username, $password]);
$user = $stmtUser->fetch(PDO::FETCH_ASSOC);

if (!$user || $user['enabled'] == 0) {
    die(json_encode(['user_info' => ['auth' => 0]]));
}

$status = 'Active';
if ($user['exp_date'] != 0 && $user['exp_date'] != null && $user['exp_date'] < time()) {
    $status = 'Expired';
    if (empty($action)) {
        die(json_encode(['user_info' => ['auth' => 0, 'status' => 'Expired']]));
    } else {
        http_response_code(403); die("Conta vencida.");
    }
}

// RASTREADOR: Salva IP durante a navegação
try { 
    try {
        $pdo->prepare("UPDATE $tabela_clientes SET last_activity = ?, last_ip = ? WHERE id = ?")->execute([time(), $ip_cliente, $user['id']]);
    } catch (Exception $e) {
        $pdo->prepare("UPDATE $tabela_clientes SET last_activity = ? WHERE id = ?")->execute([time(), $user['id']]);
    }
} catch (Exception $e){}

// ====================================================================
// INTELIGÊNCIA DE PACOTES (BOUQUETS) DO CLIENTE (CORRIGIDO PARA XUI ONE)
// ====================================================================
$allowed_streams = [];
$allowed_series = [];

if (!empty($user['bouquet'])) {
    // Extrator Bruto para evitar travamento em listas gigantes
    $clean_user_bq = str_replace(['[', ']', '"', "'", ' '], '', $user['bouquet']);
    $bq_ids = explode(',', $clean_user_bq);
    $bq_ids_valid = [];
    foreach($bq_ids as $b) { if(is_numeric($b)) $bq_ids_valid[] = (int)$b; }
    
    if (!empty($bq_ids_valid)) {
        $bq_ids_str = implode(',', $bq_ids_valid);
        
        // 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";
        
        try {
            $stmtBq = $pdo->query("SELECT $col_query FROM bouquets WHERE id IN ($bq_ids_str)");
            while ($bq = $stmtBq->fetch(PDO::FETCH_ASSOC)) {
                // Popula Canais
                if (!empty($bq['bouquet_channels'])) {
                    $clean_ch = str_replace(['[', ']', '"', "'", ' '], '', $bq['bouquet_channels']);
                    $arr_ch = explode(',', $clean_ch);
                    foreach ($arr_ch as $c) {
                        if (is_numeric($c)) $allowed_streams[(int)$c] = true;
                    }
                }
                // Popula Filmes (XUI ONE)
                if ($has_movies_col && !empty($bq['bouquet_movies'])) {
                    $clean_mv = str_replace(['[', ']', '"', "'", ' '], '', $bq['bouquet_movies']);
                    $arr_mv = explode(',', $clean_mv);
                    foreach ($arr_mv as $m) {
                        // Junta com os streams para não alterar a estrutura do código
                        if (is_numeric($m)) $allowed_streams[(int)$m] = true; 
                    }
                }
                // Popula Séries
                if (!empty($bq['bouquet_series'])) {
                    $clean_sr = str_replace(['[', ']', '"', "'", ' '], '', $bq['bouquet_series']);
                    $arr_sr = explode(',', $clean_sr);
                    foreach ($arr_sr as $s) {
                        if (is_numeric($s)) $allowed_series[(int)$s] = true;
                    }
                }
            }
        } catch(Exception $e){}
    }
}
// ====================================================================

function extrair_id_categoria($raw_cat) {
    if (empty($raw_cat)) return "0";
    if (strpos($raw_cat, '[') !== false) {
        $arr = json_decode($raw_cat, true);
        if (is_array($arr) && isset($arr[0])) return (string)$arr[0];
        preg_match('/\d+/', $raw_cat, $matches);
        return $matches[0] ?? "0";
    }
    return (string)$raw_cat;
}

// ====================================================================
// ROTEAMENTO DA API (ENDPOINTS)
// ====================================================================
switch ($action) {

    case 'get_live_categories':
    case 'get_vod_categories':
    case 'get_series_categories':
        $mapeamento_categorias = [];
        if ($action == 'get_live_categories') {
             $stmtMap = $pdo->query("SELECT id, category_id FROM streams WHERE type IN (1, 3, 4)");
        } elseif ($action == 'get_vod_categories') {
             $stmtMap = $pdo->query("SELECT id, category_id FROM streams WHERE type = 2");
        } else {
             $stmtMap = $pdo->query("SELECT id, category_id FROM $tabela_series");
        }
        
        while ($row = $stmtMap->fetch(PDO::FETCH_ASSOC)) {
            // TRAVA DE BOUQUET PARA MAPEAR CATEGORIAS
            if ($action != 'get_series_categories') {
                 if (!empty($user['bouquet']) && !isset($allowed_streams[$row['id']])) { continue; }
            } else {
                 if (!empty($user['bouquet']) && empty($allowed_series)) { continue; }
            }

            $cat_limpo = extrair_id_categoria($row['category_id']);
            if ($cat_limpo != "0") $mapeamento_categorias[$cat_limpo] = true;
        }

        $ordem_coluna = "id ASC";
        try {
            $pdo->query("SELECT cat_order FROM $tabela_categorias LIMIT 1");
            $ordem_coluna = "cat_order ASC";
        } catch(Exception $e){
            try {
                $pdo->query("SELECT `order` FROM $tabela_categorias LIMIT 1");
                $ordem_coluna = "`order` ASC";
            } catch(Exception $e2){}
        }

        $todas_cats = [];
        if ($action == 'get_series_categories') {
            try { 
                $ordem_series = "id ASC";
                try { $pdo->query("SELECT cat_order FROM series_categories LIMIT 1"); $ordem_series = "cat_order ASC"; } catch(Exception $ex){}
                $todas_cats = $pdo->query("SELECT * FROM series_categories ORDER BY $ordem_series")->fetchAll(PDO::FETCH_ASSOC); 
            } catch(Exception $e) {}
        }
        if (empty($todas_cats)) {
            try { $todas_cats = $pdo->query("SELECT * FROM $tabela_categorias ORDER BY $ordem_coluna")->fetchAll(PDO::FETCH_ASSOC); } catch(Exception $e) {}
        }
        
        $categorias_finais = [];
        foreach ($todas_cats as $c) {
            $id_str = (string)($c['id'] ?? '0');
            if (isset($mapeamento_categorias[$id_str])) {
                $categorias_finais[] = [
                    "category_id" => $id_str,
                    "category_name" => str_replace('"', '', $c['category_name'] ?? 'Sem Nome'),
                    "parent_id" => isset($c['parent_id']) ? (int)$c['parent_id'] : 0
                ];
            }
        }
        echo json_encode($categorias_finais);
        break;

    case 'get_live_streams':
        $cat_id = $_GET['category_id'] ?? null;
        $stmt = $pdo->query("SELECT * FROM streams WHERE type IN (1, 3, 4)");
        $streams = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $resultado = [];
        $num = 1;
        foreach ($streams as $s) {
            if (!empty($user['bouquet']) && !isset($allowed_streams[$s['id']])) { continue; }

            $cat_real = extrair_id_categoria($s['category_id'] ?? "0");
            if ($cat_id && $cat_real !== (string)$cat_id) continue;

            $resultado[] = [
                "num" => $num++, 
                "name" => str_replace('"', '', $s['stream_display_name'] ?? 'Canal'),
                "stream_type" => "live", 
                "stream_id" => (int)$s['id'],
                "stream_icon" => $s['stream_icon'] ?? '', 
                "epg_channel_id" => $s['custom_sid'] ?? "", 
                "added" => $s['added'] ?? "0", 
                "category_id" => $cat_real,
                "custom_sid" => $s['custom_sid'] ?? "", 
                "tv_archive" => 0, 
                "direct_source" => "", 
                "tv_archive_duration" => 0
            ];
        }
        echo json_encode($resultado);
        break;

    case 'get_vod_streams':
        $cat_id = $_GET['category_id'] ?? null;
        $stmt = $pdo->query("SELECT * FROM streams WHERE type = 2");
        $streams = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $resultado = [];
        $num = 1;
        foreach ($streams as $s) {
            if (!empty($user['bouquet']) && !isset($allowed_streams[$s['id']])) { continue; }

            $cat_real = extrair_id_categoria($s['category_id'] ?? "0");
            if ($cat_id && $cat_real !== (string)$cat_id) continue;

            $ext = isset($s['target_container']) ? trim(str_replace(['[', ']', '"'], '', $s['target_container'])) : "mp4";
            if (empty($ext)) $ext = "mp4";

            $plot = "";
            if (!empty($s['plot'])) $plot = $s['plot'];
            elseif (!empty($s['overview'])) $plot = $s['overview'];
            elseif (!empty($s['notes'])) $plot = $s['notes'];
            if (empty(trim($plot))) $plot = "Nenhuma sinopse disponível.";

            $resultado[] = [
                "num" => $num++, 
                "name" => str_replace('"', '', $s['stream_display_name'] ?? 'Filme'),
                "stream_type" => "movie", 
                "stream_id" => (int)$s['id'], 
                "stream_icon" => $s['stream_icon'] ?? '',
                "rating" => "5", 
                "rating_5based" => "2.5", 
                "added" => $s['added'] ?? "0",
                "category_id" => $cat_real, 
                "container_extension" => $ext, 
                "custom_sid" => null,
                "direct_source" => "", 
                "plot" => $plot
            ];
        }
        echo json_encode($resultado);
        break;

    case 'get_vod_info':
        $vod_id = $_GET['vod_id'] ?? 0;
        
        if (!empty($user['bouquet']) && !isset($allowed_streams[$vod_id])) { 
            echo json_encode([]); 
            break; 
        }

        $stmtVod = $pdo->prepare("SELECT * FROM streams WHERE id = ? AND type = 2");
        $stmtVod->execute([$vod_id]);
        $info = $stmtVod->fetch(PDO::FETCH_ASSOC);

        if (!$info) { echo json_encode([]); break; }

        $cover = $info['stream_icon'] ?? '';
        $name = str_replace('"', '', $info['stream_display_name'] ?? 'Filme');
        $ext = trim(str_replace(['[', ']', '"'], '', $info['target_container'] ?? 'mp4')) ?: "mp4";
        $cat_real = extrair_id_categoria($info['category_id'] ?? "0");

        $plot = "";
        if (!empty($info['plot'])) $plot = $info['plot'];
        elseif (!empty($info['overview'])) $plot = $info['overview'];
        elseif (!empty($info['notes'])) $plot = $info['notes'];
        if (empty(trim($plot))) $plot = "Nenhuma sinopse disponível para este título.";

        $resultado = [
            "info" => [
                "kinopoisk_url" => "", "tmdb_id" => "", "name" => $name, "o_name" => $name,
                "cover_big" => $cover, "movie_image" => $cover, "releasedate" => "",
                "episode_run_time" => "0", "youtube_trailer" => "", "director" => "Não informado",
                "actors" => "Não informado", "cast" => "Não informado", "description" => $plot,
                "plot" => $plot, "age" => "", "mpaa_rating" => "", "rating_count_kinopoisk" => 0,
                "country" => "", "genre" => "Diversos", "backdrop_path" => [$cover],
                "duration_secs" => 0, "duration" => "00:00:00", "video" => [], "audio" => [],
                "bitrate" => 0, "rating" => "5"
            ],
            "movie_data" => [
                "stream_id" => (int)$vod_id, "name" => $name, "title" => $name,
                "added" => $info['added'] ?? "0", "category_id" => $cat_real,
                "container_extension" => $ext, "custom_sid" => "", "direct_source" => ""
            ]
        ];
        echo json_encode($resultado);
        break;

    case 'get_series':
        $cat_id = $_GET['category_id'] ?? null;
        $stmt = $pdo->query("SELECT * FROM $tabela_series");
        $series = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $resultado = [];
        $num = 1;
        foreach ($series as $s) {
            if (!empty($user['bouquet']) && empty($allowed_series)) { continue; }

            $cat_real = extrair_id_categoria($s['category_id'] ?? "0");
            if ($cat_id && $cat_real !== (string)$cat_id) continue;

            $plot = "";
            if (!empty($s['plot'])) $plot = $s['plot'];
            elseif (!empty($s['overview'])) $plot = $s['overview'];
            if (empty(trim($plot))) $plot = "Nenhuma sinopse disponível.";

            $resultado[] = [
                "num" => $num++, 
                "name" => str_replace('"', '', $s['title'] ?? 'Serie'),
                "series_id" => (int)$s['id'], 
                "cover" => $s['cover'] ?? '',
                "plot" => $plot, 
                "cast" => "Não informado", 
                "director" => "Não informado", 
                "genre" => "Diversos",
                "releaseDate" => "", 
                "last_modified" => $s['last_modified'] ?? "0",
                "rating" => "5", 
                "rating_5based" => "2.5", 
                "backdrop_path" => [$s['cover'] ?? ''], 
                "youtube_trailer" => "", 
                "episode_run_time" => "0", 
                "category_id" => $cat_real
            ];
        }
        echo json_encode($resultado);
        break;

    case 'get_series_info':
        $series_id = $_GET['series_id'] ?? 0;
        
        if (!empty($user['bouquet']) && empty($allowed_series)) { 
            echo json_encode([]); 
            break; 
        }

        $stmtInfo = $pdo->prepare("SELECT * FROM $tabela_series WHERE id = ?");
        $stmtInfo->execute([$series_id]);
        $info = $stmtInfo->fetch(PDO::FETCH_ASSOC);

        if (!$info) { echo json_encode([]); break; }

        $stmtEps = $pdo->prepare("SELECT se.*, s.* FROM $tabela_episodios se LEFT JOIN streams s ON se.stream_id = s.id WHERE se.series_id = ? ORDER BY se.season_num ASC, se.{$col_sort} ASC");
        $stmtEps->execute([$series_id]);
        $episodes_raw = $stmtEps->fetchAll(PDO::FETCH_ASSOC);

        $episodes_formatted = [];
        $seasons_array = [];
        $seasons_tracker = [];

        foreach ($episodes_raw as $ep) {
            $s_num = (int)($ep['season_num'] ?? 1);
            if (!isset($episodes_formatted[$s_num])) { $episodes_formatted[$s_num] = []; }
            if (!in_array($s_num, $seasons_tracker)) {
                $seasons_tracker[] = $s_num;
                $seasons_array[] = ["season_number" => $s_num];
            }

            $ext = trim(str_replace(['[', ']', '"'], '', $ep['target_container'] ?? 'mp4')) ?: "mp4";

            $episodes_formatted[$s_num][] = [
                "id" => (string)$ep['stream_id'],
                "episode_num" => (string)($ep[$col_sort] ?? "1"),
                "title" => str_replace('"', '', $ep['stream_display_name'] ?? 'Episodio'),
                "container_extension" => $ext,
                "info" => ["plot" => "", "duration" => "", "movie_image" => "", "bitrate" => ""],
                "custom_sid" => null, 
                "added" => $ep['added'] ?? "0", 
                "season" => $s_num, 
                "direct_source" => ""
            ];
        }

        $plot = "";
        if (!empty($info['plot'])) $plot = $info['plot'];
        elseif (!empty($info['overview'])) $plot = $info['overview'];
        if (empty(trim($plot))) $plot = "Nenhuma sinopse disponível para esta série.";

        $cat_real = extrair_id_categoria($info['category_id'] ?? "0");
        $resultado = [
            "seasons" => $seasons_array,
            "info" => [
                "name" => str_replace('"', '', $info['title'] ?? 'Serie'),
                "cover" => $info['cover'] ?? '',
                "plot" => $plot,
                "cast" => "Não informado",
                "director" => "Não informado",
                "genre" => "Diversos",
                "releaseDate" => "",
                "last_modified" => $info['last_modified'] ?? "0",
                "rating" => "5",
                "rating_5based" => "2.5",
                "category_id" => $cat_real,
                "backdrop_path" => [$info['cover'] ?? ''], 
                "youtube_trailer" => "", 
                "episode_run_time" => "0"
            ],
            "episodes" => (object)$episodes_formatted 
        ];
        echo json_encode($resultado);
        break;

    // ====================================================================
    // ENDPOINTS DE EPG (ADICIONADOS DO NOVO CÓDIGO)
    // ====================================================================
    case 'get_short_epg':
        $stream_id = (int)($_GET['stream_id'] ?? 0);
        $limit = (int)($_GET['limit'] ?? 4);
        $resultado = ["epg_listings" => []];
        
        $stmtSid = $pdo->prepare("SELECT custom_sid FROM streams WHERE id = ? LIMIT 1");
        $stmtSid->execute([$stream_id]);
        $sid_info = $stmtSid->fetch(PDO::FETCH_ASSOC);
        
        if ($sid_info && !empty($sid_info['custom_sid'])) {
            try {
                $custom_sid = $sid_info['custom_sid'];
                $stmtEpg = $pdo->prepare("SELECT * FROM epg_data WHERE channel_id = ? AND start >= NOW() ORDER BY start ASC LIMIT ?");
                $stmtEpg->bindValue(1, $custom_sid);
                $stmtEpg->bindValue(2, $limit, PDO::PARAM_INT);
                $stmtEpg->execute();
                
                $epg_data = $stmtEpg->fetchAll(PDO::FETCH_ASSOC);
                foreach ($epg_data as $epg) {
                    $resultado["epg_listings"][] = [
                        "id" => $epg['id'],
                        "epg_id" => $epg['channel_id'],
                        "title" => base64_encode($epg['title'] ?? ''),
                        "lang" => $epg['lang'] ?? "",
                        "start" => $epg['start'],
                        "end" => $epg['end'],
                        "description" => base64_encode($epg['description'] ?? ''),
                        "channel_id" => $epg['channel_id'],
                        "start_timestamp" => strtotime($epg['start']),
                        "stop_timestamp" => strtotime($epg['end'])
                    ];
                }
            } catch (Exception $e) {}
        }
        echo json_encode($resultado);
        break;

    case 'get_simple_data_table':
        $stream_id = (int)($_GET['stream_id'] ?? 0);
        $resultado = ["epg_listings" => []];
        
        $stmtSid = $pdo->prepare("SELECT custom_sid FROM streams WHERE id = ? LIMIT 1");
        $stmtSid->execute([$stream_id]);
        $sid_info = $stmtSid->fetch(PDO::FETCH_ASSOC);
        
        if ($sid_info && !empty($sid_info['custom_sid'])) {
            try {
                $custom_sid = $sid_info['custom_sid'];
                $stmtEpg = $pdo->prepare("SELECT * FROM epg_data WHERE channel_id = ? ORDER BY start ASC LIMIT 100");
                $stmtEpg->execute([$custom_sid]);
                
                $epg_data = $stmtEpg->fetchAll(PDO::FETCH_ASSOC);
                foreach ($epg_data as $epg) {
                    $resultado["epg_listings"][] = [
                        "id" => $epg['id'],
                        "epg_id" => $epg['channel_id'],
                        "title" => base64_encode($epg['title'] ?? ''),
                        "lang" => $epg['lang'] ?? "",
                        "start" => $epg['start'],
                        "end" => $epg['end'],
                        "description" => base64_encode($epg['description'] ?? ''),
                        "channel_id" => $epg['channel_id'],
                        "start_timestamp" => strtotime($epg['start']),
                        "stop_timestamp" => strtotime($epg['end']),
                        "has_archive" => 0
                    ];
                }
            } catch (Exception $e) {}
        }
        echo json_encode($resultado);
        break;

    default:
        $server_info = [
            "xui" => true,
            "version" => "1.5.13",
            "revision" => null,
            "url" => $_SERVER['HTTP_HOST'],
            "port" => $_SERVER['SERVER_PORT'] ?? "80",
            "https_port" => "443",
            "server_protocol" => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http",
            "rtmp_port" => "8880",
            "timestamp_now" => time(),
            "time_now" => date('Y-m-d H:i:s'),
            "timezone" => "Europe/London"
        ];

        $telas_ativas = (!empty($user['last_activity']) && (time() - (int)$user['last_activity']) <= 60) ? 1 : 0;
        
        $user_info = [
            "username" => $user['username'], 
            "password" => $user['password'], 
            "message" => "Welcome to XUI.one", 
            "auth" => 1, 
            "status" => $status,
            "exp_date" => (string)$user['exp_date'], 
            "is_trial" => "0", 
            "active_cons" => (string)$telas_ativas, 
            "created_at" => (string)(isset($user['created_at']) ? $user['created_at'] : time()),
            "max_connections" => (string)($user['max_connections'] ?? "1"), 
            "allowed_output_formats" => []
        ];

        echo json_encode(["user_info" => $user_info, "server_info" => $server_info]);
        break;
}
?>
