"""
BaseTool - Abstract base class for all groknroll tools

Following OpenCode architecture, all tools inherit from BaseTool and implement:
- name: str property (tool identifier)
- description: str property (what the tool does)
- execute(**kwargs): async method (tool execution)
- check_permission(): method (permission validation)

Tools provide capabilities like:
- File operations (read, write, edit)
- Search (grep, glob)
- Execution (bash, git)
- Advanced (LSP, web fetch, etc.)
"""

from abc import ABC, abstractmethod
from typing import Any, Optional


class BaseTool(ABC):
    """
    Abstract base class for all groknroll tools

    All tools must implement:
    1. name property - unique identifier for the tool
    2. description property - human-readable description
    3. execute() method - main tool functionality

    Example:
        class ReadTool(BaseTool):
            @property
            def name(self) -> str:
                return "read"

            @property
            def description(self) -> str:
                return "Read file contents"

            async def execute(self, path: str, **kwargs) -> str:
                with open(path) as f:
                    return f.read()
    """

    @property
    @abstractmethod
    def name(self) -> str:
        """
        Unique identifier for the tool

        Returns:
            Tool name (lowercase, no spaces)

        Example:
            "read", "write", "bash", "grep", etc.
        """
        pass

    @property
    @abstractmethod
    def description(self) -> str:
        """
        Human-readable description of what the tool does

        Returns:
            Description string

        Example:
            "Read file contents from the filesystem"
        """
        pass

    @abstractmethod
    async def execute(self, **kwargs) -> Any:
        """
        Execute the tool's main functionality

        Args:
            **kwargs: Tool-specific parameters

        Returns:
            Tool execution result (type varies by tool)

        Raises:
            Exception: If tool execution fails

        Example:
            await tool.execute(path="/path/to/file")
        """
        pass

    def check_permission(self, permission_manager: Optional[Any] = None) -> bool:
        """
        Check if tool execution is permitted

        Args:
            permission_manager: Optional permission manager instance

        Returns:
            True if permitted, False otherwise

        Example:
            if tool.check_permission(pm):
                result = await tool.execute(**params)
        """
        # Default: allow if no permission manager
        if permission_manager is None:
            return True

        # Delegate to permission manager
        return permission_manager.check(self.name)

    def validate_params(self, **kwargs) -> dict[str, Any]:
        """
        Validate tool parameters before execution

        Override this method to add parameter validation.

        Args:
            **kwargs: Parameters to validate

        Returns:
            Validated parameters dict

        Raises:
            ValueError: If parameters are invalid

        Example:
            def validate_params(self, **kwargs) -> dict[str, Any]:
                if 'path' not in kwargs:
                    raise ValueError("path is required")
                return kwargs
        """
        return kwargs

    def get_parameters_schema(self) -> dict[str, Any]:
        """
        Get the JSON Schema for tool parameters.

        Override this method to define the parameters your tool accepts.
        The schema follows JSON Schema Draft 7 format for Anthropic API compatibility.

        Returns:
            JSON Schema dict describing the tool's parameters

        Example:
            def get_parameters_schema(self) -> dict[str, Any]:
                return {
                    "type": "object",
                    "properties": {
                        "path": {
                            "type": "string",
                            "description": "File path to read"
                        }
                    },
                    "required": ["path"]
                }
        """
        # Default: no parameters
        return {"type": "object", "properties": {}, "required": []}

    def to_anthropic_schema(self) -> dict[str, Any]:
        """
        Convert tool to Anthropic API tool schema format.

        Returns a dict compatible with Anthropic's tool use API:
        https://docs.anthropic.com/en/docs/build-with-claude/tool-use

        Returns:
            Tool schema dict with name, description, and input_schema

        Example:
            {
                "name": "read",
                "description": "Read file contents",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "path": {"type": "string", "description": "File path"}
                    },
                    "required": ["path"]
                }
            }
        """
        return {
            "name": self.name,
            "description": self.description,
            "input_schema": self.get_parameters_schema(),
        }

    def __str__(self) -> str:
        """String representation of the tool"""
        return f"{self.__class__.__name__}(name={self.name})"

    def __repr__(self) -> str:
        """Detailed representation of the tool"""
        return f"{self.__class__.__name__}(name='{self.name}', description='{self.description}')"
