"""
对外接口统一清单 · 集成中心路由

路由前缀：/api/v3/integration

供存客宝 / 超级管理端 / AI 数字员工 直接发现并调用工作手机 SDK 的全部对外接口：
  - GET  /integration/manifest             全量接口清单（按模块归类）
  - GET  /integration/modules              模块目录（精简，不含端点明细）
  - GET  /integration/consumers            消费方列表
  - GET  /integration/consumers/{consumer} 某消费方可用的接口子集
  - GET  /integration/health               关键集成点健康聚合（WS/连接方案/存客宝/网关）

清单从 FastAPI 路由动态生成，始终与代码同步；本路由只读、零副作用。
严禁修改存客宝 / AI 数字员工 / 超管代码——本中心仅暴露工作手机侧出口。
"""

from __future__ import annotations

from typing import Any, Dict

from fastapi import APIRouter, HTTPException, Request

from services.integration_manifest import (
    build_manifest,
    build_capability,
    filter_by_consumer,
    list_modules,
    CONSUMER_LABELS,
)

router = APIRouter()


@router.get("/integration/manifest", tags=["对外接口统一清单"])
async def integration_manifest(request: Request) -> Dict[str, Any]:
    """全量对外接口清单（按模块 + 消费方归类，机器可读）。"""
    manifest = build_manifest(request.app)
    return {"code": 200, "data": manifest}


@router.get("/integration/modules", tags=["对外接口统一清单"])
async def integration_modules(request: Request) -> Dict[str, Any]:
    """模块目录（精简：模块/标签/消费方/端点数）。"""
    manifest = build_manifest(request.app)
    return {"code": 200, "data": {
        "module_count": manifest["module_count"],
        "total_endpoints": manifest["total_endpoints"],
        "modules": list_modules(manifest),
    }}


@router.get("/integration/consumers", tags=["对外接口统一清单"])
async def integration_consumers() -> Dict[str, Any]:
    """消费方列表（存客宝/超管/AI数字员工/通用）。"""
    return {"code": 200, "data": {
        "consumers": [
            {"id": cid, "label": label} for cid, label in CONSUMER_LABELS.items()
        ]
    }}


@router.get("/integration/consumers/{consumer}", tags=["对外接口统一清单"])
async def integration_consumer_view(consumer: str, request: Request) -> Dict[str, Any]:
    """
    某消费方可直接调用的接口子集。

    consumer ∈ {cunkebao, superadmin, ai_employee, common}
    """
    if consumer not in CONSUMER_LABELS:
        raise HTTPException(
            status_code=404,
            detail=f"未知消费方: {consumer}，可选: {list(CONSUMER_LABELS.keys())}",
        )
    manifest = build_manifest(request.app)
    return {"code": 200, "data": filter_by_consumer(manifest, consumer)}


@router.get("/integration/capability/{device_id}", tags=["对外接口统一清单"])
async def integration_capability(
    device_id: str,
    request: Request,
    consumer: str = "",
    probe: bool = False,
) -> Dict[str, Any]:
    """
    某设备的实时能力矩阵：各模块此刻是否可直接调用（ready/degraded/offline）。

    - consumer: 可选，仅看某消费方（cunkebao/superadmin/ai_employee/common）的模块
    - probe=true: 触发一次轻量 Frida 探测刷新 supports_hook（仅 ping/version/profile，
      不做全量 174 探针，避免 Frida 瞬断）；默认读最近一次探测缓存。
    """
    if consumer and consumer not in CONSUMER_LABELS:
        raise HTTPException(
            status_code=404,
            detail=f"未知消费方: {consumer}，可选: {list(CONSUMER_LABELS.keys())}",
        )

    # 1) 设备在线
    online = False
    try:
        from services.ws_hub import ws_hub
        online = ws_hub.is_online(device_id)
    except Exception:  # noqa: BLE001
        online = False

    # 2) supports_hook：默认读最近探测缓存；probe=true 时轻量刷新
    supports_hook = False
    if online and probe:
        try:
            from routers.unified import hook_probe  # 复用安全的轻量探测
            pr = await hook_probe(device_id)
            supports_hook = bool(pr.get("supports_hook"))
        except Exception:  # noqa: BLE001
            supports_hook = False
    else:
        try:
            from services.hook_module_service import hook_module_service
            dev = await hook_module_service.get_device_modules(device_id)
            if isinstance(dev, dict):
                supports_hook = bool(dev.get("supports_hook"))
        except Exception:  # noqa: BLE001
            supports_hook = False
        # 退化补充：用 ws_hub 上报的 frida_available
        if not supports_hook:
            try:
                from services.ws_hub import ws_hub
                info = ws_hub.get_device_info(device_id) or {}
                supports_hook = bool(info.get("frida_available"))
            except Exception:  # noqa: BLE001
                pass

    manifest = build_manifest(request.app)
    cap = build_capability(
        manifest, device_id, online, supports_hook,
        consumer=consumer or None,
    )
    cap["probed"] = bool(probe and online)
    return {"code": 200, "data": cap}


@router.get("/integration/health", tags=["对外接口统一清单"])
async def integration_health(request: Request) -> Dict[str, Any]:
    """
    关键集成点健康聚合：
      - websocket 主控（在线设备数）
      - 连接方案（当前生效 provider）
      - 存客宝对接（是否已配置启用）
      - AI 网关（可用协议）
    供超管/存客宝一眼看清「能不能直接对接」。
    """
    health: Dict[str, Any] = {"ok": True, "checks": {}}

    # 1) WebSocket 主控
    try:
        from services.ws_hub import ws_hub
        online = list(ws_hub.connections.keys())
        health["checks"]["websocket"] = {
            "ok": True,
            "online_devices": len(online),
            "device_ids": online,
        }
    except Exception as e:  # noqa: BLE001
        health["checks"]["websocket"] = {"ok": False, "error": str(e)}
        health["ok"] = False

    # 2) 连接方案（可切换驱动）
    try:
        from services.connection_provider import connection_provider_manager as mgr
        active = mgr.active_config()
        health["checks"]["connection_provider"] = {
            "ok": True,
            "active": active,
            "providers": [p.get("id") for p in mgr.list_providers()],
        }
    except Exception as e:  # noqa: BLE001
        health["checks"]["connection_provider"] = {"ok": False, "error": str(e)}

    # 3) 存客宝对接配置
    try:
        from services.cunke_bao_service import cunke_bao_service
        cfg = cunke_bao_service.config
        health["checks"]["cunkebao"] = {
            "ok": True,
            "enabled": bool(getattr(cfg, "enabled", False)),
            "api_key_set": bool(getattr(cfg, "api_key", "")),
            "base_url": getattr(cfg, "base_url", ""),
        }
    except Exception as e:  # noqa: BLE001
        health["checks"]["cunkebao"] = {"ok": False, "error": str(e)}

    # 4) AI 网关协议
    health["checks"]["ai_gateway"] = {
        "ok": True,
        "protocols": {
            "openai_compatible": "/api/v3/gateway/v1/chat/completions",
            "mcp_tools": "/api/v3/gateway/mcp/tools",
            "mcp_call": "/api/v3/gateway/mcp/call",
            "agent_execute": "/api/v3/agent/execute",
        },
    }

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


@router.get("/integration/realtime/status", tags=["对外接口统一清单"])
async def integration_realtime_status(
    request: Request,
    consumer: str = "",
    event_limit: int = 20,
) -> Dict[str, Any]:
    """
    第三方对接实时状态入口。

    面向存客宝/纯客宝/超管/AI 数字员工：一次返回在线设备、最近 WS/Hook/Agent 事件、
    实时 WebSocket 订阅地址和推荐拉取接口。
    """
    if consumer and consumer not in CONSUMER_LABELS:
        raise HTTPException(
            status_code=404,
            detail=f"未知消费方: {consumer}，可选: {list(CONSUMER_LABELS.keys())}",
        )

    try:
        from services.device_fleet import list_merged_local_devices
        from services.ws_hub import ws_hub
        from services.hook_module_service import hook_module_service

        devices = await list_merged_local_devices()
        normalized = []
        for item in devices:
            did = item.get("device_id", "")
            normalized.append({
                "device_id": did,
                "device_id_md5": item.get("device_id_md5"),
                "project_id": item.get("project_id"),
                "model": item.get("model"),
                "status": "online" if ws_hub.is_online(did) else item.get("status", "offline"),
                "online": ws_hub.is_online(did),
                "capabilities": item.get("capabilities") or [],
                "frida": item.get("frida") or {},
                "ai_brain": item.get("ai_brain") or {},
                "wechat_version": (item.get("device_profile") or {}).get("wechat_version"),
                "last_heartbeat": item.get("last_heartbeat"),
            })
        recent_events = await hook_module_service.list_events(
            limit=max(1, min(int(event_limit or 20), 100)),
        )
    except Exception as exc:  # noqa: BLE001
        raise HTTPException(status_code=500, detail=str(exc)) from exc

    base_url = str(request.base_url).rstrip("/")
    return {
        "code": 200,
        "data": {
            "consumer": consumer or "common",
            "online_count": sum(1 for item in normalized if item.get("online")),
            "total_count": len(normalized),
            "devices": normalized,
            "recent_events": recent_events,
            "pull_endpoints": {
                "status": "/api/v3/integration/realtime/status",
                "events": "/api/v3/integration/realtime/events",
                "fleet_devices": "/api/v3/fleet/devices",
                "fleet_execute": "/api/v3/fleet/execute",
            },
            "stream": {
                "protocol": "websocket",
                "url": f"{base_url}/api/v3/hook/events/stream",
                "event_source": "真实 Agent WS / Frida Hook / AI Agent 事件总线",
            },
        },
    }


@router.get("/integration/realtime/events", tags=["对外接口统一清单"])
async def integration_realtime_events(
    event_type: str = "",
    device_id: str = "",
    platform: str = "",
    limit: int = 100,
) -> Dict[str, Any]:
    """第三方对接实时事件列表：读取真实 Agent/Hook 事件总线。"""
    try:
        from services.hook_module_service import hook_module_service

        events = await hook_module_service.list_events(
            event_type=event_type or None,
            device_id=device_id or None,
            platform=platform or None,
            limit=max(1, min(int(limit or 100), 500)),
        )
        return {"code": 200, "data": {"total": len(events), "events": events}}
    except Exception as exc:  # noqa: BLE001
        raise HTTPException(status_code=500, detail=str(exc)) from exc
