"""工具代码生成器

根据工具定义生成 Python 代码，输出符合 BaseTool 规范的代码模板
"""

import logging
from typing import Any, Dict, Optional

logger = logging.getLogger("agent")


class ToolCodeGenerator:
    """根据参数生成 BaseTool 子类代码"""

    # 默认代码模板（使用唯一占位符避免冲突）
    DEFAULT_TEMPLATE = '''"""自动生成的工具: __TOOL_NAME__

__TOOL_DESCRIPTION__

分类: __TOOL_CATEGORY__
"""

from typing import Any, Dict, Optional

# 动态导入，避免模块路径问题
import sys
from pathlib import Path

def _get_base_classes():
    # 尝试多个可能的导入路径
    for attempt_import in [
        "src.agent.tools.base",
        "agent.tools.base",
    ]:
        try:
            from importlib import import_module
            base_module = import_module(attempt_import)
            return base_module.BaseTool, base_module.ToolOutput
        except ImportError:
            continue

    # 最后尝试相对导入
    try:
        from .base import BaseTool, ToolOutput
        return BaseTool, ToolOutput
    except ImportError:
        raise ImportError("无法导入 BaseTool，请确保模块路径正确")

BaseTool, ToolOutput = _get_base_classes()
del _get_base_classes


class __CLASS_NAME__(BaseTool):
    """__TOOL_DESCRIPTION__"""

    name = "__TOOL_NAME__"
    description = "__TOOL_DESCRIPTION__"
    category = "__TOOL_CATEGORY__"

    input_schema = __SCHEMA_STR__

    def execute(self, parameters: Dict[str, Any], context: Optional[Dict] = None) -> ToolOutput:
        """执行工具

        Args:
            parameters: 工具参数
            context: 执行上下文

        Returns:
            ToolOutput: 执行结果
        """
        # TODO: 在这里实现工具逻辑
        # 示例：
        # param = parameters.get("param_name", "")

        return ToolOutput(
            success=True,
            result="工具执行成功",
            metadata={}
        )
'''

    # 简单工具模板（无参数）
    SIMPLE_TEMPLATE = '''"""自动生成的工具: {name}

{description}

分类: {category}
"""

from typing import Any, Dict, Optional
from src.agent.tools.base import BaseTool, ToolOutput


class {class_name}(BaseTool):
    """{description}"""

    name = "{name}"
    description = "{description}"
    category = "{category}"

    input_schema = {{
        "type": "object",
        "properties": {{}},
        "required": []
    }}

    def execute(self, parameters: Dict[str, Any], context: Optional[Dict] = None) -> ToolOutput:
        """执行工具

        Args:
            parameters: 工具参数
            context: 执行上下文

        Returns:
            ToolOutput: 执行结果
        """
        # TODO: 在这里实现工具逻辑

        return ToolOutput(
            success=True,
            result="工具执行成功",
            metadata={{}}
        )
'''

    def __init__(self):
        pass

    def generate(
        self,
        name: str,
        description: str,
        input_schema: Dict[str, Any],
        category: str = "general",
        code_template: Optional[str] = None
    ) -> str:
        """生成工具代码

        Args:
            name: 工具名称
            description: 工具描述
            input_schema: 输入参数 schema
            category: 工具分类
            code_template: 自定义代码模板（可选）

        Returns:
            str: 生成的 Python 代码
        """
        # 处理类名（转换为 PascalCase）
        class_name = self._to_class_name(name)

        # 格式化 input_schema
        import json
        schema_str = json.dumps(input_schema, ensure_ascii=False, indent=4)

        # 选择模板
        template = code_template or self.DEFAULT_TEMPLATE

        # 使用唯一占位符进行替换
        result = template.replace("__TOOL_NAME__", name) \
            .replace("__TOOL_DESCRIPTION__", description) \
            .replace("__TOOL_CATEGORY__", category) \
            .replace("__CLASS_NAME__", class_name) \
            .replace("__SCHEMA_STR__", schema_str)

        logger.info(f"[ToolCodeGenerator] 生成工具代码: {name}")
        return result

    def get_template(self) -> str:
        """返回代码模板，包含注释说明如何填写

        Returns:
            str: 代码模板
        """
        return self.DEFAULT_TEMPLATE

    def generate_with_code(
        self,
        name: str,
        description: str,
        input_schema: Dict[str, Any],
        code: str,
        category: str = "general"
    ) -> str:
        """使用提供的代码片段生成工具

        Args:
            name: 工具名称
            description: 工具描述
            input_schema: 输入参数 schema
            code: 工具实现代码（execute 方法的内容，应包含 return 语句）
            category: 工具分类

        Returns:
            str: 生成的 Python 代码
        """
        class_name = self._to_class_name(name)

        import json
        schema_str = json.dumps(input_schema, ensure_ascii=False, indent=4)

        # 用户代码不需要转义，因为我们会使用唯一占位符
        # 缩进用户代码
        indented_code = self._indent_code(code, 8)

        # 构建完整代码（使用唯一占位符避免冲突）
        template = '''"""自动生成的工具: __TOOL_NAME__

__TOOL_DESCRIPTION__

分类: __TOOL_CATEGORY__
"""

from typing import Any, Dict, Optional

# 动态导入，避免模块路径问题
import sys
from pathlib import Path

def _get_base_classes():
    # 尝试多个可能的导入路径
    for attempt_import in [
        "src.agent.tools.base",
        "agent.tools.base",
    ]:
        try:
            from importlib import import_module
            base_module = import_module(attempt_import)
            return base_module.BaseTool, base_module.ToolOutput
        except ImportError:
            continue

    # 最后尝试相对导入
    try:
        from .base import BaseTool, ToolOutput
        return BaseTool, ToolOutput
    except ImportError:
        raise ImportError("无法导入 BaseTool，请确保模块路径正确")

BaseTool, ToolOutput = _get_base_classes()
del _get_base_classes


class __CLASS_NAME__(BaseTool):
    """{description}"""

    name = "__TOOL_NAME__"
    description = "__TOOL_DESCRIPTION__"
    category = "__TOOL_CATEGORY__"

    input_schema = __SCHEMA_STR__

    def execute(self, parameters: Dict[str, Any], context: Optional[Dict] = None) -> ToolOutput:
        """执行工具

        Args:
            parameters: 工具参数
            context: 执行上下文

        Returns:
            ToolOutput: 执行结果
        """
__INDENTED_CODE__
'''

        # 使用唯一占位符进行替换
        full_code = template.replace("__TOOL_NAME__", name) \
            .replace("__TOOL_DESCRIPTION__", description) \
            .replace("__TOOL_CATEGORY__", category) \
            .replace("__CLASS_NAME__", class_name) \
            .replace("__SCHEMA_STR__", schema_str) \
            .replace("__INDENTED_CODE__", indented_code)

        return full_code

    def _to_class_name(self, name: str) -> str:
        """将工具名称转换为类名（PascalCase）

        Args:
            name: 工具名称

        Returns:
            str: 类名
        """
        # 替换特殊字符为空格，然后按空格分割
        parts = name.replace("-", " ").replace("_", " ").split()
        # 将每个部分首字母大写
        return "".join(part.capitalize() for part in parts) + "Tool"

    def _indent_code(self, code: str, spaces: int) -> str:
        """缩进代码，并确保返回 ToolOutput 对象

        Args:
            code: 原始代码
            spaces: 缩进空格数

        Returns:
            str: 缩进后的代码
        """
        indent = " " * spaces
        # 先确保返回 ToolOutput
        code = self._ensure_tool_output(code)

        # 按行分割，保留空行
        lines = code.split("\n")
        # 缩进每一行（非空行）
        result = "\n".join(indent + line for line in lines)

        return result

    def _ensure_tool_output(self, code: str) -> str:
        """确保代码返回 ToolOutput 对象

        如果代码只是简单的返回值（如 "hello"），自动包装成 ToolOutput

        Args:
            code: 原始代码

        Returns:
            str: 确保返回 ToolOutput 的代码
        """
        code = code.strip()

        # 如果代码为空，返回默认值
        if not code:
            return 'return ToolOutput(success=True, result="", metadata={})'

        # 如果已经包含 return 语句，检查是否是 ToolOutput
        if "return" in code:
            # 检查是否已经是 ToolOutput
            if "ToolOutput" in code:
                return code
            else:
                # 用户写了 return xxx，但没有用 ToolOutput 包装
                # 提取 return 后面的内容
                import re
                match = re.search(r'return\s+(.+)', code, re.DOTALL)
                if match:
                    return_value = match.group(1).strip()
                    return f'return ToolOutput(success=True, result={return_value}, metadata={{}})'

        # 如果没有 return，添加 return ToolOutput
        # 处理用户可能直接写返回值的情况
        return f'return ToolOutput(success=True, result={code}, metadata={{}})'


# ============================================================================
# 便捷函数
# ============================================================================


def generate_tool_code(
    name: str,
    description: str,
    input_schema: Dict[str, Any],
    category: str = "general"
) -> str:
    """便捷函数：生成工具代码

    Args:
        name: 工具名称
        description: 工具描述
        input_schema: 输入参数 schema
        category: 工具分类

    Returns:
        str: 生成的 Python 代码
    """
    generator = ToolCodeGenerator()
    return generator.generate(name, description, input_schema, category)
