#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
脚本WebSocket API路由
提供实时日志推送和脚本状态监控
"""

from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Query
from fastapi.responses import HTMLResponse
import json
from typing import Dict, Any

from services.online_script.script_websocket_service import get_websocket_manager
from utils.logger import get_logger

logger = get_logger("routes.script_websocket_api")
router = APIRouter(
    prefix="/api/script",
    tags=["Script WebSocket"]
)


@router.websocket("/ws/script-logs")
async def script_logs_websocket(
    websocket: WebSocket,
    client_id: str = Query(..., description="客户端ID"),
    client_type: str = Query(default="web", description="客户端类型")
):
    """脚本日志实时推送WebSocket连接"""
    websocket_manager = get_websocket_manager()
    connection_id = None
    
    try:
        # 建立连接
        connection_id = await websocket_manager.connect(websocket, client_id, client_type)
        
        while True:
            # 接收客户端消息
            data = await websocket.receive_text()
            message = json.loads(data)
            
            message_type = message.get("type")
            
            if message_type == "subscribe":
                # 订阅脚本日志
                script_id = message.get("script_id")
                if script_id:
                    success = await websocket_manager.subscribe_script(connection_id, script_id)
                    if not success:
                        await websocket.send_text(json.dumps({
                            "type": "error",
                            "message": f"订阅脚本 {script_id} 失败"
                        }))
            
            elif message_type == "unsubscribe":
                # 取消订阅脚本日志
                script_id = message.get("script_id")
                if script_id:
                    success = await websocket_manager.unsubscribe_script(connection_id, script_id)
                    if not success:
                        await websocket.send_text(json.dumps({
                            "type": "error",
                            "message": f"取消订阅脚本 {script_id} 失败"
                        }))
            
            elif message_type == "ping":
                # 心跳响应
                await websocket.send_text(json.dumps({
                    "type": "pong",
                    "timestamp": message.get("timestamp")
                }))
            
            elif message_type == "get_status":
                # 获取连接状态
                status = await websocket_manager.get_connection_status()
                await websocket.send_text(json.dumps({
                    "type": "status",
                    "data": status
                }))
            
            else:
                await websocket.send_text(json.dumps({
                    "type": "error",
                    "message": f"未知消息类型: {message_type}"
                }))
                
    except WebSocketDisconnect:
        logger.info(f"WebSocket客户端断开连接: {client_id}")
    except json.JSONDecodeError:
        logger.error(f"WebSocket消息JSON解析失败: {data}")
        try:
            await websocket.send_text(json.dumps({
                "type": "error",
                "message": "消息格式错误，请发送有效的JSON"
            }))
        except:
            pass
    except Exception as e:
        logger.error(f"WebSocket处理异常: {e}", exc_info=True)
    finally:
        # 清理连接
        if connection_id:
            await websocket_manager.disconnect(connection_id)


@router.get("/ws/test-page")
async def get_websocket_test_page():
    """获取WebSocket测试页面"""
    html = """
    <!DOCTYPE html>
    <html>
    <head>
        <title>VWED 脚本日志 WebSocket 测试</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 20px; }
            .container { max-width: 1200px; margin: 0 auto; }
            .section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
            .controls { background-color: #f5f5f5; }
            .logs { background-color: #f9f9f9; height: 400px; overflow-y: scroll; }
            input, button, select { margin: 5px; padding: 5px; }
            .log-entry { margin: 2px 0; padding: 5px; border-radius: 3px; }
            .log-info { background-color: #d4edda; }
            .log-warning { background-color: #fff3cd; }
            .log-error { background-color: #f8d7da; }
            .log-debug { background-color: #d1ecf1; }
            .status { background-color: #e2e3e5; }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>VWED 脚本日志 WebSocket 测试</h1>
            
            <div class="section controls">
                <h3>连接控制</h3>
                <input type="text" id="clientId" placeholder="客户端ID" value="test-client-1">
                <select id="clientType">
                    <option value="web">Web</option>
                    <option value="admin">Admin</option>
                    <option value="monitor">Monitor</option>
                </select>
                <button onclick="connect()">连接</button>
                <button onclick="disconnect()">断开</button>
                <span id="connectionStatus">未连接</span>
            </div>
            
            <div class="section controls">
                <h3>订阅控制</h3>
                <input type="text" id="scriptId" placeholder="脚本ID" value="test_script_123">
                <button onclick="subscribe()">订阅</button>
                <button onclick="unsubscribe()">取消订阅</button>
                <button onclick="getStatus()">获取状态</button>
                <button onclick="clearLogs()">清空日志</button>
            </div>
            
            <div class="section logs">
                <h3>实时日志</h3>
                <div id="logContainer"></div>
            </div>
        </div>
        
        <script>
            let ws = null;
            let clientId = '';
            
            function connect() {
                clientId = document.getElementById('clientId').value;
                const clientType = document.getElementById('clientType').value;
                
                if (!clientId) {
                    alert('请输入客户端ID');
                    return;
                }
                
                ws = new WebSocket(`ws://localhost:8000/api/script/ws/script-logs?client_id=${clientId}&client_type=${clientType}`);
                
                ws.onopen = function(event) {
                    document.getElementById('connectionStatus').textContent = '已连接';
                    addLog('系统', 'WebSocket连接建立', 'status');
                };
                
                ws.onmessage = function(event) {
                    const message = JSON.parse(event.data);
                    handleMessage(message);
                };
                
                ws.onerror = function(error) {
                    addLog('系统', '连接错误: ' + error, 'error');
                };
                
                ws.onclose = function(event) {
                    document.getElementById('connectionStatus').textContent = '已断开';
                    addLog('系统', 'WebSocket连接关闭', 'status');
                };
            }
            
            function disconnect() {
                if (ws) {
                    ws.close();
                    ws = null;
                }
            }
            
            function subscribe() {
                const scriptId = document.getElementById('scriptId').value;
                if (!scriptId || !ws) {
                    alert('请先连接并输入脚本ID');
                    return;
                }
                
                ws.send(JSON.stringify({
                    type: 'subscribe',
                    script_id: scriptId
                }));
            }
            
            function unsubscribe() {
                const scriptId = document.getElementById('scriptId').value;
                if (!scriptId || !ws) {
                    alert('请先连接并输入脚本ID');
                    return;
                }
                
                ws.send(JSON.stringify({
                    type: 'unsubscribe',
                    script_id: scriptId
                }));
            }
            
            function getStatus() {
                if (!ws) {
                    alert('请先连接');
                    return;
                }
                
                ws.send(JSON.stringify({
                    type: 'get_status'
                }));
            }
            
            function clearLogs() {
                document.getElementById('logContainer').innerHTML = '';
            }
            
            function handleMessage(message) {
                switch(message.type) {
                    case 'welcome':
                        addLog('系统', message.message + ' (连接ID: ' + message.connection_id + ')', 'status');
                        break;
                    case 'script_log':
                        addLog('脚本日志', `[${message.script_id}] ${message.message}`, message.level.toLowerCase());
                        break;
                    case 'script_status':
                        addLog('脚本状态', `[${message.script_id}] 状态: ${message.status} - ${message.message}`, 'status');
                        break;
                    case 'function_execution':
                        addLog('函数执行', `[${message.script_id}] ${message.function_name}: ${JSON.stringify(message.result)}`, 'info');
                        break;
                    case 'subscription_success':
                        addLog('系统', message.message, 'status');
                        break;
                    case 'unsubscription_success':
                        addLog('系统', message.message, 'status');
                        break;
                    case 'status':
                        addLog('状态信息', JSON.stringify(message.data, null, 2), 'info');
                        break;
                    case 'error':
                        addLog('错误', message.message, 'error');
                        break;
                    case 'ping':
                        ws.send(JSON.stringify({type: 'pong', timestamp: message.timestamp}));
                        break;
                    case 'pong':
                        addLog('系统', '心跳响应', 'debug');
                        break;
                    default:
                        addLog('未知', JSON.stringify(message), 'debug');
                }
            }
            
            function addLog(source, message, level = 'info') {
                const logContainer = document.getElementById('logContainer');
                const logEntry = document.createElement('div');
                logEntry.className = `log-entry log-${level}`;
                
                const timestamp = new Date().toLocaleTimeString();
                logEntry.innerHTML = `<strong>[${timestamp}] [${source}]</strong> ${message}`;
                
                logContainer.appendChild(logEntry);
                logContainer.scrollTop = logContainer.scrollHeight;
            }
            
            // 定期发送心跳
            setInterval(function() {
                if (ws && ws.readyState === WebSocket.OPEN) {
                    ws.send(JSON.stringify({
                        type: 'ping',
                        timestamp: new Date().toISOString()
                    }));
                }
            }, 30000);
        </script>
    </body>
    </html>
    """
    return HTMLResponse(content=html)


@router.get("/ws/connections/status", summary="获取WebSocket连接状态")
async def get_websocket_connections_status():
    """获取当前WebSocket连接状态"""
    try:
        websocket_manager = get_websocket_manager()
        status = await websocket_manager.get_connection_status()
        
        return {
            "success": True,
            "data": status
        }
        
    except Exception as e:
        logger.error(f"获取WebSocket连接状态失败: {e}", exc_info=True)
        return {
            "success": False,
            "error": f"获取WebSocket连接状态失败: {str(e)}"
        }


@router.post("/ws/broadcast/test", summary="测试广播消息")
async def test_broadcast_message(request: Dict[str, Any]):
    """测试向指定脚本的订阅者广播消息"""
    try:
        script_id = request.get("script_id")
        message = request.get("message", "测试消息")
        level = request.get("level", "info")
        
        if not script_id:
            return {"success": False, "error": "缺少script_id参数"}
        
        websocket_manager = get_websocket_manager()
        await websocket_manager.broadcast_script_log(script_id, level.upper(), message)
        
        return {
            "success": True,
            "message": f"测试消息已广播到脚本 {script_id} 的订阅者"
        }
        
    except Exception as e:
        logger.error(f"测试广播消息失败: {e}", exc_info=True)
        return {
            "success": False,
            "error": f"测试广播消息失败: {str(e)}"
        }