"""SkillDetailTool — 渐进式技能加载工具 (U5)

当 skill_config.disclosure_level == 0 时，system prompt 只注入 skill 名称 + 描述。
LLM 可调用此工具按需加载完整 skill instructions（identity/context/instructions/
constraints/output_format），从本地 SkillRegistry 检索。

与 tools/skill_search.py 的 SkillSearchTool 区别：
- SkillSearchTool 搜索 npx 外部市场（安装前发现）
- SkillDetailTool 加载本地已注册 skill 的完整内容（执行前加载）
"""

from __future__ import annotations

import logging

from agentkit.chat.skill_routing import collect_prompt_parts, format_preconditions_block
from agentkit.core.exceptions import SkillNotFoundError
from agentkit.tools.base import Tool

logger = logging.getLogger(__name__)


class SkillDetailTool(Tool):
    """按需加载本地已注册 skill 的完整 instructions。

    用于渐进式技能加载（disclosure_level=0）：system prompt 只含 skill 概要，
    LLM 决定执行该 skill 时调用此工具获取完整 instructions。

    Usage::

        from agentkit.skills.skill_detail import SkillDetailTool
        tool = SkillDetailTool(skill_registry=registry)
        result = await tool.execute(query="research")
    """

    def __init__(
        self,
        skill_registry: object,
        name: str = "skill_detail",
        description: str = (
            "Load full instructions for a registered skill by name or keyword. "
            "Use this when the system prompt only shows a skill summary (name + description) "
            "and you need the complete instructions to execute the skill. "
            "Returns the skill's identity, context, instructions, constraints, and output format."
        ),
        input_schema: dict[str, object] | None = None,
        output_schema: dict[str, object] | None = None,
        version: str = "1.0.0",
        tags: list[str] | None = None,
    ):
        schema = input_schema or {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": (
                        "Skill name or keyword to search for. "
                        "Returns the full instructions of the best-matching registered skill."
                    ),
                },
            },
            "required": ["query"],
        }
        super().__init__(
            name=name,
            description=description,
            input_schema=schema,
            output_schema=output_schema,
            version=version,
            tags=tags or ["skill", "search", "meta"],
        )
        self._registry = skill_registry

    async def execute(self, **kwargs) -> dict:
        """执行 skill 详情加载。

        Args:
            query: skill 名称或关键词。

        Returns:
            包含 ``name``、``description``、``full_instructions`` 的字典；
            无匹配时返回 ``message`` 提示。
        """
        query = str(kwargs.get("query", "")).strip()
        if not query:
            return {
                "error": "query parameter is required",
                "results": [],
            }

        # 精确名称匹配优先
        try:
            skill = self._registry.get(query)
            return self._format_skill_full(skill)
        except SkillNotFoundError:
            pass  # 非精确匹配，降级到关键词搜索

        # 关键词搜索：匹配 skill 名称和描述
        matches: list[object] = []
        query_lower = query.lower()
        for skill in self._registry.list_skills():
            name = skill.name.lower()
            desc = (skill.config.description or "").lower()
            if query_lower in name or query_lower in desc:
                matches.append(skill)

        if not matches:
            return {
                "query": query,
                "count": 0,
                "results": [],
                "message": f"No skills matched '{query}'.",
            }

        # 返回最佳匹配（第一个）
        return self._format_skill_full(matches[0])

    @staticmethod
    def _format_skill_full(skill: object) -> dict[str, object]:
        """格式化 skill 的完整 instructions 供 LLM 使用。"""
        config = skill.config
        prompt_parts = collect_prompt_parts(config, with_headers=True)

        # v7: 注入激活前置条件（安全守卫，即使在渐进加载模式下也不应省略）
        preconditions = getattr(config, "preconditions", None)
        if preconditions:
            prompt_parts.append(format_preconditions_block(preconditions, header_level=3))

        return {
            "name": config.name,
            "description": config.description,
            "version": config.version,
            "full_instructions": "\n\n".join(prompt_parts) if prompt_parts else "",
            "tools": [t.name for t in (skill.tools or [])],
        }
