"""
设备WebSocket路由
接收Android Agent APP的连接和命令
"""

from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from typing import Dict, Optional
import json
import asyncio
import logging
from datetime import datetime

router = APIRouter(tags=["WebSocket"])
logger = logging.getLogger(__name__)


class DeviceConnectionManager:
    """
    设备连接管理器
    管理所有连接的Android设备
    """
    
    def __init__(self):
        # device_id -> WebSocket连接
        self.active_connections: Dict[str, WebSocket] = {}
        # device_id -> 设备信息
        self.device_info: Dict[str, dict] = {}
        # project_id -> [device_id, ...]
        self.project_devices: Dict[str, list] = {}
    
    async def connect(self, device_id: str, websocket: WebSocket):
        """接受新连接"""
        await websocket.accept()
        self.active_connections[device_id] = websocket
        logger.info(f"设备连接: {device_id}")
    
    def disconnect(self, device_id: str):
        """断开连接"""
        if device_id in self.active_connections:
            del self.active_connections[device_id]
        if device_id in self.device_info:
            project_id = self.device_info[device_id].get("project_id")
            if project_id and project_id in self.project_devices:
                if device_id in self.project_devices[project_id]:
                    self.project_devices[project_id].remove(device_id)
            del self.device_info[device_id]
        logger.info(f"设备断开: {device_id}")
    
    def register_device(self, device_id: str, info: dict):
        """注册设备信息"""
        self.device_info[device_id] = {
            **info,
            "connected_at": datetime.now().isoformat(),
            "last_heartbeat": datetime.now().isoformat()
        }
        
        # 添加到项目
        project_id = info.get("project_id")
        if project_id:
            if project_id not in self.project_devices:
                self.project_devices[project_id] = []
            if device_id not in self.project_devices[project_id]:
                self.project_devices[project_id].append(device_id)
        
        logger.info(f"设备注册: {device_id}, 项目: {project_id}")
    
    def update_heartbeat(self, device_id: str):
        """更新心跳时间"""
        if device_id in self.device_info:
            self.device_info[device_id]["last_heartbeat"] = datetime.now().isoformat()
    
    async def send_to_device(self, device_id: str, message: dict) -> bool:
        """发送消息到指定设备"""
        if device_id in self.active_connections:
            try:
                await self.active_connections[device_id].send_json(message)
                return True
            except Exception as e:
                logger.error(f"发送失败: {device_id}, {e}")
                return False
        return False
    
    async def broadcast_to_project(self, project_id: str, message: dict):
        """广播消息到项目下所有设备"""
        if project_id in self.project_devices:
            for device_id in self.project_devices[project_id]:
                await self.send_to_device(device_id, message)
    
    def get_device(self, device_id: str) -> Optional[dict]:
        """获取设备信息"""
        return self.device_info.get(device_id)
    
    def get_project_devices(self, project_id: str) -> list:
        """获取项目下所有设备"""
        device_ids = self.project_devices.get(project_id, [])
        return [self.device_info[did] for did in device_ids if did in self.device_info]
    
    def get_all_devices(self) -> list:
        """获取所有设备"""
        return list(self.device_info.values())
    
    def is_connected(self, device_id: str) -> bool:
        """检查设备是否在线"""
        return device_id in self.active_connections


# 全局连接管理器
manager = DeviceConnectionManager()


@router.websocket("/ws/device/{device_id}")
async def websocket_endpoint(websocket: WebSocket, device_id: str):
    """
    设备WebSocket连接端点
    
    消息类型:
    - register: 设备注册
    - heartbeat: 心跳
    - result: 命令执行结果
    """
    await manager.connect(device_id, websocket)
    
    try:
        while True:
            data = await websocket.receive_json()
            msg_type = data.get("type")
            
            if msg_type == "register":
                # 设备注册
                manager.register_device(device_id, data)
                await websocket.send_json({
                    "type": "registered",
                    "device_id": device_id,
                    "message": "注册成功"
                })
            
            elif msg_type == "heartbeat":
                # 心跳
                manager.update_heartbeat(device_id)
                await websocket.send_json({
                    "type": "pong",
                    "timestamp": datetime.now().timestamp() * 1000
                })
            
            elif msg_type == "result":
                # 命令执行结果
                command_id = data.get("command_id")
                logger.info(f"命令结果: {command_id}, 成功: {data.get('success')}")
                # 这里可以存储结果或通知其他系统
            
            else:
                logger.warning(f"未知消息类型: {msg_type}")
    
    except WebSocketDisconnect:
        manager.disconnect(device_id)
    except Exception as e:
        logger.error(f"WebSocket错误: {device_id}, {e}")
        manager.disconnect(device_id)


# ========== REST API接口 ==========

@router.get("/api/v3/devices")
async def list_devices():
    """获取所有在线设备"""
    return {
        "success": True,
        "devices": manager.get_all_devices(),
        "total": len(manager.get_all_devices())
    }


@router.get("/api/v3/devices/{device_id}")
async def get_device(device_id: str):
    """获取指定设备信息"""
    device = manager.get_device(device_id)
    if device:
        return {
            "success": True,
            "device": device,
            "online": manager.is_connected(device_id)
        }
    return {"success": False, "message": "设备不存在"}


@router.get("/api/v3/projects/{project_id}/devices")
async def get_project_devices(project_id: str):
    """获取项目下所有设备"""
    devices = manager.get_project_devices(project_id)
    return {
        "success": True,
        "project_id": project_id,
        "devices": devices,
        "total": len(devices)
    }


@router.post("/api/v3/devices/{device_id}/execute")
async def execute_command(device_id: str, command: dict):
    """
    向设备发送执行命令
    
    请求体:
    {
        "action": "open_app",
        "params": {"package": "com.tencent.mm"}
    }
    """
    if not manager.is_connected(device_id):
        return {"success": False, "message": "设备离线"}
    
    command_id = f"cmd_{datetime.now().timestamp()}"
    message = {
        "type": "execute",
        "command_id": command_id,
        "action": command.get("action"),
        "params": command.get("params", {})
    }
    
    success = await manager.send_to_device(device_id, message)
    
    return {
        "success": success,
        "command_id": command_id,
        "message": "命令已发送" if success else "发送失败"
    }


@router.post("/api/v3/projects/{project_id}/broadcast")
async def broadcast_to_project(project_id: str, command: dict):
    """向项目下所有设备广播命令"""
    command_id = f"cmd_{datetime.now().timestamp()}"
    message = {
        "type": "execute",
        "command_id": command_id,
        "action": command.get("action"),
        "params": command.get("params", {})
    }
    
    await manager.broadcast_to_project(project_id, message)
    
    devices = manager.get_project_devices(project_id)
    return {
        "success": True,
        "command_id": command_id,
        "devices_count": len(devices),
        "message": f"已广播到 {len(devices)} 台设备"
    }
