"""
服务端编排：卡若 AI 网关决策 → WebSocket 下发到手机 Agent 执行。
手机无需本地 ai_api_key，统一走平常使用的 /api/gateway/chat。
"""

from __future__ import annotations

import json
import logging
import os
from pathlib import Path
from typing import Any, Dict, Optional
import importlib.util

logger = logging.getLogger(__name__)

_brain: Optional[Any] = None


def _load_ai_brain_class():
    path = Path(__file__).resolve().parent.parent / "agent" / "ai_brain.py"
    spec = importlib.util.spec_from_file_location("workphone_device_ai_brain", path)
    if spec is None or spec.loader is None:
        raise ImportError(f"无法加载 AIBrain: {path}")
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod.AIBrain


from services.ws_hub import ws_hub

_AGENT_CFG_CANDIDATES = [
    Path(__file__).resolve().parent.parent / "agent" / "config.json",
    Path(__file__).resolve().parents[2] / "agent" / "config.json",
]


def _load_ai_cfg() -> Dict[str, Any]:
    for path in _AGENT_CFG_CANDIDATES:
        try:
            if path.is_file():
                with open(path, encoding="utf-8") as f:
                    data = json.load(f)
                return data.get("ai_brain") or {}
        except Exception as exc:
            logger.warning("读取 %s 失败: %s", path, exc)
    return {}


def get_karuo_brain(force_reload: bool = False) -> Optional[Any]:
    global _brain
    if _brain is not None and not force_reload:
        return _brain
    _brain = None
    cfg = _load_ai_cfg()
    api_key = (
        os.environ.get("KARUO_API_KEY")
        or os.environ.get("WP_AI_API_KEY")
        or os.environ.get("AI_BRAIN_API_KEY")
        or cfg.get("api_key")
        or ""
    ).strip()
    api_url = (
        os.environ.get("KARUO_API_URL")
        or os.environ.get("WP_AI_API_URL")
        or os.environ.get("AI_BRAIN_API_URL")
        or cfg.get("api_url")
        or "http://127.0.0.1:3102"
    ).strip()
    # 本机直跑 SDK（非 Docker 容器内）时 host.docker.internal 不可达
    if "host.docker.internal" in api_url and not os.path.exists("/.dockerenv"):
        api_url = api_url.replace("host.docker.internal", "127.0.0.1")
    if not api_key:
        logger.warning("卡若 AI Brain 未配置 api_key（sdk/agent/config.json）")
        return None
    _brain = _load_ai_brain_class()(
        ai_api_url=api_url,
        ai_api_key=api_key,
        ai_model=cfg.get("model") or "auto",
        brain_interval=int(cfg.get("brain_interval") or 60),
        standing_orders=cfg.get("standing_orders") or [],
        enabled=True,
    )
    return _brain


def device_status(device_id: str) -> Dict[str, Any]:
    info = ws_hub.get_device_info(device_id) or {}
    qs = info.get("quick_status") or info.get("last_status") or {}
    return {
        "device_id": device_id,
        "online": ws_hub.is_online(device_id),
        "model": info.get("model"),
        "capabilities": info.get("capabilities") or [],
        "u2": qs.get("u2", False),
        "frida": info.get("frida_available", False),
        "agent_version": info.get("agent_version"),
    }


async def chat_and_execute_on_device(
    device_id: str,
    instruction: str,
    timeout: int = 120,
) -> Dict[str, Any]:
    brain = get_karuo_brain()
    if not brain:
        return {"code": 503, "message": "卡若 AI 未配置（agent/config.json ai_brain.api_key）"}
    if not ws_hub.is_online(device_id):
        return {"code": 503, "message": "设备不在线"}

    async def execute_fn(script: str, action: str, params: Dict[str, Any]) -> Dict[str, Any]:
        return await ws_hub.send_command(
            device_id,
            {
                "type": "execute",
                "data": {
                    "script": script,
                    "action": action,
                    "params": params or {},
                    "channel": "auto",
                },
            },
            timeout=timeout,
        )

    result = await brain.chat_and_execute(instruction.strip(), device_status(device_id), execute_fn)
    result["device_id"] = device_id
    result["orchestrator"] = "server_karuo_gateway"
    return result
