<?php
require_once 'session_config.php';
session_start();
require_once 'auth.php';

// 处理登出请求
if (isset($_GET['action']) && $_GET['action'] === 'logout') {
    $_SESSION = array();
    if (isset($_COOKIE[session_name()])) {
        setcookie(session_name(), '', time() - 3600, '/');
    }
    session_destroy();
    $redirect_url = strtok($_SERVER['REQUEST_URI'], '?');
    header('Location: ' . $redirect_url);
    exit;
}

// 只在收到SSO回调时验证
if (isset($_GET['sso']) && isset($_GET['sig'])) {
    if (!verify_discourse_sso()) {
        $_SESSION['login_error'] = '登录失败，请重试';
    }
}

$user = $_SESSION['user'] ?? null;
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>二次元论坛2026拜年纪</title>
    <!-- 引入 Tailwind CSS -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <!-- 引入额外的 CSS 文件 -->
    <link rel="stylesheet" type="text/css" href="https://wbot.ecylt.top/css/wtf.css"/>
    <!-- 字体 -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/lxgw-wenkai-screen-webfont/1.7.0/lxgwwenkaiscreen.min.css" rel="stylesheet">
    <!-- ICON -->
    <link rel="icon" type="image/png" href="https://api.ecylt.top/images/favicon.ico">
    <!--引入 JQ 库-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <!-- 播放器相关库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.6.2/flv.min.js"></script>
    <style>
        .container {
            max-width: 1600px;
            margin: 0 auto;
            padding: 20px;
        }
        body {
            font-family: LXGW WenKai Screen, serif;
        }
        .user-panel {
            position: fixed;
            top: 1rem;
            right: 1rem;
            display: flex;
            align-items: center;
            gap: 0.5rem;
            background: rgba(255, 255, 255, 0.9);
            padding: 0.5rem 1rem;
            border-radius: 0.5rem;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            z-index: 9999;
        }
        .user-avatar {
            width: 2.5rem;
            height: 2.5rem;
            border-radius: 50%;
            object-fit: cover;
        }
        .user-info {
            display: flex;
            flex-direction: column;
        }
        .user-name {
            font-weight: 600;
            color: #333;
        }
        .user-status {
            font-size: 0.8rem;
            color: #666;
        }
        .login-required {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background: rgba(0, 0, 0, 0.8);
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            z-index: 9999;
        }
        .login-message {
            background: white;
            padding: 2rem;
            border-radius: 0.5rem;
            text-align: center;
            max-width: 400px;
        }
        .logout-btn {
            background: #dc3545;
            color: white;
            padding: 0.25rem 0.75rem;
            border-radius: 0.25rem;
            font-size: 0.875rem;
            margin-left: 0.5rem;
            transition: background-color 0.2s;
        }
        .logout-btn:hover {
            background: #c82333;
            text-decoration: none;
        }
        .login-dialog {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 2rem;
            border-radius: 0.5rem;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            max-width: 400px;
            width: 90%;
            z-index: 10000;
        }
        .dialog-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.5);
            z-index: 9999;
        }
        .error-message {
            color: #dc3545;
            margin-bottom: 1rem;
            font-size: 0.875rem;
        }
        
        /* 直播间主布局 - 电脑端 */
        .live-wrapper {
            display: flex;
            flex-direction: row;
            gap: 1rem;
            max-width: 1600px;
            margin: 0 auto;
            padding: 0 1rem;
        }
        
        /* 直播视频区域 */
        .video-section {
            flex: 1;
            min-width: 0;
        }
        
        .video-container {
            width: 100%;
            background: #000;
            aspect-ratio: 16/9;
            border-radius: 0.5rem;
            overflow: hidden;
        }
        
        #video_player {
            width: 100%;
            height: 100%;
            background: #000;
        }
        
        /* 聊天区域 */
        .chat-section {
            width: 380px;
            flex-shrink: 0;
        }
        
        .chat-container {
            width: 100%;
            height: calc(100vh - 180px);
            min-height: 500px;
            max-height: 700px;
            border: 1px solid #e5e7eb;
            border-radius: 0.5rem;
            overflow: hidden;
            background: #fff;
        }
        
        .chat-container iframe {
            width: 100%;
            height: 100%;
            border: none;
        }
        
        /* 手机端响应式布局 */
        @media (max-width: 1024px) {
            .live-wrapper {
                flex-direction: column;
                padding: 0 0.5rem;
            }
            
            .video-section {
                width: 100%;
            }
            
            .chat-section {
                width: 100%;
            }
            
            .chat-container {
                height: 400px;
                min-height: 350px;
                max-height: 500px;
            }
        }
        
        /* 小屏手机优化 */
        @media (max-width: 640px) {
            .container {
                padding: 10px;
            }
            
            .live-wrapper {
                gap: 0.75rem;
            }
            
            .chat-container {
                height: 350px;
                min-height: 300px;
            }
            
            h1.page-title {
                font-size: 1.5rem !important;
                margin: 0.5rem 0 1rem 0 !important;
            }
            
            .user-panel {
                top: 0.5rem;
                right: 0.5rem;
                padding: 0.25rem 0.5rem;
                font-size: 0.875rem;
            }
            
            .user-avatar {
                width: 2rem;
                height: 2rem;
            }
        }
        
        /* 横屏手机优化 */
        @media (max-width: 900px) and (orientation: landscape) {
            .live-wrapper {
                flex-direction: row;
            }
            
            .video-section {
                flex: 1;
            }
            
            .chat-section {
                width: 280px;
            }
            
            .chat-container {
                height: calc(100vh - 120px);
                min-height: 250px;
            }
            
            h1.page-title {
                font-size: 1.25rem !important;
                margin: 0.25rem 0 0.5rem 0 !important;
            }
        }
    </style>
    <script>
    !function(p){"use strict";!function(t){var s=window,e=document,i=p,c="".concat("https:"===e.location.protocol?"https://":"http://","sdk.51.la/js-sdk-pro.min.js"),n=e.createElement("script"),r=e.getElementsByTagName("script")[0];n.type="text/javascript",n.setAttribute("charset","UTF-8"),n.async=!0,n.src=c,n.id="LA_COLLECT",i.d=n;var o=function(){s.LA.ids.push(i)};s.LA?s.LA.ids&&o():(s.LA=p,s.LA.ids=[],o()),r.parentNode.insertBefore(n,r)}()}({id:"K6uUH7IfMpveoKIF",ck:"K6uUH7IfMpveoKIF",autoTrack:true,hashMode:true});
    </script>
    <script type="text/javascript">
    (function(c,l,a,r,i,t,y){
        c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
        t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
        y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
    })(window, document, "clarity", "script", "puc1askam1");
    </script>
</head>
<body class="bg-gray-100">
    <?php if (!$user): ?>
    <div class="dialog-overlay">
        <div class="login-dialog">
            <h2 class="text-2xl mb-4">需要登录</h2>
            <?php if (isset($_SESSION['login_error'])): ?>
            <div class="error-message">
                <?php echo htmlspecialchars($_SESSION['login_error']); ?>
                <?php unset($_SESSION['login_error']); ?>
            </div>
            <?php endif; ?>
            <p class="mb-4">请登录后继续访问</p>
            <div class="flex justify-center gap-4">
                <a href="<?php echo get_login_url(); ?>" class="bg-blue-500 text-white px-6 py-2 rounded hover:bg-blue-600 transition-colors">
                    立即登录
                </a>
                <button onclick="window.location.href='https://www.ecylt.top/'" class="bg-gray-500 text-white px-6 py-2 rounded hover:bg-gray-600 transition-colors">
                    返回论坛
                </button>
            </div>
        </div>
    </div>
    <?php else: ?>
    <div class="user-panel">
        <img src="<?php echo htmlspecialchars($user['avatar_url'] ?? 'https://api.ecylt.top/images/icon.jpg'); ?>" 
             alt="Avatar" 
             class="user-avatar">
        <div class="user-info">
            <span class="user-name"><?php echo htmlspecialchars($user['username']); ?></span>
            <span class="user-status">
                <?php echo $user['admin'] ? '管理员' : ($user['moderator'] ? '版主' : 'e友'); ?>
            </span>
        </div>
        <a href="?action=logout" class="logout-btn">退出</a>
    </div>

    <!--引入一坨（雪花）-->
    <script type="text/javascript">
        (function($){
            $.fn.snow = function(options){
                var $flake = $('<div id="snowbox" />').css({
                    'position': 'absolute',
                    'z-index':'9998', 
                    'top': '-50px'
                }).html('&#10052;'),
                documentHeight = $(document).height(),
                documentWidth = $(document).width(),
                defaults = {
                    minSize: 5,
                    maxSize: 20,
                    newOn: 500,
                    flakeColor: "#00bfff"
                },
                options = $.extend({}, defaults, options);

                var interval = setInterval( function(){
                    var startPositionLeft = Math.random() * documentWidth - 100,
                        startOpacity = 0.5 + Math.random(),
                        sizeFlake = options.minSize + Math.random() * options.maxSize,
                        endPositionTop = documentHeight - 200,
                        endPositionLeft = startPositionLeft - 500 + Math.random() * 500,
                        durationFall = documentHeight * 10 + Math.random() * 5000;
                    
                    $flake.clone().appendTo('body').css({
                        left: startPositionLeft,
                        opacity: startOpacity,
                        'font-size': sizeFlake,
                        color: options.flakeColor
                    }).animate({
                        top: endPositionTop,
                        left: endPositionLeft,
                        opacity: 0.2
                    }, durationFall, 'linear', function(){
                        $(this).remove();
                    });
                }, options.newOn);
            };
        })(jQuery);

        $(function(){
            $.fn.snow({ 
                minSize: 10,
                maxSize: 25,
                newOn: 450
            });
        });
    </script>

    <div class="container mx-auto p-4">
        <h1 class="text-4xl font-bold text-center my-4 page-title">二次元论坛2026拜年纪</h1>
        
        <!-- 直播间主布局：电脑端左视频右聊天，手机端上视频下聊天 -->
        <div class="live-wrapper">
            <!-- 直播视频区域 -->
            <div class="video-section">
                <div class="video-container">
                    <video id="video_player" controls autoplay muted></video>
                </div>
            </div>
            
            <!-- 聊天区域 -->
            <div class="chat-section">
                <div class="chat-container">
                    <iframe src="https://www.ecylt.top/chat/c/general/2"
                            allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
                            allowfullscreen>
                    </iframe>
                </div>
            </div>
        </div>
    </div>

    <script type="text/javascript">
        /**
         * 直播流本地缓存管理器
         * 使用 localStorage 和 IndexedDB 实现用户端缓存
         */
        class StreamLocalCache {
            constructor() {
                this.dbName = 'LiveStreamCache';
                this.dbVersion = 1;
                this.storeName = 'streamData';
                this.db = null;
                this.cacheConfig = {
                    statusTTL: 10 * 1000,       // 流状态缓存10秒
                    configTTL: 60 * 1000,       // 配置缓存1分钟
                    maxStorageSize: 10 * 1024 * 1024  // 最大10MB
                };
            }
            
            /**
             * 初始化 IndexedDB
             */
            async initDB() {
                return new Promise((resolve, reject) => {
                    const request = indexedDB.open(this.dbName, this.dbVersion);
                    
                    request.onerror = () => reject(request.error);
                    request.onsuccess = () => {
                        this.db = request.result;
                        resolve(this.db);
                    };
                    
                    request.onupgradeneeded = (event) => {
                        const db = event.target.result;
                        if (!db.objectStoreNames.contains(this.storeName)) {
                            db.createObjectStore(this.storeName, { keyPath: 'key' });
                        }
                    };
                });
            }
            
            /**
             * 从 localStorage 获取缓存
             */
            getLocal(key, maxAge = 60000) {
                try {
                    const item = localStorage.getItem(`stream_${key}`);
                    if (!item) return null;
                    
                    const { data, timestamp } = JSON.parse(item);
                    if (Date.now() - timestamp > maxAge) {
                        localStorage.removeItem(`stream_${key}`);
                        return null;
                    }
                    return data;
                } catch (e) {
                    return null;
                }
            }
            
            /**
             * 保存到 localStorage
             */
            setLocal(key, data) {
                try {
                    localStorage.setItem(`stream_${key}`, JSON.stringify({
                        data,
                        timestamp: Date.now()
                    }));
                    return true;
                } catch (e) {
                    // 存储满了，清理旧数据
                    this.cleanupLocal();
                    return false;
                }
            }
            
            /**
             * 清理 localStorage 中的过期数据
             */
            cleanupLocal() {
                const keysToRemove = [];
                for (let i = 0; i < localStorage.length; i++) {
                    const key = localStorage.key(i);
                    if (key && key.startsWith('stream_')) {
                        try {
                            const item = JSON.parse(localStorage.getItem(key));
                            if (Date.now() - item.timestamp > this.cacheConfig.configTTL * 10) {
                                keysToRemove.push(key);
                            }
                        } catch (e) {
                            keysToRemove.push(key);
                        }
                    }
                }
                keysToRemove.forEach(key => localStorage.removeItem(key));
            }
            
            /**
             * 从 IndexedDB 获取缓存
             */
            async getDB(key, maxAge = 60000) {
                if (!this.db) await this.initDB();
                
                return new Promise((resolve) => {
                    try {
                        const transaction = this.db.transaction([this.storeName], 'readonly');
                        const store = transaction.objectStore(this.storeName);
                        const request = store.get(key);
                        
                        request.onsuccess = () => {
                            const result = request.result;
                            if (!result) {
                                resolve(null);
                                return;
                            }
                            
                            if (Date.now() - result.timestamp > maxAge) {
                                this.deleteDB(key);
                                resolve(null);
                                return;
                            }
                            
                            resolve(result.data);
                        };
                        
                        request.onerror = () => resolve(null);
                    } catch (e) {
                        resolve(null);
                    }
                });
            }
            
            /**
             * 保存到 IndexedDB
             */
            async setDB(key, data) {
                if (!this.db) await this.initDB();
                
                return new Promise((resolve) => {
                    try {
                        const transaction = this.db.transaction([this.storeName], 'readwrite');
                        const store = transaction.objectStore(this.storeName);
                        store.put({ key, data, timestamp: Date.now() });
                        
                        transaction.oncomplete = () => resolve(true);
                        transaction.onerror = () => resolve(false);
                    } catch (e) {
                        resolve(false);
                    }
                });
            }
            
            /**
             * 从 IndexedDB 删除
             */
            async deleteDB(key) {
                if (!this.db) return;
                
                try {
                    const transaction = this.db.transaction([this.storeName], 'readwrite');
                    const store = transaction.objectStore(this.storeName);
                    store.delete(key);
                } catch (e) {
                    console.warn('删除缓存失败:', e);
                }
            }
            
            /**
             * 获取流状态（带缓存）
             */
            async getStreamStatus(url) {
                const cacheKey = 'status_' + this.hashCode(url);
                
                // 先检查本地缓存
                let cached = this.getLocal(cacheKey, this.cacheConfig.statusTTL);
                if (cached) {
                    console.log('使用本地缓存的流状态');
                    return cached;
                }
                
                // 检查 IndexedDB 缓存
                cached = await this.getDB(cacheKey, this.cacheConfig.statusTTL);
                if (cached) {
                    console.log('使用 IndexedDB 缓存的流状态');
                    return cached;
                }
                
                // 直接检测流状态（不需要服务器代理）
                const status = await this.probeStreamDirectly(url);
                
                // 缓存结果
                this.setLocal(cacheKey, status);
                await this.setDB(cacheKey, status);
                
                return status;
            }
            
            /**
             * 直接探测流状态
             */
            async probeStreamDirectly(url) {
                try {
                    const controller = new AbortController();
                    const timeoutId = setTimeout(() => controller.abort(), 5000);
                    
                    const response = await fetch(url, {
                        method: 'HEAD',
                        mode: 'cors',
                        signal: controller.signal
                    });
                    
                    clearTimeout(timeoutId);
                    
                    return {
                        available: response.ok,
                        status: response.status,
                        contentType: response.headers.get('content-type'),
                        checkedAt: Date.now()
                    };
                } catch (e) {
                    // 网络错误或跨域，假设流可用（让播放器尝试）
                    return {
                        available: true,
                        status: 0,
                        contentType: null,
                        checkedAt: Date.now(),
                        assumed: true
                    };
                }
            }
            
            /**
             * 获取播放器配置（带缓存）
             */
            getPlayerConfig() {
                const cacheKey = 'player_config';
                let config = this.getLocal(cacheKey, this.cacheConfig.configTTL);
                
                if (!config) {
                    // 默认配置
                    config = {
                        flvUrl: 'https://ecylt-live-2026bnj-cn-wdn.ecylt.com:485/livestream.flv',
                        hlsUrl: 'https://ecylt-live-2026bnj-cn-wdn.ecylt.com:485/livestream.m3u8',
                        bufferTime: 3,
                        maxBufferTime: 10,
                        reconnectInterval: 3000,
                        maxReconnectAttempts: 5,
                        segmentTTL: 30000
                    };
                    this.setLocal(cacheKey, config);
                }
                
                return config;
            }
            
            /**
             * 保存播放器配置
             */
            savePlayerConfig(config) {
                this.setLocal('player_config', config);
            }
            
            /**
             * 保存播放状态（用于快速恢复）
             */
            savePlaybackState(state) {
                this.setLocal('playback_state', {
                    lastPlayTime: Date.now(),
                    ...state
                });
            }
            
            /**
             * 获取上次播放状态
             */
            getPlaybackState() {
                return this.getLocal('playback_state', 5 * 60 * 1000); // 5分钟内有效
            }
            
            /**
             * 简单哈希函数
             */
            hashCode(str) {
                let hash = 0;
                for (let i = 0; i < str.length; i++) {
                    const char = str.charCodeAt(i);
                    hash = ((hash << 5) - hash) + char;
                    hash = hash & hash;
                }
                return hash.toString(36);
            }
        }
        
        /**
         * 直播流播放器管理器
         * 支持本地缓存预加载、自动重连、流状态检测
         */
        class LiveStreamPlayer {
            constructor(videoElementId) {
                this.videoElement = document.getElementById(videoElementId);
                this.flvPlayer = null;
                this.reconnectAttempts = 0;
                this.statusCheckInterval = null;
                this.isDestroyed = false;
                this.lastBufferCheck = 0;
                this.cache = new StreamLocalCache();
                this.swRegistration = null;
                
                // 从本地缓存加载配置
                this.config = this.cache.getPlayerConfig();
                this.maxReconnectAttempts = this.config.maxReconnectAttempts;
                this.reconnectInterval = this.config.reconnectInterval;
            }
            
            /**
             * 注册 Service Worker
             */
            async registerServiceWorker() {
                if ('serviceWorker' in navigator) {
                    try {
                        this.swRegistration = await navigator.serviceWorker.register('stream-sw.js');
                        console.log('Service Worker 注册成功');
                        
                        // 监听来自 SW 的消息
                        navigator.serviceWorker.addEventListener('message', (event) => {
                            console.log('收到 SW 消息:', event.data);
                        });
                        
                        return true;
                    } catch (error) {
                        console.warn('Service Worker 注册失败:', error);
                        return false;
                    }
                }
                return false;
            }
            
            /**
             * 与 Service Worker 通信
             */
            async sendToSW(type, data = {}) {
                if (!this.swRegistration || !navigator.serviceWorker.controller) {
                    return null;
                }
                
                return new Promise((resolve) => {
                    const messageChannel = new MessageChannel();
                    messageChannel.port1.onmessage = (event) => {
                        resolve(event.data);
                    };
                    
                    navigator.serviceWorker.controller.postMessage(
                        { type, data },
                        [messageChannel.port2]
                    );
                    
                    // 超时处理
                    setTimeout(() => resolve(null), 3000);
                });
            }
            
            /**
             * 从本地缓存预加载配置
             */
            async preload() {
                // 注册 Service Worker
                await this.registerServiceWorker();
                
                // 初始化 IndexedDB
                await this.cache.initDB();
                
                // 检查上次播放状态
                const lastState = this.cache.getPlaybackState();
                if (lastState) {
                    console.log('恢复上次播放状态');
                }
                
                // 检查流状态（使用本地缓存）
                const streamStatus = await this.cache.getStreamStatus(this.config.flvUrl);
                console.log('流状态:', streamStatus);
                
                return streamStatus.available;
            }
            
            /**
             * 创建 FLV 播放器实例
             */
            createPlayer() {
                if (this.flvPlayer) {
                    this.destroyPlayer();
                }
                
                this.flvPlayer = flvjs.createPlayer({
                    type: 'flv',
                    url: this.config.flvUrl,
                    isLive: true,
                    hasAudio: true,
                    hasVideo: true,
                    cors: true,
                    withCredentials: false
                }, {
                    // 缓存和性能优化配置
                    // 注意：enableWorker 设为 false，因为 CSP 可能阻止 blob Worker
                    enableWorker: false,
                    enableStashBuffer: true,
                    stashInitialSize: 128 * 1024,        // 初始缓冲 128KB
                    autoCleanupSourceBuffer: true,
                    autoCleanupMaxBackwardDuration: 30,   // 保留30秒回放缓冲
                    autoCleanupMinBackwardDuration: 10,   // 最小保留10秒
                    lazyLoad: false,                      // 直播不使用懒加载
                    lazyLoadMaxDuration: this.config.maxBufferTime,
                    lazyLoadRecoverDuration: this.config.bufferTime,
                    seekType: 'range',
                    fixAudioTimestampGap: true
                });
                
                return this.flvPlayer;
            }
            
            /**
             * 销毁播放器
             */
            destroyPlayer() {
                if (this.flvPlayer) {
                    try {
                        this.flvPlayer.pause();
                        this.flvPlayer.unload();
                        this.flvPlayer.detachMediaElement();
                        this.flvPlayer.destroy();
                    } catch (e) {
                        console.warn('销毁播放器时出错:', e);
                    }
                    this.flvPlayer = null;
                }
            }
            
            /**
             * 绑定播放器事件
             */
            bindEvents() {
                if (!this.flvPlayer) return;
                
                // 错误处理
                this.flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
                    console.error('播放器错误:', errType, errDetail);
                    this.handleError(errType, errDetail);
                });
                
                // 加载状态变化
                this.flvPlayer.on(flvjs.Events.LOADING_COMPLETE, () => {
                    console.log('加载完成');
                });
                
                // 统计信息更新
                this.flvPlayer.on(flvjs.Events.STATISTICS_INFO, (info) => {
                    // 每5秒检查一次缓冲状态
                    const now = Date.now();
                    if (now - this.lastBufferCheck > 5000) {
                        this.lastBufferCheck = now;
                        this.checkBuffer(info);
                        
                        // 保存播放状态到本地
                        this.cache.savePlaybackState({
                            speed: info.speed,
                            decodedFrames: info.decodedFrames
                        });
                    }
                });
                
                // 视频元素事件
                this.videoElement.addEventListener('waiting', () => {
                    console.log('缓冲中...');
                    this.showBufferingIndicator(true);
                });
                
                this.videoElement.addEventListener('playing', () => {
                    console.log('播放中');
                    this.reconnectAttempts = 0;
                    this.showBufferingIndicator(false);
                });
                
                this.videoElement.addEventListener('error', (e) => {
                    console.error('视频元素错误:', e);
                    this.handleError('MediaError', e);
                });
            }
            
            /**
             * 显示/隐藏缓冲指示器
             */
            showBufferingIndicator(show) {
                const container = this.videoElement.parentElement;
                let indicator = container.querySelector('.buffering-indicator');
                
                if (show && !indicator) {
                    indicator = document.createElement('div');
                    indicator.className = 'buffering-indicator';
                    indicator.innerHTML = `
                        <div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
                                    background:rgba(0,0,0,0.6);padding:1rem 2rem;border-radius:0.5rem;color:white;">
                            <span>加载中...</span>
                        </div>
                    `;
                    container.style.position = 'relative';
                    container.appendChild(indicator);
                } else if (!show && indicator) {
                    indicator.remove();
                }
            }
            
            /**
             * 检查缓冲状态
             */
            checkBuffer(info) {
                if (this.videoElement.buffered.length > 0) {
                    const bufferedEnd = this.videoElement.buffered.end(this.videoElement.buffered.length - 1);
                    const bufferLength = bufferedEnd - this.videoElement.currentTime;
                    
                    // 如果缓冲过长，跳转到接近实时位置（保持直播时效性）
                    if (bufferLength > this.config.maxBufferTime) {
                        console.log('缓冲过长，跳转到实时位置');
                        this.videoElement.currentTime = bufferedEnd - this.config.bufferTime;
                    }
                }
            }
            
            /**
             * 处理错误并尝试重连
             */
            handleError(errType, errDetail) {
                if (this.isDestroyed) return;
                
                // 网络错误时尝试重连
                if (errType === flvjs.ErrorTypes.NETWORK_ERROR ||
                    errType === flvjs.ErrorTypes.MEDIA_ERROR) {
                    this.attemptReconnect();
                }
            }
            
            /**
             * 尝试重连
             */
            async attemptReconnect() {
                if (this.isDestroyed) return;
                
                if (this.reconnectAttempts >= this.maxReconnectAttempts) {
                    console.error('已达到最大重连次数');
                    this.showReconnectUI();
                    return;
                }
                
                this.reconnectAttempts++;
                console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
                
                // 使用本地缓存检查流状态
                const status = await this.cache.getStreamStatus(this.config.flvUrl);
                
                setTimeout(() => {
                    if (this.isDestroyed) return;
                    
                    if (status && status.available) {
                        this.destroyPlayer();
                        this.initPlayer();
                    } else {
                        this.attemptReconnect();
                    }
                }, this.reconnectInterval);
            }
            
            /**
             * 显示重连UI
             */
            showReconnectUI() {
                const container = this.videoElement.parentElement;
                let overlay = container.querySelector('.reconnect-overlay');
                
                if (!overlay) {
                    overlay = document.createElement('div');
                    overlay.className = 'reconnect-overlay';
                    overlay.innerHTML = `
                        <div style="position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.7);display:flex;flex-direction:column;align-items:center;justify-content:center;color:white;">
                            <p style="margin-bottom:1rem;">直播流连接失败</p>
                            <button id="reconnectBtn" style="padding:0.5rem 1rem;background:#3b82f6;border:none;border-radius:0.25rem;color:white;cursor:pointer;">
                                点击重新连接
                            </button>
                        </div>
                    `;
                    container.style.position = 'relative';
                    container.appendChild(overlay);
                    
                    document.getElementById('reconnectBtn').addEventListener('click', () => {
                        overlay.remove();
                        this.reconnectAttempts = 0;
                        this.destroyPlayer();
                        this.initPlayer();
                    });
                }
            }
            
            /**
             * 启动状态检测定时器
             */
            startStatusCheck() {
                // 每30秒检查一次流状态（使用本地缓存）
                this.statusCheckInterval = setInterval(async () => {
                    if (this.isDestroyed) return;
                    
                    const status = await this.cache.getStreamStatus(this.config.flvUrl);
                    if (status && !status.available && this.flvPlayer) {
                        console.log('检测到直播流不可用');
                    }
                }, 30000);
            }
            
            /**
             * 初始化播放器（不含预加载）
             */
            initPlayer() {
                // 创建播放器
                this.createPlayer();
                this.flvPlayer.attachMediaElement(this.videoElement);
                
                // 绑定事件
                this.bindEvents();
                
                // 加载并播放
                this.flvPlayer.load();
                
                // 尝试自动播放
                this.videoElement.play().catch(e => {
                    console.log('自动播放被阻止，需要用户交互');
                });
            }
            
            /**
             * 初始化（包含预加载）
             */
            async init() {
                if (!flvjs.isSupported()) {
                    console.error('您的浏览器不支持 FLV 播放');
                    return;
                }
                
                // 预加载配置和缓存
                const streamAvailable = await this.preload();
                console.log('预加载完成，流可用:', streamAvailable);
                
                // 初始化播放器
                this.initPlayer();
                
                // 启动状态检测
                this.startStatusCheck();
            }
            
            /**
             * 销毁
             */
            destroy() {
                this.isDestroyed = true;
                
                if (this.statusCheckInterval) {
                    clearInterval(this.statusCheckInterval);
                }
                
                // 保存最终状态
                this.cache.savePlaybackState({
                    destroyed: true
                });
                
                this.destroyPlayer();
            }
        }
        
        // 初始化播放器
        document.addEventListener('DOMContentLoaded', function() {
            const player = new LiveStreamPlayer('video_player');
            player.init();
            
            // 页面卸载时清理
            window.addEventListener('beforeunload', function() {
                player.destroy();
            });
        });
    </script>

    <!--<script src="https://api.ecylt.top/f_d/lucky_bag.js?v=5.1.6"></script>-->
    <?php endif; ?>
</body>
</html>
