"""SkillSearchTool - Agent 可调用的技能搜索工具"""

import asyncio
import logging
from typing import Any

from agentkit.tools.base import Tool

logger = logging.getLogger(__name__)


class SkillSearchTool(Tool):
    """技能搜索工具

    让 Agent 可以搜索可用的技能包，在安装之前先确认技能是否存在。
    使用 `npx skills search <keyword>` 搜索可用技能。

    Usage:
        tool = SkillSearchTool()
        result = await tool.execute(keyword="ppt")
    """

    def __init__(
        self,
        name: str = "skill_search",
        description: str = (
            "搜索可用的 Agent 技能包。在安装技能之前，应先使用此工具搜索确认技能名称和来源。"
            "返回匹配的技能列表，包含名称、描述和安装来源。"
        ),
        input_schema: dict[str, Any] | None = None,
        output_schema: dict[str, Any] | None = None,
        version: str = "1.0.0",
        tags: list[str] | None = None,
    ):
        schema = input_schema or {
            "type": "object",
            "properties": {
                "keyword": {
                    "type": "string",
                    "description": "搜索关键词，如 ppt、code-review、find-skills",
                },
            },
            "required": ["keyword"],
        }
        super().__init__(
            name=name,
            description=description,
            input_schema=schema,
            output_schema=output_schema,
            version=version,
            tags=tags or ["skill", "search"],
        )

    async def execute(self, **kwargs) -> dict:
        keyword = kwargs.get("keyword", "").strip()

        if not keyword:
            return {
                "output": "错误: 必须提供 keyword 参数",
                "exit_code": 1,
                "is_error": True,
            }

        try:
            # ``--yes`` is an npx flag that auto-accepts npx's own
            # "Need to install the following packages: skills@x.y.z.
            # Ok to proceed?" prompt. Without it, npx blocks waiting
            # for stdin in the non-interactive subprocess.
            proc = await asyncio.create_subprocess_exec(
                "npx",
                "--yes",
                "skills@latest",
                "search",
                keyword,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE,
            )
            stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=60)
            output = stdout.decode("utf-8", errors="replace")
            error_output = stderr.decode("utf-8", errors="replace")

            if output.strip():
                # Parse and format the search results
                results = self._format_search_results(output, keyword)
                return {
                    "output": results,
                    "exit_code": 0,
                    "is_error": False,
                }
            elif error_output.strip():
                # Some versions output to stderr
                results = self._format_search_results(error_output, keyword)
                return {
                    "output": results,
                    "exit_code": 0,
                    "is_error": False,
                }
            else:
                return {
                    "output": (
                        f"未找到与 '{keyword}' 匹配的技能。\n\n"
                        "建议：\n"
                        "1. 尝试不同的关键词搜索\n"
                        "2. 检查技能名称拼写\n"
                        "3. 访问 https://github.com/topics/agent-skills 浏览可用技能"
                    ),
                    "exit_code": 0,
                    "is_error": False,
                }
        except asyncio.TimeoutError:
            return {
                "output": f"搜索技能 '{keyword}' 超时（60s），请稍后重试",
                "exit_code": -1,
                "is_error": True,
            }
        except FileNotFoundError:
            return {
                "output": (
                    "npx 命令未找到，请确保 Node.js 已安装。\n安装方式: https://nodejs.org/"
                ),
                "exit_code": -1,
                "is_error": True,
            }
        except Exception as e:
            return {
                "output": f"搜索技能 '{keyword}' 时发生异常: {e}",
                "exit_code": -1,
                "is_error": True,
            }

    @staticmethod
    def _format_search_results(raw_output: str, keyword: str) -> str:
        """Format raw npx skills search output into a readable result."""
        # Clean up ANSI escape codes
        import re

        clean = re.sub(r"\x1b\[[0-9;]*m", "", raw_output)

        if not clean.strip():
            return (
                f"未找到与 '{keyword}' 匹配的技能。\n\n"
                "建议：\n"
                "1. 尝试不同的关键词搜索\n"
                "2. 检查技能名称拼写\n"
                "3. 访问 https://github.com/topics/agent-skills 浏览可用技能"
            )

        # Return the cleaned output with a helpful header
        return f"搜索 '{keyword}' 的结果：\n\n{clean.strip()}"
