"""
Base tool definitions for orchestration tools.

This module provides the foundation classes for all tool implementations,
including configuration, results, and the abstract base tool interface.
"""

from abc import ABC, abstractmethod
from typing import Any, Dict, Optional
from pydantic import BaseModel, Field
from enum import Enum


class ToolCategory(str, Enum):
    """
    Enumeration of tool categories.

    Categories help organize and classify tools by their primary function:
    - SEARCH: Web search, knowledge retrieval
    - COMPUTATION: Calculators, data processing, algorithms
    - DATA_ACCESS: Database queries, file access, API calls
    - COMMUNICATION: Email, messaging, notifications
    - CUSTOM: User-defined or specialized tools
    """

    SEARCH = "search"
    COMPUTATION = "computation"
    DATA_ACCESS = "data_access"
    COMMUNICATION = "communication"
    CUSTOM = "custom"


class ToolConfig(BaseModel):
    """
    Configuration model for tools.

    This Pydantic model defines the configuration parameters for tool behavior,
    including metadata, parameter schemas, and execution limits.

    :param name: str - Unique identifier for the tool.
    :param description: str - Human-readable description of tool functionality.
    :param category: ToolCategory - Category classification for the tool.
    :param parameters_schema: Dict[str, Any] - JSON schema for tool parameters.
    :param timeout: Optional[float] - Execution timeout in seconds. None means no timeout.
    :param metadata: Dict[str, Any] - Custom metadata for tool-specific configuration.
    """

    name: str = Field(..., description="Tool name")
    description: str = Field(..., description="Tool description")
    category: ToolCategory = Field(ToolCategory.CUSTOM, description="Tool category")
    parameters_schema: Dict[str, Any] = Field(default_factory=dict)
    timeout: Optional[float] = Field(None, ge=0.0, description="Tool execution timeout")
    metadata: Dict[str, Any] = Field(default_factory=dict)


class ToolResult(BaseModel):
    """
    Result model for tool execution outcomes.

    This Pydantic model encapsulates the results of tool execution,
    including success status, output data, errors, and execution metrics.

    :param success: bool - Whether the tool execution succeeded.
    :param result: Any - The output data from tool execution.
    :param error: Optional[str] - Error message if execution failed. None on success.
    :param execution_time: Optional[float] - Time taken to execute in seconds.
    :param metadata: Dict[str, Any] - Additional execution metadata.
    """

    success: bool = Field(..., description="Whether tool execution succeeded")
    result: Any = Field(None, description="Tool execution result")
    error: Optional[str] = Field(None, description="Error message if failed")
    execution_time: Optional[float] = Field(None, description="Execution time in seconds")
    metadata: Dict[str, Any] = Field(default_factory=dict)


class BaseTool(ABC):
    """
    Abstract base class for all tool implementations.

    This class defines the interface that all tool implementations must provide,
    including execution, parameter validation, and schema retrieval.

    Tools extend agent capabilities by providing access to:
    - External APIs and services
    - Computational operations
    - Data retrieval and manipulation
    - Communication channels

    Subclasses must implement:
    - execute(): Perform the tool's primary function
    - validate_parameters(): Validate input parameters before execution
    """

    def __init__(self, config: ToolConfig):
        """
        Initialize the base tool with configuration.

        :param config: ToolConfig - Configuration for this tool instance.
        """
        self.config = config
        self.name = config.name
        self.description = config.description
        self.category = config.category

    @abstractmethod
    async def execute(self, **kwargs) -> ToolResult:
        """
        Execute the tool with the given parameters.

        This is the main entry point for tool execution. Subclasses implement
        this method to define their specific functionality.

        :param kwargs: Tool-specific parameters.
        :return: ToolResult - Execution results including success status and output.
        """
        pass

    @abstractmethod
    def validate_parameters(self, parameters: Dict[str, Any]) -> bool:
        """
        Validate parameters before execution.

        Subclasses implement this to check parameter correctness, types,
        and required fields before attempting execution.

        :param parameters: Dict[str, Any] - Parameters to validate.
        :return: bool - True if valid, False otherwise.
        """
        pass

    def get_schema(self) -> Dict[str, Any]:
        """
        Get the tool's schema definition.

        Returns a structured representation of the tool including name,
        description, category, and parameter schema for agent introspection.

        :return: Dict[str, Any] - Tool schema with metadata and parameter definitions.
        """
        return {
            "name": self.name,
            "description": self.description,
            "category": self.category.value,
            "parameters": self.config.parameters_schema,
        }

    def __repr__(self) -> str:
        return f"<{self.__class__.__name__}(name='{self.name}', category='{self.category.value}')>"
