"""ServiceAgent — 只读客服 Agent

职责：
1. 查询工具表、工具组、后端运行时、工具状态
2. 回答外部 Agent 关于工具使用的问题
3. 撰写任务书提交给 CodingAgent（唯一的写操作）
4. 不直接调用工具、不启停工具
"""

from __future__ import annotations

import json
import logging
import uuid
from typing import TYPE_CHECKING

from claude_agent_sdk import (
    AssistantMessage, TextBlock, ClaudeAgentOptions, tool,
    create_sdk_mcp_server, ClaudeSDKClient, ToolUseBlock,
)

if TYPE_CHECKING:
    from tool_agent.router.agent import Router

logger = logging.getLogger(__name__)

MCP_SERVER_NAME = "service_tools"
_router: Router | None = None


def _result(data: dict) -> dict:
    return {"content": [{"type": "text", "text": json.dumps(data, ensure_ascii=False, indent=2)}]}


# ===========================================================================
#  只读工具
# ===========================================================================

@tool(name="list_tools", description="列出所有已注册工具的摘要。",
      input_schema={"type": "object", "properties": {}})
async def list_tools_fn(args):
    tools = []
    for t in _router.registry.list_all():
        route = _router.status_manager.get_status(t.tool_id)
        tools.append({
            "tool_id": t.tool_id, "name": t.name,
            "description": t.description, "category": t.category,
            "backend_runtime": t.backend_runtime.value if t.backend_runtime else "unknown",
            "group_ids": t.group_ids,
            "state": route.state.value if route else "stopped",
        })
    return _result({"total": len(tools), "tools": tools})


@tool(name="get_tool_details", description="获取指定工具的详细信息。",
      input_schema={"type": "object", "properties": {
          "tool_id": {"type": "string"}}, "required": ["tool_id"]})
async def get_tool_details_fn(args):
    t = _router.registry.get(args["tool_id"])
    if not t:
        return _result({"error": f"Tool '{args['tool_id']}' not found"})
    route = _router.status_manager.get_status(t.tool_id)
    return _result({
        "tool_id": t.tool_id, "name": t.name,
        "description": t.description, "category": t.category,
        "backend_runtime": t.backend_runtime.value if t.backend_runtime else "unknown",
        "group_ids": t.group_ids,
        "input_schema": t.input_schema, "output_schema": t.output_schema,
        "state": route.state.value if route else "stopped",
    })


@tool(name="list_groups", description="列出所有工具组。",
      input_schema={"type": "object", "properties": {}})
async def list_groups_fn(args):
    groups = []
    for g in _router.registry.group_manager.list_all():
        groups.append({
            "group_id": g.group_id, "name": g.name,
            "description": g.description, "category": g.category.value,
            "tool_ids": g.tool_ids, "usage_order": g.usage_order,
            "usage_example": g.usage_example,
        })
    return _result({"total": len(groups), "groups": groups})


@tool(name="list_backend_runtimes", description="列出后端执行环境类型。",
      input_schema={"type": "object", "properties": {}})
async def list_backend_runtimes_fn(args):
    runtimes = [
        {"backend_runtime": "local", "name": "本地 Python 运行时",
         "tool_count": len(_router.registry.find_by_backend_runtime("local"))},
        {"backend_runtime": "docker", "name": "Docker 容器运行时",
         "tool_count": len(_router.registry.find_by_backend_runtime("docker"))},
        {"backend_runtime": "remote", "name": "远程 API / 云端服务",
         "tool_count": len(_router.registry.find_by_backend_runtime("remote"))},
    ]
    return _result({"backend_runtimes": runtimes})


@tool(name="check_task_status", description="查询异步任务状态。",
      input_schema={"type": "object", "properties": {
          "task_id": {"type": "string"}}, "required": ["task_id"]})
async def check_task_status_fn(args):
    task = _router.get_task_status(args["task_id"])
    if not task:
        return _result({"error": "Task not found"})
    return _result(task)


# ===========================================================================
#  提交任务书给 RouterAgent
# ===========================================================================

@tool(name="submit_task", description="""
撰写任务书并提交给 RouterAgent，由它调度 CodingAgent 创建新工具。

你需要先理解用户需求，然后撰写详细任务书（task_spec），包含：
1. 功能描述  2. 输入输出 JSON Schema  3. 实现要求  4. tool_id
""", input_schema={"type": "object", "properties": {
    "tool_id": {"type": "string", "description": "工具 ID"},
    "description": {"type": "string", "description": "简短功能描述"},
    "task_spec": {"type": "string", "description": "详细任务书"},
}, "required": ["tool_id", "description", "task_spec"]})
async def submit_task_fn(args):
    task_id = f"create_{uuid.uuid4().hex[:8]}"
    # 提交给 Router（RouterAgent），由它调度 CodingAgent
    _router.submit_create_task(task_id, args["task_spec"])
    return _result({"task_id": task_id, "status": "submitted_to_router",
                     "message": f"任务书已提交给 RouterAgent，tool_id={args['tool_id']}"})


ALL_TOOLS = [
    list_tools_fn, get_tool_details_fn, list_groups_fn,
    list_backend_runtimes_fn, check_task_status_fn, submit_task_fn,
]


# ===========================================================================
#  动态上下文
# ===========================================================================

def _build_context(router: Router) -> str:
    """构造实时系统上下文，注入到每次对话中"""
    tools = []
    for t in router.registry.list_all():
        route = router.status_manager.get_status(t.tool_id)
        tools.append({
            "tool_id": t.tool_id, "name": t.name,
            "description": t.description[:80],
            "backend_runtime": t.backend_runtime.value if t.backend_runtime else "unknown",
            "group_ids": t.group_ids,
            "state": route.state.value if route else "stopped",
        })
    groups = [{"group_id": g.group_id, "name": g.name,
               "tool_ids": g.tool_ids, "usage_order": g.usage_order}
              for g in router.registry.group_manager.list_all()]
    coding = router.get_coding_agent_status()
    return json.dumps({"tools": tools, "groups": groups,
                        "coding_agent": coding}, ensure_ascii=False, indent=2)


# ===========================================================================
#  System Prompt
# ===========================================================================

SYSTEM_PROMPT = """你是 Tool Agent 系统的智能客服。

**身份**：你是客服助手，负责与外部 Agent 交流。每个对话窗口对应一个独立的你。

**职责**：
1. 帮助外部 Agent 了解可用工具、工具组、使用方法
2. 解答工具参数、输入输出格式、调用顺序等问题
3. 当用户需要新工具时，撰写详细任务书，通过 submit_task 提交给 RouterAgent

**你拥有的工具**：
- `list_tools` — 列出所有工具
- `get_tool_details` — 查看工具详情（参数、Schema）
- `list_groups` — 列出工具组及使用顺序
- `list_backend_runtimes` — 列出后端执行环境类型
- `check_task_status` — 查询任务进度
- `submit_task` — 撰写任务书提交给 RouterAgent（由它调度 CodingAgent 创建工具）

**架构说明**：
- 所有工具对外统一为本地 Python/FastAPI 调用层
- 后端执行环境分 local（本地 Python）、docker、remote（云端 API）
- 你不能直接调用工具或启停工具，只能查询和提交任务书
- RouterAgent 负责接收你的任务书并调度 CodingAgent 实现

**规则**：
1. 基于实时上下文中的工具信息回答
2. 推荐工具时优先介绍工具组和使用顺序
3. 不确定时主动询问
4. 友好、简洁、专业
"""


# ===========================================================================
#  ServiceAgent 类
# ===========================================================================

class ServiceAgent:
    """只读客服 Agent，按 session_id 维护对话记忆"""

    def __init__(self, router: Router, model: str = "claude-sonnet-4-5"):
        self.router = router
        self.model = model
        global _router
        _router = router

    async def chat(self, message: str, session_id: str | None = None) -> tuple[str, str]:
        """对话。返回 (回复文本, session_id)"""
        mcp_server = create_sdk_mcp_server(
            name=MCP_SERVER_NAME, version="1.0.0", tools=ALL_TOOLS)

        ctx = _build_context(self.router)
        enhanced = f"[实时系统上下文]\n{ctx}\n\n用户消息：{message}"

        options = ClaudeAgentOptions(
            system_prompt=SYSTEM_PROMPT,
            mcp_servers={MCP_SERVER_NAME: mcp_server},
            model=self.model,
            setting_sources=["project"],
            allowed_tools=[f"mcp__{MCP_SERVER_NAME}__{t.name}" for t in ALL_TOOLS],
        )
        if session_id:
            options.resume = session_id

        result_text = ""
        actual_sid = session_id

        async with ClaudeSDKClient(options=options) as client:
            await client.query(enhanced)
            for msg in client.get_conversation():
                if isinstance(msg, AssistantMessage):
                    for block in msg.content:
                        if isinstance(block, TextBlock):
                            result_text += block.text
            actual_sid = getattr(client, 'session_id', None) or actual_sid

        return result_text, actual_sid or str(uuid.uuid4())
