"""自定义工具装饰器 — 替代 langchain_core.tools.tool"""

import functools
import inspect
from typing import Any, Callable


def tool(func: Callable = None, *, name: str = None, description: str = None) -> Callable:
    """自定义工具装饰器，兼容 langchain_core.tools.tool 的大部分行为"""
    def decorator(f: Callable) -> Callable:
        @functools.wraps(f)
        def wrapper(*args, **kwargs):
            return f(*args, **kwargs)

        wrapper._is_tool = True
        wrapper._tool_name = name or f.__name__
        wrapper._tool_description = description or inspect.getdoc(f) or ""
        wrapper._tool_signature = _get_signature(f)
        wrapper.name = wrapper._tool_name
        wrapper.description = wrapper._tool_description
        wrapper.args_schema = _get_signature(f)
        return wrapper

    if func is not None:
        return decorator(func)
    return decorator


def _get_signature(func: Callable) -> dict:
    """从函数签名提取参数 schema"""
    sig = inspect.signature(func)
    properties = {}
    required = []
    for param_name, param in sig.parameters.items():
        if param_name in ('self', 'cls'):
            continue
        prop = {"type": "string", "description": ""}
        if param.annotation != inspect.Parameter.empty:
            if param.annotation == str:
                prop["type"] = "string"
            elif param.annotation == int:
                prop["type"] = "integer"
            elif param.annotation == float:
                prop["type"] = "number"
            elif param.annotation == bool:
                prop["type"] = "boolean"
            elif param.annotation == list or str(param.annotation).startswith("list"):
                prop["type"] = "array"
                prop["items"] = {"type": "string"}
        if param.default == inspect.Parameter.empty:
            required.append(param_name)
        properties[param_name] = prop
    return {
        "type": "object",
        "properties": properties,
        "required": required,
    }


def get_tool_schema(tool_func: Callable) -> dict:
    """从工具函数获取 OpenAI function calling schema"""
    name = getattr(tool_func, 'name', tool_func.__name__)
    description = getattr(tool_func, 'description', tool_func.__doc__ or "")
    parameters = getattr(tool_func, 'args_schema', _get_signature(tool_func))
    return {
        "type": "function",
        "function": {
            "name": name,
            "description": description.strip() if description else "",
            "parameters": parameters,
        }
    }