"""
Base agent definitions for orchestration agents.

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

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


class AgentConfig(BaseModel):
    """
    Configuration model for agents.

    This Pydantic model defines the configuration parameters for agent behavior,
    including model selection, generation parameters, and optional tools.

    :param name: str - Unique identifier for the agent.
    :param description: Optional[str] - Human-readable description of agent purpose/role.
    :param model: str - Model identifier (e.g., 'gpt-4', 'claude-3-opus').
    :param temperature: float - Sampling temperature (0.0-2.0). Higher = more random.
    :param max_tokens: Optional[int] - Maximum tokens to generate. None means model default.
    :param system_prompt: Optional[str] - System-level instructions for the agent.
    :param tools: List[str] - List of tool names available to this agent.
    :param metadata: Dict[str, Any] - Custom metadata for agent-specific configuration.
    """

    name: str = Field(..., description="Agent name")
    description: Optional[str] = Field(None, description="Agent description")
    model: str = Field(..., description="Model identifier")
    temperature: float = Field(0.7, ge=0.0, le=2.0)
    max_tokens: Optional[int] = Field(None, ge=1)
    system_prompt: Optional[str] = None
    tools: List[str] = Field(default_factory=list)
    metadata: Dict[str, Any] = Field(default_factory=dict)


class BaseAgent(ABC):
    """
    Abstract base class for all agent implementations.

    This class defines the interface that all agent implementations must provide,
    including task execution, text generation, and interaction history management.

    Agents are the core execution units in orchestration patterns, responsible for:
    - Generating text responses
    - Executing tasks with context
    - Managing conversation/interaction history

    Subclasses must implement:
    - execute(): Execute a task with optional context
    - generate(): Generate text from a prompt
    """

    def __init__(self, config: AgentConfig):
        """
        Initialize the base agent with configuration.

        :param config: AgentConfig - Configuration for this agent instance.
        """
        self.config = config
        self.name = config.name
        self.description = config.description
        self._history: List[Dict[str, Any]] = []

    @abstractmethod
    async def execute(self, task: str, context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        Execute a task with optional context.

        This method provides high-level task execution with structured input/output.
        Subclasses implement this to define task processing logic.

        :param task: str - The task to execute.
        :param context: Optional[Dict[str, Any]] - Additional context for execution.
        :return: Dict[str, Any] - Execution results and metadata.
        """
        pass

    @abstractmethod
    async def generate(self, prompt: str, **kwargs) -> str:
        """
        Generate text from a prompt.

        This is the core text generation method used by patterns. Subclasses
        implement this to interface with language models or other generation backends.

        :param prompt: str - The prompt to generate from.
        :param kwargs: Additional generation parameters (model-specific).
        :return: str - Generated text response.
        """
        pass

    def add_to_history(self, entry: Dict[str, Any]) -> None:
        """
        Add an entry to the agent's interaction history.

        :param entry: Dict[str, Any] - History entry (e.g., prompt, response, metadata).
        """
        self._history.append(entry)

    def get_history(self) -> List[Dict[str, Any]]:
        """
        Get a copy of the agent's interaction history.

        :return: List[Dict[str, Any]] - Copy of history entries.
        """
        return self._history.copy()

    def clear_history(self) -> None:
        """
        Clear the agent's interaction history.

        Removes all history entries to start fresh.
        """
        self._history.clear()

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