"""
工作手机SDK v3.0 - 外部对接网关
支持三种对接形式：REST API / OpenAI Compatible / MCP Protocol

阿机负责 · 阿桥对接
"""

from fastapi import APIRouter, HTTPException, Request, Depends
from pydantic import BaseModel, Field
from typing import Optional, List, Any
import asyncio
import logging
import time
import json

from services.ws_hub import ws_hub
from services.adb_device import adb_manager
from services.device_manager import device_manager

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


# ═══════════════════════════════════════════════
# 一、OpenAI Compatible API（AI 对接）
# ═══════════════════════════════════════════════

class ChatMessage(BaseModel):
    role: str = "user"
    content: str

class ChatRequest(BaseModel):
    model: str = "workphone-agent"
    messages: List[ChatMessage]
    device_id: Optional[str] = None
    stream: bool = False
    temperature: float = 0.7

class ChatChoice(BaseModel):
    index: int = 0
    message: ChatMessage
    finish_reason: str = "stop"

class ChatUsage(BaseModel):
    prompt_tokens: int = 0
    completion_tokens: int = 0
    total_tokens: int = 0

class ChatResponse(BaseModel):
    id: str = "chatcmpl-workphone"
    object: str = "chat.completion"
    created: int = 0
    model: str = "workphone-agent"
    choices: List[ChatChoice] = []
    usage: ChatUsage = ChatUsage()


@router.post("/gateway/v1/chat/completions", tags=["外部对接网关"])
async def openai_compatible_chat(req: ChatRequest):
    """
    OpenAI 兼容的 Chat API —— 外部程序可像调用 GPT 一样控制手机。
    
    用法：把 base_url 改为 http://服务器:8899/api/v3/gateway/v1，
    即可用任何 OpenAI SDK 直接对接。
    """
    user_msg = next((m.content for m in reversed(req.messages) if m.role == "user"), "")
    if not user_msg:
        raise HTTPException(400, "messages 中无 user 消息")

    device_id = req.device_id
    if not device_id:
        devices = list(ws_hub.connections.keys())
        if not devices:
            adb_devs = await adb_manager.async_scan_devices()
            devices = adb_devs
        device_id = devices[0] if devices else None

    result_text = ""
    executed_steps = []

    try:
        from services import ai_agent as ai_agent_service
        ai_result = await ai_agent_service.execute_ai_command(
            device_id=device_id or "none",
            command=user_msg,
            mode="ai"
        )
        if isinstance(ai_result, dict):
            result_text = ai_result.get("message", ai_result.get("response", str(ai_result)))
            executed_steps = ai_result.get("executed", [])
        else:
            result_text = str(ai_result)
    except Exception as e:
        result_text = f"执行失败: {e}"

    response_content = result_text
    if executed_steps:
        steps_text = "\n".join(
            f"{'✅' if s.get('success') else '❌'} {s.get('step', '未知步骤')}"
            for s in executed_steps
        )
        response_content = f"{result_text}\n\n执行步骤:\n{steps_text}"

    return ChatResponse(
        id=f"chatcmpl-wp-{int(time.time())}",
        created=int(time.time()),
        model=req.model,
        choices=[ChatChoice(
            message=ChatMessage(role="assistant", content=response_content)
        )],
        usage=ChatUsage(
            prompt_tokens=len(user_msg),
            completion_tokens=len(response_content),
            total_tokens=len(user_msg) + len(response_content)
        ),
    )


@router.get("/gateway/v1/models", tags=["外部对接网关"])
async def list_models():
    """OpenAI 兼容 —— 列出可用模型"""
    return {
        "object": "list",
        "data": [
            {
                "id": "workphone-agent",
                "object": "model",
                "created": 1700000000,
                "owned_by": "workphone-sdk",
                "description": "工作手机 AI Agent — 自然语言控制手机"
            },
            {
                "id": "workphone-adb",
                "object": "model",
                "created": 1700000000,
                "owned_by": "workphone-sdk",
                "description": "ADB 直控模式 — 精确设备操作"
            },
        ]
    }


# ═══════════════════════════════════════════════
# 二、MCP Protocol（MCP 对接）
# ═══════════════════════════════════════════════

MCP_TOOLS = [
    {
        "name": "send_message",
        "description": "通过微信发送消息给指定联系人",
        "inputSchema": {
            "type": "object",
            "properties": {
                "device_id": {"type": "string", "description": "设备ID"},
                "to": {"type": "string", "description": "接收人昵称或备注名"},
                "content": {"type": "string", "description": "消息内容"},
                "platform": {"type": "string", "default": "wechat"}
            },
            "required": ["to", "content"]
        }
    },
    {
        "name": "take_screenshot",
        "description": "对手机截屏，返回当前屏幕画面",
        "inputSchema": {
            "type": "object",
            "properties": {
                "device_id": {"type": "string", "description": "设备ID"}
            }
        }
    },
    {
        "name": "open_app",
        "description": "打开手机上的APP",
        "inputSchema": {
            "type": "object",
            "properties": {
                "device_id": {"type": "string", "description": "设备ID"},
                "app_name": {"type": "string", "description": "APP名称: wechat/douyin/xhs/xianyu"}
            },
            "required": ["app_name"]
        }
    },
    {
        "name": "get_device_status",
        "description": "获取设备的实时状态信息（电量、网络、当前APP等）",
        "inputSchema": {
            "type": "object",
            "properties": {
                "device_id": {"type": "string", "description": "设备ID"}
            }
        }
    },
    {
        "name": "list_devices",
        "description": "列出所有已连接的设备及其状态",
        "inputSchema": {"type": "object", "properties": {}}
    },
    {
        "name": "execute_task",
        "description": "用自然语言描述一个任务，AI Agent 自动执行",
        "inputSchema": {
            "type": "object",
            "properties": {
                "device_id": {"type": "string", "description": "设备ID"},
                "task": {"type": "string", "description": "任务描述（自然语言）"}
            },
            "required": ["task"]
        }
    },
    {
        "name": "add_friend",
        "description": "在微信中添加好友",
        "inputSchema": {
            "type": "object",
            "properties": {
                "device_id": {"type": "string", "description": "设备ID"},
                "phone_or_wxid": {"type": "string", "description": "手机号或微信号"},
                "greeting": {"type": "string", "description": "打招呼消息", "default": "你好"}
            },
            "required": ["phone_or_wxid"]
        }
    },
    {
        "name": "batch_send",
        "description": "批量发送消息给多个联系人",
        "inputSchema": {
            "type": "object",
            "properties": {
                "device_id": {"type": "string", "description": "设备ID"},
                "targets": {"type": "array", "items": {"type": "string"}, "description": "接收人列表"},
                "content": {"type": "string", "description": "消息内容"},
                "interval_seconds": {"type": "number", "default": 30, "description": "每条间隔秒数"}
            },
            "required": ["targets", "content"]
        }
    },
]


@router.get("/gateway/mcp/tools", tags=["外部对接网关"])
async def mcp_list_tools():
    """MCP Protocol —— 列出所有可用工具"""
    return {"tools": MCP_TOOLS}


@router.post("/gateway/mcp/call", tags=["外部对接网关"])
async def mcp_call_tool(request: Request):
    """
    MCP Protocol —— 调用指定工具

    请求体: {"name": "send_message", "arguments": {"to": "张三", "content": "你好"}}
    """
    body = await request.json()
    tool_name = body.get("name", "")
    args = body.get("arguments", {})
    device_id = args.get("device_id")

    if not device_id:
        ws_devices = list(ws_hub.connections.keys())
        adb_devices = await adb_manager.async_scan_devices()
        device_id = (ws_devices + adb_devices + ["none"])[0]

    try:
        result = await _execute_mcp_tool(tool_name, device_id, args)
        return {
            "content": [{"type": "text", "text": json.dumps(result, ensure_ascii=False, indent=2)}],
            "isError": False
        }
    except Exception as e:
        return {
            "content": [{"type": "text", "text": f"执行失败: {e}"}],
            "isError": True
        }


async def _execute_mcp_tool(name: str, device_id: str, args: dict) -> dict:
    """执行 MCP 工具调用"""

    APP_PACKAGES = {
        "wechat": "com.tencent.mm",
        "douyin": "com.ss.android.ugc.aweme",
        "xhs": "com.xingin.xhs",
        "xianyu": "com.taobao.idlefish",
    }

    if name == "list_devices":
        ws_online = ws_hub.get_online_devices()
        adb_devs = await adb_manager.async_scan_devices()
        return {
            "devices": [
                {"device_id": d["device_id"], "status": "online", "type": "websocket"}
                for d in ws_online
            ] + [
                {"device_id": s, "status": "adb", "type": "adb"}
                for s in adb_devs
            ],
            "total": len(ws_online) + len(adb_devs)
        }

    if name == "take_screenshot":
        adb_dev = adb_manager.get_device(device_id)
        if adb_dev:
            result = await adb_dev.async_screenshot()
            return {"success": True, "width": result.get("width"), "height": result.get("height")}
        return {"success": False, "error": "设备不可用"}

    if name == "open_app":
        app_name = args.get("app_name", "wechat")
        package = APP_PACKAGES.get(app_name, app_name)
        adb_dev = adb_manager.get_device(device_id)
        if adb_dev:
            result = await adb_dev.async_start_app(package)
            return {"success": True, "app": app_name, "package": package}
        return {"success": False, "error": "设备不可用"}

    if name == "get_device_status":
        adb_dev = adb_manager.get_device(device_id)
        if adb_dev:
            info = adb_dev.get_info()
            return {"device_id": device_id, **info}
        ws_info = ws_hub.device_info.get(device_id, {})
        return {"device_id": device_id, **ws_info} if ws_info else {"error": "设备不在线"}

    if name == "send_message":
        from services.wechat_adb_engine import WeChatADBEngine
        adb_dev = adb_manager.get_device(device_id)
        if not adb_dev:
            return {"success": False, "error": f"设备 {device_id} 不可用"}
        engine = WeChatADBEngine(adb_dev)
        result = await asyncio.get_running_loop().run_in_executor(
            None, engine.send_message, args.get("to", ""), args.get("content", "")
        )
        record_journey(device_id, f"send_message → {args.get('to','')}", result, "mcp")
        return {"success": True, "result": result}

    if name == "add_friend":
        from services.wechat_adb_engine import WeChatADBEngine
        adb_dev = adb_manager.get_device(device_id)
        if not adb_dev:
            return {"success": False, "error": f"设备 {device_id} 不可用"}
        engine = WeChatADBEngine(adb_dev)
        result = await asyncio.get_running_loop().run_in_executor(
            None, engine.add_friend, args.get("phone_or_wxid", ""), args.get("greeting", "你好")
        )
        record_journey(device_id, f"add_friend → {args.get('phone_or_wxid','')}", result, "mcp")
        return {"success": True, "result": result}

    if name == "execute_task":
        from services import ai_agent as ai_agent_service
        result = await ai_agent_service.execute_ai_command(
            device_id=device_id,
            command=args["task"],
            mode="ai"
        )
        record_journey(device_id, f"execute_task: {args['task'][:50]}", result, "mcp")
        return result if isinstance(result, dict) else {"result": str(result)}

    if name == "batch_send":
        from services.wechat_adb_engine import WeChatADBEngine
        adb_dev = adb_manager.get_device(device_id)
        if not adb_dev:
            return {"success": False, "error": f"设备 {device_id} 不可用"}
        engine = WeChatADBEngine(adb_dev)
        results = []
        for target in args.get("targets", []):
            try:
                r = await asyncio.get_running_loop().run_in_executor(
                    None, engine.send_message, target, args.get("content", "")
                )
                results.append({"target": target, "success": True})
                record_journey(device_id, f"batch_send → {target}", "ok", "mcp")
            except Exception as e:
                results.append({"target": target, "success": False, "error": str(e)})
            interval = args.get("interval_seconds", 30)
            if interval > 0:
                await asyncio.sleep(interval)
        return {"results": results, "total": len(results)}

    raise HTTPException(404, f"未知工具: {name}")


# ═══════════════════════════════════════════════
# 三、REST API 网关元信息
# ═══════════════════════════════════════════════

@router.get("/gateway/info", tags=["外部对接网关"])
async def gateway_info():
    """网关信息 —— 三种对接方式的入口和说明"""
    return {
        "name": "工作手机SDK 外部对接网关",
        "version": "1.0.0",
        "protocols": {
            "rest_api": {
                "base_url": "/api/v3",
                "docs": "/docs",
                "description": "192+ REST API 端点，完整的微信/设备控制能力",
                "auth": "暂未启用（生产环境需配置 API Key）"
            },
            "openai_compatible": {
                "base_url": "/api/v3/gateway/v1",
                "endpoints": {
                    "chat": "POST /api/v3/gateway/v1/chat/completions",
                    "models": "GET /api/v3/gateway/v1/models"
                },
                "description": "OpenAI 兼容接口，可直接用 openai SDK 对接",
                "usage": {
                    "python": "from openai import OpenAI\nclient = OpenAI(base_url='http://服务器:8899/api/v3/gateway/v1', api_key='any')\nclient.chat.completions.create(model='workphone-agent', messages=[{'role':'user','content':'打开微信发消息给张三'}])",
                    "curl": "curl -X POST http://服务器:8899/api/v3/gateway/v1/chat/completions -H 'Content-Type: application/json' -d '{\"model\":\"workphone-agent\",\"messages\":[{\"role\":\"user\",\"content\":\"打开微信\"}]}'"
                }
            },
            "mcp": {
                "tools_endpoint": "GET /api/v3/gateway/mcp/tools",
                "call_endpoint": "POST /api/v3/gateway/mcp/call",
                "description": "MCP Protocol 兼容，8 个工具可直接被 AI Agent 调用",
                "tools_count": len(MCP_TOOLS),
                "tools": [t["name"] for t in MCP_TOOLS]
            }
        },
        "devices": {
            "ws_online": len(ws_hub.connections),
            "ws_device_ids": list(ws_hub.connections.keys()),
        }
    }


# ═══════════════════════════════════════════════
# 四、多设备批量控制（Fleet Management）
# ═══════════════════════════════════════════════

class FleetCommandRequest(BaseModel):
    device_ids: Optional[List[str]] = None
    command: str
    params: dict = {}

class DeviceGroupRequest(BaseModel):
    group_name: str
    device_ids: List[str]

_device_groups: dict = {}


@router.get("/gateway/fleet/status", tags=["外部对接网关"])
async def fleet_status():
    """多设备总览 —— 所有设备的实时状态汇总"""
    ws_devices = ws_hub.get_online_devices()
    adb_devices = await adb_manager.async_scan_devices()

    fleet = []
    seen = set()

    for d in ws_devices:
        did = d.get("device_id", "")
        if did in seen:
            continue
        seen.add(did)
        info = ws_hub.device_info.get(did, {})
        fleet.append({
            "device_id": did,
            "status": "online",
            "channel": "websocket",
            "model": info.get("model", ""),
            "battery": info.get("battery_level", -1),
            "network": info.get("network_type", ""),
            "current_app": info.get("current_app", ""),
            "uptime_minutes": info.get("uptime_minutes", 0),
            "last_heartbeat": info.get("last_heartbeat", ""),
        })

    for serial in adb_devices:
        if serial in seen:
            continue
        seen.add(serial)
        adb_dev = adb_manager.get_device(serial)
        info = adb_dev.get_info() if adb_dev else {}
        fleet.append({
            "device_id": serial,
            "status": "adb",
            "channel": "adb",
            "model": info.get("model", ""),
            "battery": info.get("battery_level", -1),
            "network": info.get("network_type", ""),
            "current_app": "",
            "uptime_minutes": 0,
            "last_heartbeat": "",
        })

    healthy = len([d for d in fleet if d["status"] in ("online", "adb")])
    return {
        "code": 200,
        "data": {
            "total": len(fleet),
            "healthy": healthy,
            "offline": len(fleet) - healthy,
            "devices": fleet,
            "groups": {name: ids for name, ids in _device_groups.items()},
            "timestamp": int(time.time()),
        }
    }


@router.post("/gateway/fleet/broadcast", tags=["外部对接网关"])
async def fleet_broadcast(req: FleetCommandRequest):
    """
    向多台设备广播命令 —— 批量控制

    如果 device_ids 为空，则向所有在线设备广播。
    """
    target_ids = req.device_ids
    if not target_ids:
        target_ids = list(ws_hub.connections.keys())
        adb_devs = await adb_manager.async_scan_devices()
        target_ids += [s for s in adb_devs if s not in target_ids]

    if not target_ids:
        return {"code": 200, "data": {"results": [], "message": "无在线设备"}}

    results = []
    for did in target_ids:
        try:
            if did in ws_hub.connections:
                resp = await ws_hub.send_command(did, {
                    "type": "execute",
                    "data": {"action": req.command, "params": req.params}
                }, timeout=15)
                results.append({"device_id": did, "success": True, "result": resp})
            else:
                adb_dev = adb_manager.get_device(did)
                if adb_dev:
                    results.append({"device_id": did, "success": True, "channel": "adb"})
                else:
                    results.append({"device_id": did, "success": False, "error": "设备不在线"})
        except Exception as e:
            results.append({"device_id": did, "success": False, "error": str(e)})

    success_count = len([r for r in results if r["success"]])
    return {
        "code": 200,
        "data": {
            "total": len(results),
            "success": success_count,
            "failed": len(results) - success_count,
            "results": results
        }
    }


@router.post("/gateway/fleet/group", tags=["外部对接网关"])
async def create_device_group(req: DeviceGroupRequest):
    """创建设备分组 —— 方便批量管理"""
    _device_groups[req.group_name] = req.device_ids
    return {"code": 200, "data": {"group": req.group_name, "devices": req.device_ids}}


@router.get("/gateway/fleet/groups", tags=["外部对接网关"])
async def list_device_groups():
    """列出所有设备分组"""
    return {"code": 200, "data": _device_groups}


# ═══════════════════════════════════════════════
# 五、AI 旅程追踪（Journey Tracking）
# ═══════════════════════════════════════════════

_journey_store: List[dict] = []


@router.get("/gateway/journey/{device_id}", tags=["外部对接网关"])
async def get_device_journey(device_id: str, limit: int = 50):
    """
    获取设备的 AI 旅程 —— 每台手机的操作历史和 AI 决策记录
    """
    entries = [j for j in _journey_store if j.get("device_id") == device_id]
    entries.sort(key=lambda x: x.get("timestamp", 0), reverse=True)
    return {
        "code": 200,
        "data": {
            "device_id": device_id,
            "entries": entries[:limit],
            "total": len(entries),
        }
    }


@router.get("/gateway/journey", tags=["外部对接网关"])
async def get_all_journeys(limit: int = 100):
    """获取所有设备的 AI 旅程"""
    entries = sorted(_journey_store, key=lambda x: x.get("timestamp", 0), reverse=True)
    by_device = {}
    for e in entries:
        did = e.get("device_id", "unknown")
        if did not in by_device:
            by_device[did] = []
        if len(by_device[did]) < 20:
            by_device[did].append(e)
    return {
        "code": 200,
        "data": {
            "total_entries": len(_journey_store),
            "devices": list(by_device.keys()),
            "journeys": by_device,
        }
    }


def record_journey(device_id: str, action: str, result: Any = None, source: str = "api"):
    """记录一条 AI 旅程条目（内部调用）"""
    entry = {
        "device_id": device_id,
        "action": action,
        "result": str(result)[:500] if result else None,
        "source": source,
        "timestamp": time.time(),
        "time_str": time.strftime("%Y-%m-%d %H:%M:%S"),
    }
    _journey_store.append(entry)
    if len(_journey_store) > 5000:
        _journey_store[:] = _journey_store[-3000:]
