"""``@pillar.tool()`` decorator implementation.

The decorator captures metadata, extracts the JSON Schema from the function's
type hints (unless an explicit schema is provided), attaches the metadata as a
``__pillar_tool__`` attribute, and registers the function in the parent
``Pillar`` instance's tool registry.
"""
from __future__ import annotations

import functools
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Callable

from pillar._schema import extract_schema

if TYPE_CHECKING:
    pass


@dataclass
class ToolRegistration:
    """Internal record for a registered tool."""

    name: str
    description: str
    handler: Callable[..., Any]
    input_schema: dict[str, Any]
    output_schema: dict[str, Any] | None = None
    guidance: str | None = None
    timeout_ms: int = 30_000
    channel_compatibility: list[str] = field(
        default_factory=lambda: ["*"]
    )
    tool_type: str = "server_side"


def make_tool_decorator(
    registry: dict[str, ToolRegistration],
    description: str,
    *,
    name: str | None = None,
    guidance: str | None = None,
    input_schema: dict[str, Any] | None = None,
    output_schema: dict[str, Any] | None = None,
    timeout_ms: int = 30_000,
    channel_compatibility: list[str] | None = None,
    tool_type: str = "server_side",
) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
    """Return a decorator that registers *func* as a Pillar tool."""

    def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
        tool_name = name or func.__name__
        schema = input_schema if input_schema is not None else extract_schema(func)

        reg = ToolRegistration(
            name=tool_name,
            description=description,
            handler=func,
            input_schema=schema,
            output_schema=output_schema,
            guidance=guidance,
            timeout_ms=timeout_ms,
            channel_compatibility=channel_compatibility or ["*"],
            tool_type=tool_type,
        )

        func.__pillar_tool__ = reg  # type: ignore[attr-defined]
        registry[tool_name] = reg

        @functools.wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            return func(*args, **kwargs)

        wrapper.__pillar_tool__ = reg  # type: ignore[attr-defined]
        return wrapper

    return decorator
