<?php
/**
 * API路由控制器
 * 统一处理所有API请求，实现请求分发、参数验证、响应格式化等功能
 */

// 设置响应头
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

// 处理OPTIONS请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    exit(json_encode(['success' => true, 'message' => 'Preflight OK']));
}

// 加载数据库配置
require_once __DIR__ . '/../config.php';

// 加载API客户端
require_once 'api_client.php';

// 初始化MCP桥接服务
McpBridge::init();

class ApiRouter {
    private $routes = [];
    private $request;
    private $response;
    
    public function __construct() {
        $this->registerRoutes();
        $this->parseRequest();
    }
    
    /**
     * 注册API路由
     */
    private function registerRoutes() {
        // 天气API
        $this->routes['GET/weather/current'] = ['handler' => 'getCurrentWeather', 'description' => '获取当前天气'];
        $this->routes['GET/weather/forecast'] = ['handler' => 'getWeatherForecast', 'description' => '获取天气预报'];
        $this->routes['GET/weather/all'] = ['handler' => 'getWeatherAll', 'description' => '获取当前天气和预报'];
        
        // 票务API
        $this->routes['GET/ticket/train'] = ['handler' => 'queryTrainTickets', 'description' => '查询火车票'];
        $this->routes['GET/ticket/flight'] = ['handler' => 'queryFlights', 'description' => '查询机票'];
        $this->routes['GET/ticket/station'] = ['handler' => 'getStationInfo', 'description' => '获取车站信息'];
        $this->routes['GET/ticket/cities'] = ['handler' => 'getHotCities', 'description' => '获取热门城市'];
        
        // 数字人API - 婚礼主持
        $this->routes['GET/digital-human/host/status'] = ['handler' => 'getHostStatus', 'description' => '获取司仪数字人状态'];
        $this->routes['POST/digital-human/host/phase'] = ['handler' => 'startHostPhase', 'description' => '启动/切换主持环节'];
        $this->routes['GET/digital-human/host/script'] = ['handler' => 'getHostScript', 'description' => '获取主持词'];
        $this->routes['POST/digital-human/host/transition'] = ['handler' => 'hostTransition', 'description' => '获取串场词'];
        $this->routes['POST/digital-human/host/clear'] = ['handler' => 'clearHostSession', 'description' => '清除主持会话'];

        // 数字人API - 全局总管
        $this->routes['GET/digital-human/manager/status'] = ['handler' => 'getManagerStatus', 'description' => '获取总管状态'];
        $this->routes['POST/digital-human/manager/progress'] = ['handler' => 'updateProgress', 'description' => '更新环节进度'];
        $this->routes['POST/digital-human/manager/reset'] = ['handler' => 'resetManager', 'description' => '重置总管状态'];
        $this->routes['POST/digital-human/manager/task'] = ['handler' => 'createTask', 'description' => '创建任务'];
        $this->routes['GET/digital-human/manager/alerts'] = ['handler' => 'getManagerAlerts', 'description' => '获取预警'];
        $this->routes['POST/digital-human/manager/suggest'] = ['handler' => 'managerSuggest', 'description' => '获取建议'];
        $this->routes['POST/digital-human/manager/chat'] = ['handler' => 'managerChat', 'description' => '总管数字人对话'];
        $this->routes['POST/digital-human/manager/notify-host'] = ['handler' => 'notifyHost', 'description' => '通知司仪数字人'];
        $this->routes['POST/digital-human/manager/resolve-alert'] = ['handler' => 'resolveAlert', 'description' => '解决预警'];
        $this->routes['POST/digital-human/manager/clear'] = ['handler' => 'clearManagerSession', 'description' => '清除总管会话'];
        // 自动化任务管理API
        $this->routes['POST/digital-human/manager/auto-assign'] = ['handler' => 'autoAssignTask', 'description' => '智能任务分配'];
        $this->routes['POST/digital-human/manager/auto-start'] = ['handler' => 'autoStart', 'description' => '启动自动模式'];
        $this->routes['POST/digital-human/manager/auto-pause'] = ['handler' => 'autoPause', 'description' => '暂停自动模式'];
        $this->routes['POST/digital-human/manager/auto-process'] = ['handler' => 'autoProcess', 'description' => '自动化处理'];
        $this->routes['GET/digital-human/manager/auto-stats'] = ['handler' => 'getAutoStats', 'description' => '获取自动化统计'];

        // 数字人API - 协作总线
        $this->routes['POST/digital-human/bus/message'] = ['handler' => 'sendBusMessage', 'description' => '数字人消息传递'];
        $this->routes['GET/digital-human/bus/events'] = ['handler' => 'getBusEvents', 'description' => '获取协作事件'];

        // 视频资产API
        $this->routes['GET/video/assets'] = ['handler' => 'getVideoAssets', 'description' => '获取视频资产列表'];
        $this->routes['GET/video/asset/{id}'] = ['handler' => 'getVideoAsset', 'description' => '获取单个视频资产'];
        $this->routes['POST/video/asset'] = ['handler' => 'createVideoAsset', 'description' => '创建视频资产记录'];
        $this->routes['PUT/video/asset/{id}'] = ['handler' => 'updateVideoAsset', 'description' => '更新视频资产'];
        $this->routes['DELETE/video/asset/{id}'] = ['handler' => 'deleteVideoAsset', 'description' => '删除视频资产'];
        $this->routes['POST/video/upload'] = ['handler' => 'uploadVideo', 'description' => '上传视频文件'];
        $this->routes['GET/video/play/{id}'] = ['handler' => 'getVideoPlayUrl', 'description' => '获取视频播放地址'];
        $this->routes['POST/video/play-log'] = ['handler' => 'logVideoPlay', 'description' => '记录视频播放日志'];
        
        // 图片分享API
        $this->routes['POST/image/upload'] = ['handler' => 'uploadShareImage', 'description' => '上传分享图片'];
        $this->routes['GET/image/share/{id}'] = ['handler' => 'getShareImage', 'description' => '获取分享图片'];
        $this->routes['GET/image/assets'] = ['handler' => 'getImageAssets', 'description' => '获取图片资产列表'];
        $this->routes['DELETE/image/asset'] = ['handler' => 'deleteImageAsset', 'description' => '删除图片资产'];

        // 片尾配置API
        $this->routes['GET/ending/config'] = ['handler' => 'getEndingConfig', 'description' => '获取片尾配置'];
        $this->routes['POST/ending/config'] = ['handler' => 'saveEndingConfig', 'description' => '保存片尾配置'];

        // 系统API
        $this->routes['GET/system/health'] = ['handler' => 'getHealthStatus', 'description' => '健康检查'];
        $this->routes['GET/system/time'] = ['handler' => 'getCurrentTime', 'description' => '获取当前时间'];
        $this->routes['GET/system/config'] = ['handler' => 'getApiConfig', 'description' => '获取API配置'];
        $this->routes['GET/system/mcp_status'] = ['handler' => 'getMcpStatus', 'description' => '获取MCP服务状态'];
    }
    
    /**
     * 解析请求
     */
    private function parseRequest() {
        $method = strtoupper($_SERVER['REQUEST_METHOD']);
        $path = isset($_GET['path']) ? $_GET['path'] : '';
        $path = trim($path, '/');
        
        // 从URL路径中提取
        if (empty($path)) {
            $requestUri = $_SERVER['REQUEST_URI'];
            $parsed = parse_url($requestUri);
            $path = trim($parsed['path'], '/');
            // 移除api_router.php及其前面的路径部分（处理多种URL格式）
            $patterns = ['api/api_router.php', '/api_router.php', 'api_router.php'];
            foreach ($patterns as $pattern) {
                $pos = strpos($path, $pattern);
                if ($pos !== false) {
                    $path = substr($path, $pos + strlen($pattern));
                    break;
                }
            }
            $path = trim($path, '/');
        }
        
        // 获取请求参数
        $params = [];
        if ($method === 'GET') {
            $params = $_GET;
        } else if ($method === 'POST') {
            $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
            if (strpos($contentType, 'application/json') !== false) {
                $params = json_decode(file_get_contents('php://input'), true) ?? [];
            } else {
                $params = $_POST;
            }
        } else if ($method === 'DELETE' || $method === 'PUT') {
            $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
            if (strpos($contentType, 'application/json') !== false) {
                $params = json_decode(file_get_contents('php://input'), true) ?? [];
            }
            // 合并URL参数
            $params = array_merge($params, $_GET);
        }
        
        $this->request = [
            'method' => $method,
            'path' => $path,
            'params' => $params,
            'timestamp' => time()
        ];
    }
    
    /**
     * 执行路由匹配
     */
    public function dispatch() {
        $method = $this->request['method'];
        $path = $this->request['path'];
        $routeKey = "$method/$path";
        
        // 查找路由
        if (isset($this->routes[$routeKey])) {
            $route = $this->routes[$routeKey];
            return $this->executeHandler($route['handler']);
        }
        
        // 查找通配符路由
        foreach ($this->routes as $key => $route) {
            if ($this->matchWildcard($key, $routeKey)) {
                return $this->executeHandler($route['handler']);
            }
        }
        
        return $this->error(404, 'API_NOT_FOUND', 'API endpoint not found');
    }
    
    /**
     * 通配符匹配并提取参数
     */
    private function matchWildcard($pattern, $routeKey) {
        $pattern = str_replace('/', '\/', $pattern);
        $pattern = str_replace('{id}', '([a-zA-Z0-9_]+)', $pattern);
        $pattern = '/^' . $pattern . '$/';
        if (preg_match($pattern, $routeKey, $matches)) {
            // 提取通配符参数
            if (isset($matches[1])) {
                $this->request['params']['id'] = $matches[1];
            }
            return true;
        }
        return false;
    }
    
    /**
     * 执行处理器
     */
    private function executeHandler($handler) {
        try {
            if (method_exists($this, $handler)) {
                $result = $this->$handler();
                return $this->success($result);
            }
            return $this->error(500, 'HANDLER_ERROR', 'Handler method not found');
        } catch (Exception $e) {
            return $this->error(500, 'EXECUTE_ERROR', $e->getMessage());
        }
    }
    
    /**
     * 成功响应
     */
    private function success($data, $message = '操作成功') {
        return json_encode([
            'success' => true,
            'code' => 200,
            'message' => $message,
            'data' => $data,
            'timestamp' => time()
        ], JSON_UNESCAPED_UNICODE);
    }
    
    /**
     * 错误响应
     */
    private function error($httpCode, $errorCode, $message) {
        http_response_code($httpCode);
        return json_encode([
            'success' => false,
            'code' => $httpCode,
            'error_code' => $errorCode,
            'message' => $message,
            'timestamp' => time()
        ], JSON_UNESCAPED_UNICODE);
    }
    
    // ==================== 天气API处理器 ====================
    
    /**
     * 获取当前天气
     */
    private function getCurrentWeather() {
        $city = $this->getParam('city', '北京');
        
        $weatherService = new WeatherApiService();
        $result = $weatherService->getWeatherByCity($city);
        
        if (isset($result['success']) && $result['success']) {
            return $result;
        }
        
        return $this->generateMockWeather($city);
    }
    
    private function getWeatherForecast() {
        $city = $this->getParam('city', '北京');
        $days = (int)$this->getParam('days', 7);
        
        $weatherService = new WeatherApiService();
        $result = $weatherService->getForecast($city, $days);
        
        if (isset($result['success']) && $result['success']) {
            return $result;
        }
        
        return $this->generateMockForecast($city, $days);
    }

    private function getWeatherAll() {
        $city = $this->getParam('city', '北京');
        
        $weatherService = new WeatherApiService();
        $result = $weatherService->getCurrentAndForecast($city);
        
        if (isset($result['success']) && $result['success']) {
            return $result;
        }
        
        return [
            'success' => true,
            'current' => $this->generateMockWeather($city),
            'forecast' => $this->generateMockForecast($city, 5),
            'source' => 'mock'
        ];
    }
    
    // ==================== 票务API处理器 ====================
    
    /**
     * 查询火车票
     */
    private function queryTrainTickets() {
        $from = $this->getParam('from', '');
        $to = $this->getParam('to', '');
        $date = $this->getParam('date', date('Y-m-d'));
        
        // 参数验证
        if (empty($from) || empty($to)) {
            throw new Exception('出发地和目的地不能为空');
        }
        
        $ticketService = new TicketApiService();
        return $ticketService->queryTrainTickets($from, $to, $date);
    }
    
    /**
     * 查询机票
     */
    private function queryFlights() {
        $from = $this->getParam('from', '');
        $to = $this->getParam('to', '');
        $date = $this->getParam('date', date('Y-m-d'));
        
        // 参数验证
        if (empty($from) || empty($to)) {
            throw new Exception('出发地和目的地不能为空');
        }
        
        $ticketService = new TicketApiService();
        return $ticketService->queryFlights($from, $to, $date);
    }
    
    /**
     * 获取车站信息
     */
    private function getStationInfo() {
        $city = $this->getParam('city', '');
        
        if (empty($city)) {
            throw new Exception('城市名称不能为空');
        }
        
        $ticketService = new TicketApiService();
        return $ticketService->getStationInfo($city);
    }
    
    /**
     * 获取热门城市
     */
    private function getHotCities() {
        $ticketService = new TicketApiService();
        return $ticketService->getHotCities();
    }

    // ==================== 数字人API处理器 ====================

    private function getHostAgent() {
        require_once __DIR__ . '/agent_host.php';
        $sessionId = $this->getParam('session_id', null);
        return new HostAgent($sessionId);
    }

    private function getManagerAgent() {
        require_once __DIR__ . '/agent_manager.php';
        $sessionId = $this->getParam('session_id', null);
        $agent = new ManagerAgent($sessionId);
        $agent->loadPhasesFromDB();
        return $agent;
    }

    private function getHostStatus() {
        $agent = $this->getHostAgent();
        return $agent->getStatus();
    }

    private function startHostPhase() {
        $agent = $this->getHostAgent();
        $phase = $this->getParam('phase', 'opening');
        $context = json_decode($this->getParam('context', '{}'), true) ?: [];
        return $agent->startPhase($phase, $context);
    }

    private function getHostScript() {
        $agent = $this->getHostAgent();
        $phase = $this->getParam('phase', 'opening');
        $style = $this->getParam('style', 'romantic');
        return $agent->getPhaseScript($phase, $style);
    }

    private function hostTransition() {
        $agent = $this->getHostAgent();
        $from = $this->getParam('from_phase', 'opening');
        $to = $this->getParam('to_phase', 'bride_entrance');
        return $agent->getTransitionScript($from, $to);
    }

    private function clearHostSession() {
        $agent = $this->getHostAgent();
        $agent->clearSession();
        return ['success' => true, 'message' => '主持会话已清除'];
    }

    private function getManagerStatus() {
        $agent = $this->getManagerAgent();
        return $agent->getFullStatus();
    }

    private function updateProgress() {
        $agent = $this->getManagerAgent();
        $phaseKey = $this->getParam('phase_id', '');
        $status = $this->getParam('status', 'pending');
        $actualTime = $this->getParam('actual_time', null);
        $notes = $this->getParam('notes', '');
        return $agent->updateProgress($phaseKey, $status, $actualTime, $notes);
    }

    private function resetManager() {
        $agent = $this->getManagerAgent();
        return $agent->resetAllPhases();
    }

    private function createTask() {
        $agent = $this->getManagerAgent();
        $team = $this->getParam('assignee', '');
        $task = $this->getParam('task', '');
        $deadline = $this->getParam('deadline', '');
        $priority = $this->getParam('priority', 'medium');
        if (empty($team) || empty($task)) {
            throw new Exception('团队和任务不能为空');
        }
        return $agent->createTask($team, $task, $deadline, $priority);
    }

    private function getManagerAlerts() {
        $agent = $this->getManagerAgent();
        return $agent->getAlerts();
    }

    private function managerSuggest() {
        $agent = $this->getManagerAgent();
        $situation = $this->getParam('situation', '');
        if (empty($situation)) {
            throw new Exception('情况描述不能为空');
        }
        return $agent->suggest($situation);
    }

    private function managerChat() {
        $agent = $this->getManagerAgent();
        $message = $this->getParam('message', '');
        if (empty($message)) {
            throw new Exception('消息不能为空');
        }
        return $agent->chat($message);
    }

    private function notifyHost() {
        $agent = $this->getManagerAgent();
        $event = $this->getParam('event', 'info');
        $detail = $this->getParam('detail', '');
        return $agent->notifyHost($event, $detail);
    }

    private function resolveAlert() {
        $agent = $this->getManagerAgent();
        $index = intval($this->getParam('alert_index', -1));
        return $agent->resolveAlert($index);
    }

    private function clearManagerSession() {
        $agent = $this->getManagerAgent();
        $agent->clearSession();
        return ['success' => true, 'message' => '总管会话已清除'];
    }

    private function autoAssignTask() {
        $agent = $this->getManagerAgent();
        $description = $this->getParam('description', '');
        $deadline = $this->getParam('deadline', '');
        $priority = $this->getParam('priority', 'medium');
        $teams = $this->getParam('teams', '');
        
        if (empty($description)) {
            throw new Exception('任务描述不能为空');
        }
        
        return $agent->autoAssignTask($description, $deadline, $priority, $teams);
    }

    private function autoStart() {
        $agent = $this->getManagerAgent();
        return $agent->startAutoMode();
    }

    private function autoPause() {
        $agent = $this->getManagerAgent();
        return $agent->pauseAutoMode();
    }

    private function autoProcess() {
        $agent = $this->getManagerAgent();
        return $agent->processAutoTasks();
    }

    private function getAutoStats() {
        $agent = $this->getManagerAgent();
        return $agent->getAutoStats();
    }

    private function sendBusMessage() {
        require_once __DIR__ . '/agent_base.php';
        global $pdo;
        $from = $this->getParam('from', '');
        $to = $this->getParam('to', '');
        $type = $this->getParam('type', 'event');
        $payload = json_decode($this->getParam('payload', '{}'), true) ?: [];

        if (empty($from) || empty($to)) {
            throw new Exception('发送方和接收方不能为空');
        }

        try {
            $stmt = $pdo->prepare("INSERT INTO agent_events (from_agent, to_agent, event_type, payload) VALUES (?, ?, ?, ?)");
            $stmt->execute([$from, $to, $type, json_encode($payload, JSON_UNESCAPED_UNICODE)]);
            return ['success' => true, 'event_id' => $pdo->lastInsertId()];
        } catch (PDOException $e) {
            throw new Exception('消息发送失败');
        }
    }

    private function getBusEvents() {
        require_once __DIR__ . '/agent_base.php';
        global $pdo;
        $subscriber = $this->getParam('subscriber', '');
        $since = intval($this->getParam('since', 0));

        if (empty($subscriber)) {
            throw new Exception('订阅者不能为空');
        }

        try {
            $stmt = $pdo->prepare("SELECT * FROM agent_events WHERE to_agent = ? AND is_read = 0 AND id > ? ORDER BY id ASC");
            $stmt->execute([$subscriber, $since]);
            $events = $stmt->fetchAll(PDO::FETCH_ASSOC);

            if (!empty($events)) {
                $ids = array_column($events, 'id');
                $placeholders = implode(',', array_fill(0, count($ids), '?'));
                $pdo->prepare("UPDATE agent_events SET is_read = 1 WHERE id IN ($placeholders)")->execute($ids);
            }

            return ['success' => true, 'events' => $events];
        } catch (PDOException $e) {
            return ['success' => true, 'events' => []];
        }
    }
    
    // ==================== 系统API处理器 ====================
    
    /**
     * 健康检查
     */
    private function getHealthStatus() {
        return [
            'status' => 'healthy',
            'services' => [
                'weather_api' => 'available',
                'ticket_api' => 'available',
                'database' => 'available'
            ],
            'version' => '1.0.0'
        ];
    }
    
    /**
     * 获取当前时间
     */
    private function getCurrentTime() {
        return [
            'timestamp' => time(),
            'date' => date('Y-m-d'),
            'time' => date('H:i:s'),
            'datetime' => date('Y-m-d H:i:s'),
            'timezone' => 'Asia/Shanghai'
        ];
    }
    
    /**
     * 获取API配置
     */
    private function getApiConfig() {
        $config = ApiClient::getConfig();
        $config['mcp_services'] = McpBridge::getServiceStatus();
        return $config;
    }
    
    /**
     * 获取MCP服务状态
     */
    private function getMcpStatus() {
        return McpBridge::getServiceStatus();
    }
    
    // ==================== 辅助方法 ====================
    
    /**
     * 获取请求参数
     */
    private function getParam($key, $default = null) {
        return $this->request['params'][$key] ?? $default;
    }
    
    /**
     * 生成模拟天气数据
     */
    private function generateMockWeather($city) {
        $conditions = ['晴', '多云', '阴', '小雨', '中雨', '大雨', '雪'];
        $icons = ['☀️', '⛅', '☁️', '🌧', '🌧', '🌧', '❄️'];
        $windDirs = ['北风', '南风', '东风', '西风', '东北风', '西南风'];
        $idx = rand(0, 6);
        
        return [
            'success' => true,
            'city' => $city,
            'temperature' => rand(-5, 38),
            'feels_like' => rand(-10, 35),
            'condition' => $conditions[$idx],
            'icon' => $icons[$idx],
            'wind' => $windDirs[rand(0, 5)] . ' ' . rand(1, 6) . '级',
            'humidity' => rand(20, 95),
            'visibility' => rand(1, 10) . 'km',
            'pressure' => rand(990, 1030) . 'hPa',
            'last_update' => date('Y-m-d H:i:s'),
            'source' => 'mock'
        ];
    }
    
    /**
     * 生成模拟预报数据
     */
    private function generateMockForecast($city, $days) {
        $conditions = ['晴', '多云', '阴', '小雨', '中雨', '大雨', '雪'];
        $icons = ['☀️', '⛅', '☁️', '🌧', '🌧', '🌧', '❄️'];
        $windDirs = ['北风', '南风', '东风', '西风'];
        $forecasts = [];
        
        for ($i = 0; $i < $days; $i++) {
            $date = date('Y-m-d', strtotime("+$i days"));
            $high = rand(5, 35);
            $low = rand(-10, $high - 5);
            $idx = rand(0, 6);
            
            $forecasts[] = [
                'date' => $date,
                'high' => $high,
                'low' => $low,
                'condition' => $conditions[$idx],
                'icon' => $icons[$idx],
                'wind' => $windDirs[rand(0, 3)] . ' ' . rand(2, 4) . '级',
                'humidity' => rand(20, 90)
            ];
        }
        
        return [
            'success' => true,
            'city' => $city,
            'forecasts' => $forecasts,
            'source' => 'mock'
        ];
    }

    // ==================== 视频资产API处理器 ====================

    private function getVideoAssets() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        $type = $this->getParam('type', '');
        $activeOnly = $this->getParam('active_only', false);
        $sortBy = $this->getParam('sort_by', 'play_priority');
        $sortOrder = $this->getParam('sort_order', 'ASC');
        
        $validSortFields = ['play_priority', 'video_name', 'created_at', 'duration'];
        if (!in_array($sortBy, $validSortFields)) {
            $sortBy = 'play_priority';
        }
        $sortOrder = strtoupper($sortOrder) === 'DESC' ? 'DESC' : 'ASC';
        
        try {
            $sql = "SELECT * FROM video_assets WHERE 1=1";
            $params = [];
            
            if (!empty($type)) {
                $sql .= " AND video_type = ?";
                $params[] = $type;
            }
            if ($activeOnly) {
                $sql .= " AND is_active = 1";
            }
            
            $sql .= " ORDER BY " . $sortBy . " " . $sortOrder;
            
            $stmt = $pdo->prepare($sql);
            $stmt->execute($params);
            $assets = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            return ['success' => true, 'data' => $assets];
        } catch (PDOException $e) {
            throw new Exception('查询失败: ' . $e->getMessage());
        }
    }

    private function getVideoAsset() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        $videoId = $this->getParam('id', '');
        if (empty($videoId)) {
            throw new Exception('视频ID不能为空');
        }
        
        try {
            $stmt = $pdo->prepare("SELECT * FROM video_assets WHERE video_id = ?");
            $stmt->execute([$videoId]);
            $asset = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$asset) {
                throw new Exception('视频不存在');
            }
            
            return ['success' => true, 'data' => $asset];
        } catch (PDOException $e) {
            throw new Exception('查询失败: ' . $e->getMessage());
        }
    }

    private function createVideoAsset() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        $videoName = $this->getParam('video_name', '');
        $videoType = $this->getParam('video_type', 'other');
        $storagePath = $this->getParam('storage_path', '');
        $fileName = $this->getParam('file_name', '');
        
        if (empty($videoName) || empty($fileName)) {
            throw new Exception('视频名称和文件名不能为空');
        }
        
        try {
            $videoId = uniqid('vid_');
            
            $stmt = $pdo->prepare("INSERT INTO video_assets 
                (video_id, video_name, video_type, storage_path, file_name, duration, format, play_priority, is_active, description)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            
            $stmt->execute([
                $videoId,
                $videoName,
                $videoType,
                $storagePath,
                $fileName,
                $this->getParam('duration', 0.00),
                $this->getParam('format', 'mp4'),
                $this->getParam('play_priority', 1),
                $this->getParam('is_active', 1),
                $this->getParam('description', '')
            ]);
            
            return ['success' => true, 'video_id' => $videoId, 'message' => '视频资产创建成功'];
        } catch (PDOException $e) {
            throw new Exception('创建失败: ' . $e->getMessage());
        }
    }

    private function updateVideoAsset() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        $videoId = $this->getParam('id', '');
        if (empty($videoId)) {
            throw new Exception('视频ID不能为空');
        }
        
        try {
            $updates = [];
            $params = [];
            
            if (isset($this->request['params']['video_name'])) {
                $updates[] = "video_name = ?";
                $params[] = $this->getParam('video_name');
            }
            if (isset($this->request['params']['video_type'])) {
                $updates[] = "video_type = ?";
                $params[] = $this->getParam('video_type');
            }
            if (isset($this->request['params']['is_active'])) {
                $updates[] = "is_active = ?";
                $params[] = $this->getParam('is_active');
            }
            if (isset($this->request['params']['play_priority'])) {
                $priority = $this->getParam('play_priority');
                if (is_numeric($priority)) {
                    $priority = intval($priority);
                    if ($priority > 0 || $priority < 0) {
                        $updates[] = "play_priority = play_priority + ?";
                    } else {
                        $updates[] = "play_priority = ?";
                    }
                    $params[] = $priority;
                }
            }
            if (isset($this->request['params']['duration'])) {
                $updates[] = "duration = ?";
                $params[] = $this->getParam('duration');
            }
            if (isset($this->request['params']['description'])) {
                $updates[] = "description = ?";
                $params[] = $this->getParam('description');
            }
            
            if (empty($updates)) {
                throw new Exception('没有需要更新的字段');
            }
            
            $params[] = $videoId;
            $sql = "UPDATE video_assets SET " . implode(', ', $updates) . " WHERE video_id = ?";
            
            $stmt = $pdo->prepare($sql);
            $stmt->execute($params);
            
            if ($stmt->rowCount() === 0) {
                throw new Exception('视频不存在');
            }
            
            return ['success' => true, 'message' => '视频资产更新成功'];
        } catch (PDOException $e) {
            throw new Exception('更新失败: ' . $e->getMessage());
        }
    }

    private function deleteVideoAsset() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        $videoId = $this->getParam('id', '');
        if (empty($videoId)) {
            throw new Exception('视频ID不能为空');
        }
        
        try {
            $stmt = $pdo->prepare("SELECT storage_path, file_name FROM video_assets WHERE video_id = ?");
            $stmt->execute([$videoId]);
            $asset = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$asset) {
                throw new Exception('视频不存在');
            }
            
            $filePath = __DIR__ . '/../' . $asset['storage_path'] . $asset['file_name'];
            if (file_exists($filePath)) {
                unlink($filePath);
            }
            
            $stmt = $pdo->prepare("DELETE FROM video_assets WHERE video_id = ?");
            $stmt->execute([$videoId]);
            
            return ['success' => true, 'message' => '视频资产删除成功'];
        } catch (PDOException $e) {
            throw new Exception('删除失败: ' . $e->getMessage());
        }
    }

    private function uploadVideo() {
        $allowedTypes = ['video/mp4', 'video/webm', 'video/ogg', 'application/octet-stream'];
        $allowedExtensions = ['mp4', 'webm', 'ogg'];
        $maxFileSize = 200 * 1024 * 1024;
        
        // 检查文件是否存在
        if (!isset($_FILES['video'])) {
            throw new Exception('请选择要上传的视频文件');
        }
        
        $file = $_FILES['video'];
        
        // 检查上传错误
        $errorMessages = [
            UPLOAD_ERR_INI_SIZE => '上传文件大小超过了php.ini中的限制',
            UPLOAD_ERR_FORM_SIZE => '上传文件大小超过了表单中的限制',
            UPLOAD_ERR_PARTIAL => '文件只上传了一部分',
            UPLOAD_ERR_NO_FILE => '没有文件被上传',
            UPLOAD_ERR_NO_TMP_DIR => '找不到临时目录',
            UPLOAD_ERR_CANT_WRITE => '文件写入失败',
            UPLOAD_ERR_EXTENSION => '文件上传被扩展阻止'
        ];
        
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $msg = isset($errorMessages[$file['error']]) ? $errorMessages[$file['error']] : '未知错误';
            throw new Exception('文件上传失败: ' . $msg . ' (错误码: ' . $file['error'] . ')');
        }
        
        // 检查文件大小
        if ($file['size'] > $maxFileSize) {
            throw new Exception('文件大小超过限制（最大200MB），当前大小: ' . round($file['size'] / 1024 / 1024, 2) . 'MB');
        }
        
        // 检查文件格式
        $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if (!in_array($ext, $allowedExtensions) && !in_array($file['type'], $allowedTypes)) {
            throw new Exception('不支持的文件格式: ' . $file['type'] . '，仅支持MP4、WebM、OGG格式');
        }
        
        // 获取视频类型和名称
        $videoType = $this->getParam('video_type', 'other');
        $videoName = $this->getParam('video_name', '');
        if (empty($videoName)) {
            $videoName = pathinfo($file['name'], PATHINFO_FILENAME);
        }
        
        // 生成新文件名
        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $newFileName = uniqid() . '.' . $ext;
        
        // 确定上传目录
        if ($videoType === 'opening') {
            $uploadDir = __DIR__ . '/../videos/opening/';
            $storagePath = 'videos/opening/';
        } elseif ($videoType === 'host') {
            $uploadDir = __DIR__ . '/../videos/host/';
            $storagePath = 'videos/host/';
        } else {
            $uploadDir = __DIR__ . '/../videos/';
            $storagePath = 'videos/';
        }
        
        // 确保目录存在
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }
        
        if (!file_exists($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }
        
        $destination = $uploadDir . $newFileName;
        
        if (!move_uploaded_file($file['tmp_name'], $destination)) {
            throw new Exception('文件移动失败');
        }
        
        $duration = $this->getVideoDuration($destination);
        
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        try {
            $videoId = uniqid('vid_');
            
            $stmt = $pdo->prepare("INSERT INTO video_assets 
                (video_id, video_name, video_type, storage_path, file_name, file_size, duration, format, is_active, uploaded_by, play_priority, description)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            
            $stmt->execute([
                $videoId,
                $videoName,
                $videoType,
                $storagePath,
                $newFileName,
                $file['size'],
                $duration,
                strtoupper($ext),
                1,
                'admin',
                1,
                ''
            ]);
            
            return [
                'success' => true,
                'video_id' => $videoId,
                'video_name' => $videoName,
                'file_name' => $newFileName,
                'storage_path' => $storagePath,
                'duration' => $duration,
                'message' => '视频上传成功'
            ];
        } catch (PDOException $e) {
            unlink($destination);
            throw new Exception('数据库写入失败: ' . $e->getMessage());
        }
    }
    
    private function uploadShareImage() {
        $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
        $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        $maxFileSize = 10 * 1024 * 1024;
        
        if (!isset($_FILES['file'])) {
            throw new Exception('请选择要上传的图片文件');
        }
        
        $file = $_FILES['file'];
        
        $errorMessages = [
            UPLOAD_ERR_INI_SIZE => '上传文件大小超过了php.ini中的限制',
            UPLOAD_ERR_FORM_SIZE => '上传文件大小超过了表单中的限制',
            UPLOAD_ERR_PARTIAL => '文件只上传了一部分',
            UPLOAD_ERR_NO_FILE => '没有文件被上传',
            UPLOAD_ERR_NO_TMP_DIR => '找不到临时目录',
            UPLOAD_ERR_CANT_WRITE => '文件写入失败',
            UPLOAD_ERR_EXTENSION => '文件上传被扩展阻止'
        ];
        
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $msg = isset($errorMessages[$file['error']]) ? $errorMessages[$file['error']] : '未知错误';
            throw new Exception('文件上传失败: ' . $msg . ' (错误码: ' . $file['error'] . ')');
        }
        
        if ($file['size'] > $maxFileSize) {
            throw new Exception('文件大小超过限制（最大10MB），当前大小: ' . round($file['size'] / 1024 / 1024, 2) . 'MB');
        }
        
        $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if (!in_array($ext, $allowedExtensions) && !in_array($file['type'], $allowedTypes)) {
            throw new Exception('不支持的文件格式: ' . $file['type'] . '，仅支持JPG、PNG、GIF格式');
        }
        
        $newFileName = uniqid() . '.' . $ext;
        $uploadDir = __DIR__ . '/../images/share/';
        $storagePath = 'images/share/';
        
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }
        
        $destination = $uploadDir . $newFileName;
        
        if (!move_uploaded_file($file['tmp_name'], $destination)) {
            throw new Exception('文件移动失败');
        }
        
        $imageId = uniqid('img_');
        
        return [
            'image_id' => $imageId,
            'file_name' => $newFileName,
            'storage_path' => $storagePath,
            'url' => $storagePath . $newFileName,
            'message' => '图片上传成功'
        ];
    }
    
    private function getShareImage() {
        $imageId = $this->getParam('id', '');
        if (empty($imageId)) {
            throw new Exception('图片ID不能为空');
        }
        
        $uploadDir = __DIR__ . '/../images/share/';
        $files = glob($uploadDir . '*');
        
        foreach ($files as $file) {
            $fileName = basename($file);
            if (strpos($fileName, $imageId) === 0) {
                $filePath = $file;
                break;
            }
        }
        
        if (!isset($filePath) || !file_exists($filePath)) {
            throw new Exception('图片不存在');
        }
        
        $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        $mimeTypes = [
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
            'webp' => 'image/webp'
        ];
        
        header('Content-Type: ' . ($mimeTypes[$ext] ?? 'application/octet-stream'));
        readfile($filePath);
        exit;
    }

    private function getImageAssets() {
        $uploadDir = __DIR__ . '/../images/share/';
        $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
        $images = [];
        
        if (is_dir($uploadDir)) {
            $files = scandir($uploadDir);
            foreach ($files as $file) {
                if ($file === '.' || $file === '..') continue;
                $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
                if (!in_array($ext, $allowedExtensions)) continue;
                $filePath = $uploadDir . $file;
                $images[] = [
                    'file_name' => $file,
                    'url' => 'images/share/' . $file,
                    'size' => filesize($filePath),
                    'modified_at' => filemtime($filePath)
                ];
            }
        }
        
        // 按修改时间倒序（最新在前）
        usort($images, function($a, $b) {
            return $b['modified_at'] - $a['modified_at'];
        });
        
        return $images;
    }

    private function deleteImageAsset() {
        $fileName = $this->getParam('file', '');
        if (empty($fileName)) {
            $fileName = $this->getParam('id', '');
        }
        if (empty($fileName)) {
            throw new Exception('图片文件名不能为空');
        }
        
        // 防止路径遍历：仅允许纯文件名
        if (basename($fileName) !== $fileName || strpos($fileName, '..') !== false) {
            throw new Exception('非法文件名');
        }
        
        $uploadDir = __DIR__ . '/../images/share/';
        $filePath = $uploadDir . $fileName;
        
        if (!file_exists($filePath)) {
            throw new Exception('图片不存在');
        }
        
        if (!unlink($filePath)) {
            throw new Exception('图片删除失败');
        }
        
        return ['message' => '图片删除成功'];
    }

    private function getVideoDuration($filePath) {
        try {
            $ffmpegPath = 'ffmpeg';
            $command = escapeshellcmd($ffmpegPath . ' -i "' . $filePath . '" 2>&1');
            $output = shell_exec($command);
            
            if (preg_match('/Duration: (\d{2}):(\d{2}):(\d{2})\.\d+/', $output, $matches)) {
                return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3];
            }
        } catch (Exception $e) {
        }
        
        return 0.00;
    }

    private function getVideoPlayUrl() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        $videoId = $this->getParam('id', '');
        if (empty($videoId)) {
            throw new Exception('视频ID不能为空');
        }
        
        try {
            $stmt = $pdo->prepare("SELECT storage_path, file_name, is_active FROM video_assets WHERE video_id = ?");
            $stmt->execute([$videoId]);
            $asset = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$asset) {
                throw new Exception('视频不存在');
            }
            
            if (!$asset['is_active']) {
                throw new Exception('视频未启用');
            }
            
            $relativePath = $asset['storage_path'] . $asset['file_name'];
            
            $isSecure = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';
            $scheme = $isSecure ? 'https' : 'http';
            $host = $_SERVER['HTTP_HOST'];
            $scriptDir = dirname(dirname($_SERVER['PHP_SELF']));
            $scriptDir = str_replace('\\', '/', $scriptDir);
            if ($scriptDir === '/' || $scriptDir === '\\') {
                $scriptDir = '';
            }
            $baseUrl = $scheme . '://' . $host . $scriptDir;
            $playUrl = $baseUrl . '/' . $relativePath;
            
            return ['success' => true, 'url' => $playUrl, 'relative_url' => $relativePath, 'data' => $asset];
        } catch (PDOException $e) {
            throw new Exception('查询失败: ' . $e->getMessage());
        }
    }

    private function logVideoPlay() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        $videoId = $this->getParam('video_id', '');
        $status = $this->getParam('status', 'started');
        $duration = $this->getParam('duration', 0.00);
        
        if (empty($videoId)) {
            throw new Exception('视频ID不能为空');
        }
        
        try {
            $stmt = $pdo->prepare("INSERT INTO video_play_logs (video_id, duration, status, client_ip) VALUES (?, ?, ?, ?)");
            $stmt->execute([
                $videoId,
                $duration,
                $status,
                $_SERVER['REMOTE_ADDR'] ?? ''
            ]);
            
            return ['success' => true, 'log_id' => $pdo->lastInsertId()];
        } catch (PDOException $e) {
            throw new Exception('记录失败: ' . $e->getMessage());
        }
    }

    // ==================== 片尾配置API处理器 ====================

    private function getEndingConfig() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        try {
            $pdo->exec("CREATE TABLE IF NOT EXISTS ending_config (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                config_key TEXT UNIQUE NOT NULL,
                config_value TEXT NOT NULL,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )");
            
            $stmt = $pdo->query("SELECT config_key, config_value FROM ending_config");
            $config = [];
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $config[$row['config_key']] = $row['config_value'];
            }
            
            $defaultConfig = [
                'text' => '感谢各位来宾的光临，祝新人新婚快乐，永结同心！',
                'studio' => '礼典世家婚礼策划',
                'date' => '',
                'animation' => 'fade',
                'duration' => '30',
                'bgMusic' => '',
                'autoTrigger' => '1'
            ];
            
            return ['success' => true, 'data' => array_merge($defaultConfig, $config)];
        } catch (PDOException $e) {
            throw new Exception('查询失败: ' . $e->getMessage());
        }
    }

    private function saveEndingConfig() {
        require_once __DIR__ . '/../config.php';
        global $pdo;
        
        $data = $this->request['params'];
        
        try {
            $pdo->exec("CREATE TABLE IF NOT EXISTS ending_config (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                config_key TEXT UNIQUE NOT NULL,
                config_value TEXT NOT NULL,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )");
            
            foreach ($data as $key => $value) {
                $stmt = $pdo->prepare("INSERT OR REPLACE INTO ending_config (config_key, config_value) VALUES (:key, :value)");
                $stmt->execute([':key' => $key, ':value' => $value]);
            }
            
            return ['success' => true, 'message' => '片尾配置保存成功'];
        } catch (PDOException $e) {
            throw new Exception('保存失败: ' . $e->getMessage());
        }
    }
}

// 执行路由
$router = new ApiRouter();
echo $router->dispatch();
