"""
YAML agent loader with validation.

This module provides the AgentLoader class for loading agent definitions
from YAML files with automatic validation using pydantic-yaml.

Requirements: AGENT-01 (agent definition loading with validation)
"""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING, Optional, Union

from pydantic_yaml import parse_yaml_raw_as

from gsd_rlm.agents.definition import AgentDefinition

if TYPE_CHECKING:
    from rlm_toolkit.agents import Agent


class AgentLoaderError(Exception):
    """Raised when agent loading fails.

    This exception is raised when:
    - The YAML file does not exist
    - The YAML content is malformed
    - The agent definition fails validation
    """

    pass


class AgentLoader:
    """Load and validate agents from YAML files.

    This class provides methods for loading agent definitions from YAML
    files with automatic validation. All required fields are validated
    on load, and errors include the file path for easy debugging.

    Example:
        ```python
        loader = AgentLoader(agents_dir=Path("agents"))

        # Load by file path
        definition = loader.load_from_file(Path("agents/example.yaml"))

        # Load by name
        definition = loader.load_by_name("example")
        ```

    Attributes:
        agents_dir: Directory containing agent YAML files
    """

    def __init__(self, agents_dir: Optional[Path] = None):
        """Initialize the agent loader.

        Args:
            agents_dir: Directory containing agent YAML files.
                        Defaults to "agents" in current directory.
        """
        self.agents_dir = agents_dir or Path("agents")

    def load_from_file(self, yaml_path: Union[str, Path]) -> AgentDefinition:
        """Load agent definition from YAML file with validation.

        Args:
            yaml_path: Path to the YAML file

        Returns:
            Validated AgentDefinition instance

        Raises:
            AgentLoaderError: If file not found, YAML malformed, or validation fails
        """
        yaml_path = Path(yaml_path)

        if not yaml_path.exists():
            raise AgentLoaderError(f"Agent definition not found: {yaml_path}")

        content = yaml_path.read_text(encoding="utf-8")

        try:
            # Pydantic-YAML validates on load
            definition = parse_yaml_raw_as(AgentDefinition, content)
        except Exception as e:
            raise AgentLoaderError(
                f"Invalid agent definition in {yaml_path}:\n{e}"
            ) from e

        return definition

    def load_by_name(self, name: str) -> AgentDefinition:
        """Load agent by name from agents directory.

        Searches for the agent in the agents directory using several
        naming conventions: exact name, name.yaml, name.yml.

        Args:
            name: Agent name or filename (with or without extension)

        Returns:
            Validated AgentDefinition instance

        Raises:
            AgentLoaderError: If agent not found or validation fails
        """
        # Try exact name, then with .yaml extension
        candidates = [
            self.agents_dir / name,
            self.agents_dir / f"{name}.yaml",
            self.agents_dir / f"{name}.yml",
        ]

        for path in candidates:
            if path.exists():
                return self.load_from_file(path)

        raise AgentLoaderError(
            f"Agent '{name}' not found. Searched: {[str(c) for c in candidates]}"
        )

    def create_agent(
        self,
        definition: AgentDefinition,
        llm_provider,
        tools_registry: "AgentToolRegistry",
    ) -> "Agent":
        """Create runtime LLMAgent from definition.

        Creates an LLMAgent instance from the definition, configuring
        the tool registry to whitelist only the tools specified in
        the definition.

        Args:
            definition: Agent definition with configuration
            llm_provider: LLM provider instance (from RLM-Toolkit)
            tools_registry: AgentToolRegistry for tool whitelisting

        Returns:
            Configured LLMAgent instance
        """
        # Import here to avoid circular dependency
        from rlm_toolkit.agents import AgentRole, LLMAgent

        agent_id = definition.get_agent_id()

        # Configure allowed tools for this agent
        tool_names = [t.name for t in definition.tools]
        tool_configs = {t.name: t.config for t in definition.tools if t.config}
        tools_registry.configure_agent(agent_id, tool_names, tool_configs)

        return LLMAgent(
            agent_id=agent_id,
            name=definition.name,
            llm_provider=llm_provider,
            system_prompt=definition.get_system_prompt(),
            role=AgentRole.CUSTOM,
        )


def load_agent(path: Union[str, Path]) -> AgentDefinition:
    """Convenience function to load agent from path.

    Args:
        path: Path to the agent YAML file

    Returns:
        Validated AgentDefinition instance

    Example:
        ```python
        from gsd_rlm.agents import load_agent
        from pathlib import Path

        definition = load_agent(Path("agents/example.yaml"))
        print(definition.name)
        ```
    """
    return AgentLoader().load_from_file(Path(path))
