"""
Simple tool decorator for compatibility with the reference SDK.

The refactored backend executes tools server-side; this decorator is
primarily for capturing metadata (name, input_schema) to send during
agent creation.
"""

from __future__ import annotations

import inspect
from functools import wraps
from typing import Any, Callable, Dict, Optional


def _schema_from_signature(func: Callable) -> Dict[str, Any]:
    sig = inspect.signature(func)
    props: Dict[str, Any] = {}
    required = []
    for name, param in sig.parameters.items():
        type_hint = param.annotation
        json_type = "string"
        if type_hint is int:
            json_type = "integer"
        elif type_hint is float:
            json_type = "number"
        elif type_hint is bool:
            json_type = "boolean"
        elif type_hint in (list, tuple) or str(type_hint).startswith(("list", "List", "typing.List")):
            json_type = "array"
        elif type_hint in (dict,) or str(type_hint).startswith(("dict", "Dict", "typing.Dict")):
            json_type = "object"
        props[name] = {"type": json_type}
        if param.default is inspect.Parameter.empty:
            required.append(name)
    schema: Dict[str, Any] = {"type": "object", "properties": props}
    if required:
        schema["required"] = required
    return schema


def tool(name: Optional[str] = None, schema: Optional[Dict[str, Any]] = None) -> Callable[[Callable], Callable]:
    """
    Decorate a function to capture tool metadata.

    The decorated function itself is returned unchanged; metadata is attached
    under ``_poping_tool`` for the AgentBuilder to consume.
    """

    def decorator(func: Callable) -> Callable:
        tool_schema = schema or _schema_from_signature(func)

        @wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)

        wrapper._poping_tool = {
            "name": name or func.__name__,
            "description": func.__doc__ or "",
            "input_schema": tool_schema,
            "callable": func,
        }
        return wrapper

    return decorator


def get_tool_definition(obj: Any) -> Optional[Dict[str, Any]]:
    """
    Extract tool definition from a decorated callable or raw dict.
    """
    if callable(obj) and hasattr(obj, "_poping_tool"):
        data = getattr(obj, "_poping_tool")
        return {
            "name": data["name"],
            "description": data["description"],
            "input_schema": data["input_schema"],
        }
    if isinstance(obj, dict) and {"name", "description", "input_schema"} <= set(obj.keys()):
        return {
            "name": obj["name"],
            "description": obj.get("description", ""),
            "input_schema": obj.get("input_schema") or {},
        }
    if isinstance(obj, str):
        # Bare tool name; backend must already know it.
        return {"name": obj, "description": obj, "input_schema": {}}
    return None


__all__ = ["tool", "get_tool_definition"]
