"""BaseTool — abstract base class for all tool plugins.

Tools are discovered from ``{data_dir}/tools/`` and executed by the
tool Action via :class:`ToolRegistry`.  Each tool directory contains
a ``tool.json`` metadata file and a ``main.py`` handler.
"""

from __future__ import annotations

from typing import Any, Optional


class BaseTool:
    """Abstract base class for tool implementations.

    Subclasses must define ``name``, ``description``, ``input_schema``
    and implement :meth:`run`.

    Attributes:
        name: Unique snake_case identifier used by LLM tool-calling.
        description: Human-readable description (LLM uses for selection).
        input_schema: JSON Schema dict describing the tool's parameters.
    """

    name: str = ""
    description: str = ""
    input_schema: dict[str, Any] = {}

    def __init__(self, context: Optional[dict[str, Any]] = None) -> None:
        self.ctx = context or {}

    def run(self, **kwargs: Any) -> dict[str, Any]:
        """Execute the tool with the given parameters.

        Returns:
            Dict with at minimum ``{"text": "..."}`` for LLM consumption.
            Optional keys: ``data`` (structured), ``canvas`` (rendering).

        Raises:
            NotImplementedError: If subclass does not implement.
        """
        raise NotImplementedError(
            f"Tool '{self.name}' must implement run()"
        )

    def to_schema(self) -> dict[str, Any]:
        """Convert to LLM-compatible tool schema (Anthropic format)."""
        return {
            "name": self.name,
            "description": self.description,
            "input_schema": self.input_schema or {
                "type": "object",
                "properties": {},
            },
        }
