"""
工作手机SDK v3.0 - AI Agent路由
自然语言控制手机（支持 WebSocket Agent 和 ADB 直连双模式）
增强版：智能命令引擎，支持多步骤、坐标点击、复合命令
"""

from fastapi import APIRouter, HTTPException
from typing import Optional, List
from pydantic import BaseModel
import logging
import re
import time
import asyncio

from services.ws_hub import ws_hub
from services.device_manager import device_manager
from services.adb_device import adb_manager
from services.brain_skill_registry import SKILL_REGISTRY, registry_summary
from config import settings

router = APIRouter()
logger = logging.getLogger(__name__)

# ========== 常用 APP 包名映射（全量） ==========

APP_PACKAGES = {
    # 社交
    "微信": "com.tencent.mm", "wechat": "com.tencent.mm",
    "QQ": "com.tencent.mobileqq", "qq": "com.tencent.mobileqq",
    "飞书": "com.ss.android.lark", "lark": "com.ss.android.lark",
    "钉钉": "com.alibaba.android.rimet",
    "企业微信": "com.tencent.wework",
    # 短视频/内容
    "抖音": "com.ss.android.ugc.aweme", "douyin": "com.ss.android.ugc.aweme",
    "小红书": "com.xingin.xhs", "xhs": "com.xingin.xhs",
    "快手": "com.smile.gifmaker",
    "B站": "tv.danmaku.bili", "bilibili": "tv.danmaku.bili",
    # 电商
    "闲鱼": "com.taobao.idlefish", "xianyu": "com.taobao.idlefish",
    "淘宝": "com.taobao.taobao", "taobao": "com.taobao.taobao",
    "京东": "com.jingdong.app.mall", "jd": "com.jingdong.app.mall",
    "拼多多": "com.xunmeng.pinduoduo",
    # 支付/金融
    "支付宝": "com.eg.android.AlipayGphone", "alipay": "com.eg.android.AlipayGphone",
    # 系统/工具
    "设置": "com.android.settings", "settings": "com.android.settings",
    "相机": "com.android.camera2", "camera": "com.android.camera2",
    "浏览器": "com.android.chrome", "chrome": "com.android.chrome",
    "Chrome": "com.android.chrome",
    "电话": "com.google.android.dialer", "拨号": "com.google.android.dialer",
    "短信": "com.google.android.apps.messaging", "消息": "com.google.android.apps.messaging",
    "相册": "com.google.android.apps.photos", "photos": "com.google.android.apps.photos",
    "文件管理": "com.android.documentsui",
    "日历": "com.google.android.calendar",
    "计算器": "com.google.android.calculator",
    "时钟": "com.google.android.deskclock",
    "地图": "com.google.android.apps.maps", "maps": "com.google.android.apps.maps",
    # 终端
    "termux": "com.termux", "Termux": "com.termux", "终端": "com.termux",
    # 外卖/生活
    "美团": "com.sankuai.meituan",
    "饿了么": "me.ele",
    "高德": "com.autonavi.minimap", "高德地图": "com.autonavi.minimap",
    "滴滴": "com.sdu.didi.psnger",
}

# ========== 数据模型 ==========

class ExecuteTaskRequest(BaseModel):
    """执行任务请求"""
    device_id: str
    task: str
    llm_provider: str = "deepseek"  # deepseek/openai/ollama
    max_steps: int = 30


class ExecuteTaskResponse(BaseModel):
    """执行任务响应"""
    success: bool
    steps: List[str] = []
    duration_ms: int = 0
    error: Optional[str] = None


# ========== 智能命令引擎 ==========

def _execute_single(adb_dev, cmd: str) -> dict:
    """执行单条解析后的命令，返回 {success, step, detail}"""
    cmd = cmd.strip()
    if not cmd:
        return {"success": True, "step": "空命令跳过"}

    # --- 打开 APP ---
    for name, pkg in APP_PACKAGES.items():
        if cmd == name or cmd == f"打开{name}" or cmd.lower() == f"open {name.lower()}":
            r = adb_dev.start_app(pkg)
            return {"success": r.get("code") == 200, "step": f"打开 {name}", "detail": r}

    # 通过包名打开
    pkg_match = re.match(r"^(?:打开|启动|open)\s*(com\.\S+)", cmd)
    if pkg_match:
        pkg = pkg_match.group(1)
        r = adb_dev.start_app(pkg)
        return {"success": r.get("code") == 200, "step": f"打开 {pkg}", "detail": r}

    # --- 按键 ---
    if cmd in ("主页", "回主页", "回首页", "home", "Home", "HOME"):
        r = adb_dev.press_key("home")
        return {"success": r.get("code") == 200, "step": "Home", "detail": r}
    if cmd in ("返回", "back", "Back", "BACK"):
        r = adb_dev.press_key("back")
        return {"success": r.get("code") == 200, "step": "返回", "detail": r}
    if cmd in ("最近任务", "多任务", "recent", "Recent"):
        r = adb_dev.press_key("recent")
        return {"success": r.get("code") == 200, "step": "最近任务", "detail": r}
    if cmd in ("回车", "确认", "enter", "Enter"):
        r = adb_dev.press_key("enter")
        return {"success": r.get("code") == 200, "step": "回车", "detail": r}
    if cmd in ("音量加", "音量+", "volume_up"):
        r = adb_dev.press_key("volume_up")
        return {"success": r.get("code") == 200, "step": "音量+", "detail": r}
    if cmd in ("音量减", "音量-", "volume_down"):
        r = adb_dev.press_key("volume_down")
        return {"success": r.get("code") == 200, "step": "音量-", "detail": r}
    if cmd in ("锁屏", "电源", "power"):
        r = adb_dev.press_key("KEYCODE_POWER")
        return {"success": r.get("code") == 200, "step": "电源键", "detail": r}

    # --- 截图 ---
    if cmd in ("截图", "截屏", "screenshot"):
        r = adb_dev.screenshot()
        return {"success": r.get("code") == 200, "step": "截图", "detail": r}

    # --- 滑动 ---
    swipe_map = {
        "上滑": "up", "往上滑": "up", "向上滑": "up", "翻页": "up", "下一页": "up",
        "下滑": "down", "往下滑": "down", "向下滑": "down", "刷新": "down", "上一页": "down",
        "左滑": "left", "往左滑": "left", "向左滑": "left",
        "右滑": "right", "往右滑": "right", "向右滑": "right",
    }
    if cmd in swipe_map:
        r = adb_dev.swipe(swipe_map[cmd])
        return {"success": r.get("code") == 200, "step": cmd, "detail": r}

    # --- 坐标点击: "点击 540 1200" 或 "tap 540 1200" ---
    coord_match = re.match(r"(?:点击|tap|click)\s*(\d+)[,\s]+(\d+)", cmd)
    if coord_match:
        x, y = int(coord_match.group(1)), int(coord_match.group(2))
        r = adb_dev.click(x, y)
        return {"success": r.get("code") == 200, "step": f"点击坐标 ({x},{y})", "detail": r}

    # --- 纯坐标 "540,1200" 或 "540 1200" ---
    pure_coord = re.match(r"^(\d{2,4})[,\s]+(\d{2,4})$", cmd)
    if pure_coord:
        x, y = int(pure_coord.group(1)), int(pure_coord.group(2))
        r = adb_dev.click(x, y)
        return {"success": r.get("code") == 200, "step": f"点击坐标 ({x},{y})", "detail": r}

    # --- 点击文字 ---
    click_match = re.match(r"(?:点击|点|按|选择|找到|tap|click)\s*[「\"']?(.+?)[」\"']?\s*$", cmd)
    if click_match:
        text = click_match.group(1).strip()
        r = adb_dev.click_text(text)
        return {"success": r.get("code") == 200, "step": f"点击「{text}」", "detail": r}

    # --- 输入文字 ---
    input_match = re.match(r"(?:输入|打字|写|type|input|write)\s*[：:\s]*(.+)", cmd)
    if input_match:
        text = input_match.group(1).strip()
        r = adb_dev.input_text(text)
        return {"success": r.get("code") == 200, "step": f"输入「{text}」", "detail": r}

    # --- 等待 ---
    wait_match = re.match(r"(?:等待|等|wait|sleep)\s*(\d+)\s*(?:秒|s)?", cmd)
    if wait_match:
        secs = min(int(wait_match.group(1)), 30)  # 最多30秒
        time.sleep(secs)
        return {"success": True, "step": f"等待 {secs} 秒"}

    # --- 查看当前APP ---
    if cmd in ("当前APP", "当前应用", "current_app", "current"):
        r = adb_dev.current_app()
        return {"success": r.get("code") == 200, "step": "查看当前APP", "detail": r}

    # --- 已安装APP ---
    if cmd in ("已安装", "装了什么", "app列表", "list_apps"):
        r = adb_dev.installed_apps()
        return {"success": r.get("code") == 200, "step": "查看已安装APP", "detail": r}

    # --- UI树 ---
    if cmd in ("ui树", "UI树", "ui_tree", "界面分析"):
        r = adb_dev.get_ui_tree()
        return {"success": r.get("code") == 200, "step": "获取UI树", "detail": r}

    # --- 关闭APP ---
    close_match = re.match(r"(?:关闭|停止|杀掉|kill|stop)\s*(.+)", cmd)
    if close_match:
        app_name = close_match.group(1).strip()
        pkg = APP_PACKAGES.get(app_name, app_name)
        r = adb_dev.stop_app(pkg)
        return {"success": r.get("code") == 200, "step": f"关闭 {app_name}", "detail": r}

    return None  # 未匹配


def _execute_ai_action(adb_dev, action: dict) -> dict:
    """执行 AI 返回的单个操作"""
    act = action.get("action", "")
    steps = []

    if act == "open_app":
        app_name = action.get("app", "")
        pkg = APP_PACKAGES.get(app_name, app_name)
        # 如果还不是包名格式，尝试模糊匹配
        if "." not in pkg:
            for name, p in APP_PACKAGES.items():
                if name.lower() == app_name.lower() or app_name.lower() in name.lower():
                    pkg = p
                    break
        r = adb_dev.start_app(pkg)
        return {"success": r.get("code") == 200, "step": f"打开 {app_name}", "detail": r}

    elif act == "click":
        if "text" in action:
            r = adb_dev.click_text(action["text"])
            return {"success": r.get("code") == 200, "step": f"点击「{action['text']}」", "detail": r}
        elif "x" in action and "y" in action:
            r = adb_dev.click(int(action["x"]), int(action["y"]))
            return {"success": r.get("code") == 200, "step": f"点击 ({action['x']},{action['y']})", "detail": r}

    elif act == "input":
        text = action.get("text", "")
        r = adb_dev.input_text(text)
        return {"success": r.get("code") == 200, "step": f"输入「{text}」", "detail": r}

    elif act == "back":
        r = adb_dev.press_key("back")
        return {"success": r.get("code") == 200, "step": "返回", "detail": r}

    elif act == "home":
        r = adb_dev.press_key("home")
        return {"success": r.get("code") == 200, "step": "主页", "detail": r}

    elif act == "swipe":
        direction = action.get("direction", "up")
        r = adb_dev.swipe(direction)
        return {"success": r.get("code") == 200, "step": f"滑动{direction}", "detail": r}

    elif act == "wait":
        secs = min(int(action.get("seconds", 1)), 3)  # AI 等待最多3秒
        time.sleep(secs)
        return {"success": True, "step": f"等待 {secs} 秒"}

    elif act == "screenshot":
        r = adb_dev.screenshot()
        return {"success": r.get("code") == 200, "step": "截图", "detail": r}

    elif act == "key_event":
        key = action.get("key", "")
        key_map = {
            "enter": "enter", "回车": "enter",
            "back": "back", "返回": "back",
            "home": "home", "主页": "home",
            "tab": "tab",
            "delete": "del", "删除": "del",
            "search": "search", "搜索": "search",
        }
        key_name = key_map.get(key.lower(), key)
        r = adb_dev.press_key(key_name)
        return {"success": r.get("code") == 200, "step": f"按键 {key}", "detail": r}

    elif act == "close_app":
        app_name = action.get("app", "")
        pkg = APP_PACKAGES.get(app_name, app_name)
        r = adb_dev.stop_app(pkg)
        return {"success": r.get("code") == 200, "step": f"关闭 {app_name}", "detail": r}

    elif act == "shell":
        # 执行 ADB shell 命令（用于系统设置等高级操作）
        command = action.get("command", "")
        if not command:
            return {"success": False, "step": "shell 命令为空"}
        # 安全检查：禁止危险命令
        dangerous = ["rm -rf /", "format", "wipe", "factory_reset", "reboot"]
        if any(d in command.lower() for d in dangerous):
            return {"success": False, "step": f"危险命令被阻止: {command}"}
        try:
            r = adb_dev._shell(command, timeout=10)
            return {"success": True, "step": f"执行: {command}", "detail": {"output": r}}
        except Exception as e:
            return {"success": False, "step": f"shell 失败: {command}", "detail": {"error": str(e)}}

    # 未知操作：尝试智能回退
    logger.warning(f"[AI] 未知操作类型: {act}，尝试智能回退")

    # 回退策略1：如果有 app 字段，当作 open_app
    if "app" in action:
        app_name = action["app"]
        pkg = APP_PACKAGES.get(app_name, app_name)
        if "." not in pkg:
            for name, p in APP_PACKAGES.items():
                if name.lower() == app_name.lower():
                    pkg = p
                    break
        r = adb_dev.start_app(pkg)
        return {"success": r.get("code") == 200, "step": f"打开 {app_name} (回退)", "detail": r}

    # 回退策略2：如果有 text 字段，当作 click
    if "text" in action:
        r = adb_dev.click_text(action["text"])
        return {"success": r.get("code") == 200, "step": f"点击「{action['text']}」(回退)", "detail": r}

    # 回退策略3：如果有 command 字段，当作 shell
    if "command" in action:
        try:
            r = adb_dev._shell(action["command"], timeout=10)
            return {"success": True, "step": f"执行: {action['command']} (回退)"}
        except Exception:
            pass

    return {"success": False, "step": f"未知操作: {act}"}


def _parse_and_execute_adb(device_id: str, task: str) -> dict:
    """
    智能命令引擎：解析自然语言，支持单步和多步命令。
    用 "然后" / "，" / ";" 分隔多步骤。
    如果无法精确匹配，尝试智能推断。
    """
    adb_dev = adb_manager.get_device(device_id)
    if not adb_dev:
        return {"success": False, "error": f"ADB 设备 {device_id} 不可用"}

    task = task.strip()
    if not task:
        return {"success": False, "error": "命令为空"}

    # 分割多步命令（支持 "然后"、"，"、"；"、";"、"→"、"->"）
    parts = re.split(r"[;；]\s*|然后\s*|之后\s*|→\s*|->\s*", task)
    # 如果只有一段且包含逗号分隔的完整子命令，也拆分
    if len(parts) == 1 and "，" in task:
        # 只在确实是多个命令时才按逗号拆（不拆坐标等）
        potential = re.split(r"[，]\s*", task)
        if len(potential) > 1 and all(len(p.strip()) > 1 for p in potential):
            parts = potential

    all_steps = []
    all_success = True
    last_detail = None
    needs_ai_parts = []

    for part in parts:
        part = part.strip()
        if not part:
            continue

        result = _execute_single(adb_dev, part)

        if result is None:
            # 智能推断：尝试作为 APP 名打开
            for name, pkg in APP_PACKAGES.items():
                if name.lower() == part.lower() or name == part:
                    r = adb_dev.start_app(pkg)
                    result = {"success": r.get("code") == 200, "step": f"打开 {name}", "detail": r}
                    break

        if result is None:
            # 智能推断：纯数字当成等待秒数（<=10）或当成文字点击
            if part.isdigit():
                num = int(part)
                if num <= 10:
                    time.sleep(num)
                    result = {"success": True, "step": f"等待 {num} 秒"}
                else:
                    # 当作文字点击
                    r = adb_dev.click_text(part)
                    result = {"success": r.get("code") == 200, "step": f"点击「{part}」", "detail": r}

        if result is None:
            # 最终尝试：当作要点击的文字（UI上找这个文字）
            r = adb_dev.click_text(part)
            if r.get("code") == 200:
                result = {"success": True, "step": f"点击「{part}」", "detail": r}
            else:
                # 标记为需要 AI 处理
                result = {"success": False, "step": part, "needs_ai": True}

        all_steps.append(result.get("step", part))
        last_detail = result.get("detail")
        if not result.get("success"):
            if result.get("needs_ai"):
                # 收集需要 AI 处理的部分
                needs_ai_parts.append(part)
            else:
                all_success = False
                if result.get("error"):
                    all_steps[-1] += f" (失败: {result['error']})"

        # 多步之间短暂等待
        if len(parts) > 1:
            time.sleep(0.5)

    # 如果有需要 AI 处理的部分，在最后返回时标记
    if needs_ai_parts:
        return {
            "success": all_success if not needs_ai_parts else None,  # None = 需要 AI
            "steps": all_steps,
            "detail": last_detail,
            "total_steps": len(all_steps),
            "needs_ai": True,
            "ai_query": task,  # 把原始完整命令传给 AI
        }

    return {
        "success": all_success,
        "steps": all_steps,
        "detail": last_detail,
        "total_steps": len(all_steps),
    }


# ========== AI Agent接口 ==========

@router.post("/agent/execute", response_model=dict)
async def execute_task(req: ExecuteTaskRequest):
    """
    执行自然语言任务（自动选择 WebSocket Agent 或 ADB 直连模式）
    
    示例任务：
    - "打开微信"
    - "回主页"
    - "点击 发现"
    - "输入 你好"
    """

    # 优先使用 WebSocket Agent（功能更强）
    if ws_hub.is_online(req.device_id):
        if req.llm_provider == "deepseek" and not settings.DEEPSEEK_API_KEY:
            raise HTTPException(status_code=400, detail="未配置DEEPSEEK_API_KEY")

        result = await ws_hub.send_command(req.device_id, {
            "type": "agent_execute",
            "data": {
                "task": req.task,
                "llm_provider": req.llm_provider,
                "max_steps": req.max_steps
            }
        }, timeout=120)

        if result.get("code") != 200:
            return {
                "code": result.get("code", 500),
                "data": {"success": False, "error": result.get("message", "执行失败")}
            }

        try:
            await device_manager.log_command(req.device_id, "agent.execute", {"task": req.task}, result)
        except Exception:
            pass

        return {"code": 200, "data": result.get("data", {})}

    # 降级：ADB 本地直连执行
    adb_dev = adb_manager.get_device(req.device_id)
    if adb_dev and adb_dev.is_online():
        logger.info(f"[agent] ADB 直连执行: {req.device_id} -> {req.task}")
        result = _parse_and_execute_adb(req.device_id, req.task)

        # 如果模式匹配失败，调用 AI 引擎
        if result.get("needs_ai"):
            logger.info(f"[agent] 模式匹配失败，调用 AI: {req.task}")
            from services.ai_command import ai_engine

            # 获取当前屏幕上下文
            context = None
            try:
                app_info = adb_dev.current_app()
                if app_info.get("code") == 200:
                    context = {"current_app": app_info["data"].get("package", "unknown")}
            except Exception:
                pass

            ai_actions = await ai_engine.parse(req.task, context)
            if ai_actions:
                ai_steps = []
                ai_success = True
                for action in ai_actions:
                    r = _execute_ai_action(adb_dev, action)
                    ai_steps.append(r.get("step", str(action)))
                    if not r.get("success"):
                        ai_success = False
                    time.sleep(0.5)

                return {"code": 200, "data": {
                    "success": ai_success,
                    "steps": ai_steps,
                    "total_steps": len(ai_steps),
                    "engine": "ai",
                }}
            else:
                # AI 也失败了
                return {"code": 200, "data": {
                    "success": False,
                    "error": f"无法理解命令: {req.task}",
                    "hint": "AI 引擎无法解析。试试: 打开微信/点击XXX/输入XXX/截图 等",
                }}

        return {"code": 200, "data": result}

    raise HTTPException(status_code=503, detail="设备不在线（WebSocket 和 ADB 均不可用）")


@router.get("/agent/status/{device_id}", response_model=dict)
async def get_agent_status(device_id: str):
    """获取Agent状态"""
    
    if not ws_hub.is_online(device_id):
        return {
            "code": 200,
            "data": {
                "status": "offline",
                "device_id": device_id
            }
        }
    
    result = await ws_hub.send_command(device_id, {
        "type": "agent_status"
    }, timeout=5)
    
    return {
        "code": 200,
        "data": result.get("data", {"status": "ready"})
    }


@router.post("/agent/stop/{device_id}", response_model=dict)
async def stop_agent(device_id: str):
    """停止正在执行的Agent任务"""
    
    if not ws_hub.is_online(device_id):
        raise HTTPException(status_code=503, detail="设备不在线")
    
    result = await ws_hub.send_command(device_id, {
        "type": "agent_stop"
    }, timeout=5)
    
    return {
        "code": 200,
        "data": {"stopped": True}
    }


# ========== AI 引擎端点 ==========

@router.get("/ai/status", response_model=dict)
async def ai_status():
    """获取 AI 引擎状态"""
    from services.ai_command import ai_engine
    status = await ai_engine.get_status()
    return {"code": 200, "data": status}


class AIChatRequest(BaseModel):
    message: str
    device_id: Optional[str] = None


@router.post("/ai/chat", response_model=dict)
async def ai_chat(req: AIChatRequest):
    """
    AI 对话控制手机 —— 核心端点
    用户输入自然语言，AI 返回并执行操作
    """
    from services.ai_command import ai_engine

    t0 = time.time()

    # 1. 获取设备（跳过 current_app 避免 3 秒开销，AI 不需要这个上下文）
    context = None
    adb_dev = None
    if req.device_id:
        adb_dev = adb_manager.get_device(req.device_id)

    t1 = time.time()
    logger.info(f"[ai_chat] 设备获取: {t1-t0:.2f}s")

    # 2. AI 解析
    actions = await ai_engine.parse(req.message, context)

    t2 = time.time()
    logger.info(f"[ai_chat] AI 解析: {t2-t1:.2f}s ({len(actions)} 步)")

    if not actions:
        return {"code": 200, "data": {
            "success": False,
            "message": f"AI 无法解析: {req.message}",
            "actions": [],
        }}

    # 3. 如果有设备，自动执行（放到线程池避免阻塞事件循环）
    executed_steps = []
    if adb_dev:
        def _run_actions():
            results = []
            for i, action in enumerate(actions):
                ta = time.time()
                try:
                    r = _execute_ai_action(adb_dev, action)
                    results.append(r)
                    tb = time.time()
                    logger.info(f"[ai_chat] 步骤{i+1} {action.get('action')}: {tb-ta:.2f}s {'✅' if r.get('success') else '❌'}")
                    # wait 动作已自带延时，其他操作短暂间隔
                    if action.get("action") != "wait":
                        time.sleep(0.2)
                except Exception as e:
                    results.append({"success": False, "step": f"异常: {e}"})
                    logger.error(f"[ai_chat] 步骤{i+1} 异常: {e}")
            return results
        
        try:
            executed_steps = await asyncio.wait_for(
                asyncio.to_thread(_run_actions),
                timeout=20.0  # 总执行时间上限
            )
        except asyncio.TimeoutError:
            executed_steps.append({"success": False, "step": "执行超时（20秒上限）"})
            logger.warning(f"[ai_chat] 执行超时！")

    t3 = time.time()
    logger.info(f"[ai_chat] 总耗时: {t3-t0:.2f}s")

    return {"code": 200, "data": {
        "success": all(s.get("success") for s in executed_steps) if executed_steps else True,
        "message": f"AI 解析 {len(actions)} 步" + (f"，已执行 {len(executed_steps)} 步" if executed_steps else ""),
        "actions": actions,
        "executed": executed_steps,
        "engine": "ai",
    }}


# ========== AI Brain 技能注册表 ==========
# 真源: sdk/app/services/brain_skill_registry.py

@router.get("/ai/brain/skill-registry")
async def get_skill_registry():
    """AI Brain 技能注册表 — 返回所有可用技能、模块、操作的完整清单"""
    return {
        "code": 200,
        "data": {
            "skills": SKILL_REGISTRY,
            "summary": registry_summary(),
        },
    }


@router.get("/ai/brain/dashboard")
async def ai_brain_dashboard():
    """AI Brain 仪表盘 — 汇总 AI Brain 在全部设备上的状态"""
    online_devices = ws_hub.get_online_devices() if hasattr(ws_hub, 'get_online_devices') else []
    try:
        all_devices = await device_manager.get_all_devices() if hasattr(device_manager, 'get_all_devices') else []
    except Exception:
        all_devices = []
    try:
        adb_count = len(adb_manager.scan_devices()) if hasattr(adb_manager, 'scan_devices') else 0
    except Exception:
        adb_count = 0

    total_skills = len(SKILL_REGISTRY)
    total_actions = sum(len(a) for s in SKILL_REGISTRY.values() for a in s["modules"].values())

    channels = {
        "frida_hook": {"name": "Frida Hook", "priority": 1, "desc": "直接调用 APP 内部方法，50-200ms"},
        "u2_automation": {"name": "uiautomator2", "priority": 2, "desc": "UI 自动化模拟操作，2-15s"},
        "adb_shell": {"name": "ADB Shell", "priority": 3, "desc": "ADB 命令控制，1-10s"},
        "ai_agent": {"name": "AI Agent", "priority": 4, "desc": "LLM 意图解析 + 步骤执行"},
    }

    return {
        "code": 200,
        "data": {
            "devices": {
                "ws_online": len(online_devices) if isinstance(online_devices, list) else online_devices,
                "adb_online": adb_count,
                "total_registered": len(all_devices) if isinstance(all_devices, list) else all_devices,
            },
            "skills": {"total_skills": total_skills, "total_actions": total_actions},
            "channels": channels,
            "ai_brain": {
                "version": "1.0.0",
                "architecture": "v3.1 Frida优先 → u2兜底",
                "heartbeat_interval": 60,
                "features": [
                    "心跳驱动自主决策",
                    "离线自主运行模式",
                    "Frida 优先通道",
                    "任务队列管理",
                    "常驻指令执行",
                    "离线缓冲上传",
                ],
            },
        },
    }


@router.post("/ai/brain/execute-script")
async def execute_brain_script(request: dict):
    """
    AI Brain 脚本执行器 — 向指定设备发送技能脚本
    Body: {device_id, script, action, params, channel?}
    """
    device_id = request.get("device_id")
    script = request.get("script")
    action = request.get("action")
    params = request.get("params", {})
    channel = request.get("channel", "auto")

    if not device_id or not script or not action:
        raise HTTPException(status_code=400, detail="device_id, script, action 必填")

    if ws_hub.is_online(device_id):
        cmd = {
            "type": "execute",
            "script": script,
            "action": action,
            "params": params,
            "channel": channel,
        }
        result = await ws_hub.send_command(device_id, cmd, timeout=60)
        return {"code": 200, "data": result}

    adb_dev = adb_manager.get_device(device_id)
    if adb_dev and adb_dev.is_online():
        raise HTTPException(status_code=501, detail="ADB 模式暂不支持直接技能执行，请通过 /agent/execute 调用")

    raise HTTPException(status_code=503, detail=f"设备 {device_id} 不在线")


@router.post("/ai/brain/batch-execute")
async def batch_execute_script(request: dict):
    """
    AI Brain 批量脚本执行 — 向多台设备同时发送相同脚本
    Body: {device_ids: [...], script, action, params}
    """
    device_ids = request.get("device_ids", [])
    script = request.get("script")
    action = request.get("action")
    params = request.get("params", {})

    if not device_ids or not script or not action:
        raise HTTPException(status_code=400, detail="device_ids, script, action 必填")

    results = {}
    tasks = []
    for did in device_ids:
        if ws_hub.is_online(did):
            cmd = {"type": "execute", "script": script, "action": action, "params": params}
            tasks.append((did, ws_hub.send_command(did, cmd, timeout=60)))
        else:
            results[did] = {"code": 503, "message": "设备不在线"}

    for did, task in tasks:
        try:
            result = await task
            results[did] = result
        except Exception as e:
            results[did] = {"code": 500, "message": str(e)}

    return {
        "code": 200,
        "data": {
            "results": results,
            "total": len(device_ids),
            "success": sum(1 for r in results.values() if isinstance(r, dict) and r.get("code") == 200),
        },
    }


# ========== OpenAI 兼容代理（给 OpenClaw 用） ==========

@router.post("/v1/chat/completions", response_model=dict)
async def openai_proxy(request: dict):
    """
    OpenAI 兼容端点 —— 代理到本地 Ollama
    OpenClaw 可以配置 baseUrl 指向这里
    """
    import httpx
    from services.ai_command import OLLAMA_URL, OLLAMA_MODEL

    model = request.get("model", OLLAMA_MODEL)
    messages = request.get("messages", [])
    max_tokens = request.get("max_tokens", 200)

    try:
        async with httpx.AsyncClient(timeout=60.0) as c:
            r = await c.post(f"{OLLAMA_URL}/v1/chat/completions", json={
                "model": model,
                "messages": messages,
                "max_tokens": max_tokens,
                "stream": False,
            })
            return r.json()
    except Exception as e:
        return {
            "error": {"message": str(e), "type": "proxy_error"},
            "choices": [],
        }
