"""
语音命令路由
处理来自APP和PC端的语音指令
"""

from fastapi import APIRouter, WebSocket, WebSocketDisconnect, HTTPException
from pydantic import BaseModel
from typing import Optional, List, Dict, Any
import json
import logging
import asyncio

from services.ai_agent import process_voice_command, ai_agent
from services.ws_hub import ws_hub

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/voice", tags=["语音控制"])


def _map_action_to_device(action: dict) -> dict:
    """将 AI 解析的 action 转为设备端 execute.data 格式"""
    act = action.get("action", "")
    params = action.get("params") or {}
    if act == "open_app":
        return {"action": "app_start", "params": {"package": params.get("package", "")}}
    if act == "input_text":
        return {"action": "input", "params": {"text": params.get("text", ""), "clear": False}}
    if act == "key_event":
        keycode = (params.get("keycode") or "KEYCODE_BACK").lower()
        key = "back" if "back" in keycode else ("home" if "home" in keycode else "back")
        return {"action": "press_key", "params": {"key": key}}
    if act == "back":
        return {"action": "press_key", "params": {"key": "back"}}
    if act == "home":
        return {"action": "press_key", "params": {"key": "home"}}
    if act == "screenshot":
        return {"action": "screenshot", "params": params}
    return {"action": act, "params": params}


class VoiceCommandRequest(BaseModel):
    """语音命令请求"""
    text: str
    device_id: Optional[str] = None
    project_id: Optional[str] = None
    execute: bool = True  # 是否立即执行


class VoiceCommandResponse(BaseModel):
    """语音命令响应"""
    success: bool
    message: str
    text: str
    actions: List[Dict[str, Any]]
    executed: bool = False


@router.post("/command", response_model=VoiceCommandResponse)
async def voice_command(request: VoiceCommandRequest):
    """
    处理语音命令
    
    接收文本命令，解析意图，可选择立即执行
    
    示例：
    POST /api/v3/voice/command
    {
        "text": "打开微信",
        "device_id": "device_001",
        "execute": true
    }
    """
    # 解析命令
    result = await process_voice_command(request.text, request.device_id)
    
    executed = False
    
    if request.execute and result["success"] and request.device_id:
        try:
            for action in result["actions"]:
                payload = _map_action_to_device(action)
                command = {
                    "type": "execute",
                    "command_id": f"voice_{id(action)}",
                    "data": payload
                }
                await ws_hub.send_to_device(request.device_id, command)
                if action.get("action") == "wait":
                    wait_time = action.get("params", {}).get("seconds", 1)
                    await asyncio.sleep(min(max(wait_time, 0.5), 10))
            executed = True
        except Exception as e:
            logger.error(f"执行命令失败: {e}")
            result["message"] += f" (执行失败: {str(e)})"
    
    return VoiceCommandResponse(
        success=result["success"],
        message=result["message"],
        text=result["text"],
        actions=result["actions"],
        executed=executed
    )


@router.post("/parse")
async def parse_command(request: VoiceCommandRequest):
    """
    仅解析命令，不执行
    
    用于预览AI解析结果
    """
    result = await process_voice_command(request.text, request.device_id)
    return result


@router.websocket("/ws")
async def voice_websocket(websocket: WebSocket):
    """
    语音命令WebSocket
    
    用于PC端实时语音控制
    
    消息格式：
    发送: {"text": "打开微信", "device_id": "xxx"}
    接收: {"success": true, "actions": [...], "executed": true}
    """
    await websocket.accept()
    logger.info("PC语音控制连接已建立")
    
    try:
        while True:
            # 接收消息
            data = await websocket.receive_text()
            message = json.loads(data)
            
            text = message.get("text", "")
            device_id = message.get("device_id")
            execute = message.get("execute", True)
            
            if not text:
                await websocket.send_json({
                    "success": False,
                    "message": "请提供语音文本"
                })
                continue
            
            # 处理命令
            result = await process_voice_command(text, device_id)
            
            executed = False
            
            if execute and result["success"] and device_id:
                try:
                    for action in result["actions"]:
                        payload = _map_action_to_device(action)
                        command = {
                            "type": "execute",
                            "command_id": f"voice_ws_{id(action)}",
                            "data": payload
                        }
                        await ws_hub.send_to_device(device_id, command)
                        if action.get("action") == "wait":
                            wait_time = action.get("params", {}).get("seconds", 1)
                            await asyncio.sleep(min(max(wait_time, 0.5), 10))
                    executed = True
                except Exception as e:
                    logger.error(f"执行失败: {e}")
                    result["message"] += f" (执行失败: {str(e)})"
            
            # 返回结果
            result["executed"] = executed
            await websocket.send_json(result)
            
    except WebSocketDisconnect:
        logger.info("PC语音控制连接断开")
    except Exception as e:
        logger.error(f"WebSocket错误: {e}")


@router.get("/apps")
async def get_common_apps():
    """
    获取常用应用列表
    
    用于语音识别提示
    """
    return {
        "apps": [
            {"name": "微信", "package": "com.tencent.mm"},
            {"name": "抖音", "package": "com.ss.android.ugc.aweme"},
            {"name": "支付宝", "package": "com.eg.android.AlipayGphone"},
            {"name": "淘宝", "package": "com.taobao.taobao"},
            {"name": "微博", "package": "com.sina.weibo"},
            {"name": "QQ", "package": "com.tencent.mobileqq"},
            {"name": "设置", "package": "com.android.settings"},
            {"name": "相机", "package": "com.android.camera"},
            {"name": "浏览器", "package": "com.android.chrome"},
        ],
        "commands": [
            "打开微信",
            "返回",
            "回到桌面",
            "向上滑动",
            "向下滑动",
            "截图",
            "发送消息给xxx",
            "搜索xxx",
        ]
    }
