"""
Agent manifest spec models.

Defines the core behavior specification for agents.
"""

from pydantic import BaseModel, Field

from typing import Optional


class ModelConfig(BaseModel):
    """LLM model configuration."""

    provider: str = Field(..., description="LLM provider (e.g., openai, anthropic, google)")
    name: str = Field(..., description="Model identifier (e.g., gpt-4o, claude-3-opus)")
    parameters: dict[str, object] = Field(
        default_factory=dict,
        description="Model parameters (temperature, max_tokens, top_p, etc.)",
    )


class ToolConfig(BaseModel):
    """Tool-specific configuration."""

    timeout: Optional[str] = Field(None, description="Tool timeout (e.g., 30s)")
    retries: Optional[int] = Field(None, ge=0, description="Number of retries")
    cache: Optional[dict[str, object]] = Field(None, description="Cache configuration")


class ToolDefinition(BaseModel):
    """
    Tool definition following MCP Tool Protocol and OpenAI Function Calling patterns.

    Supports both inline definitions and external references.
    """

    # Inline definition fields
    name: Optional[str] = Field(None, description="Tool name")
    description: Optional[str] = Field(None, description="Tool description")
    parameters: Optional[dict[str, object]] = Field(
        None,
        description="JSON Schema for tool parameters (OpenAI-compatible)",
    )
    config: Optional[ToolConfig] = Field(None, description="Tool configuration")

    # External reference (MCP or local file)
    ref: Optional[str] = Field(
        None,
        alias="$ref",
        description="External tool reference (e.g., mcp://server/tool, ./tools/custom.yaml)",
    )

    model_config = {"populate_by_name": True}


class InterfaceSchema(BaseModel):
    """
    Agent input/output interface definition using JSON Schema.

    Follows patterns from OpenAI Assistants API and LangChain.
    """

    input: dict[str, object] = Field(
        default_factory=dict,
        description="Input JSON Schema",
    )
    output: dict[str, object] = Field(
        default_factory=dict,
        description="Output JSON Schema",
    )


class AgentSpec(BaseModel):
    """
    Agent specification block.

    Defines the core behavior, capabilities, and interface of an agent.
    Inspired by CrewAI's agent identity pattern.
    """

    # Agent identity (CrewAI-inspired)
    role: Optional[str] = Field(None, description="Agent role description")
    goal: Optional[str] = Field(None, description="Agent objective")
    backstory: Optional[str] = Field(
        None,
        description="Context for agent behavior (system prompt foundation)",
    )

    # Framework binding
    framework: str = Field(..., description="Target execution framework")

    # Framework-specific configuration
    framework_config: Optional[dict[str, object]] = Field(
        None,
        description="Framework-specific configuration (e.g., crewai, langchain settings)",
    )

    # Model configuration
    model: Optional[ModelConfig] = Field(None, description="LLM model configuration")

    # Capabilities
    capabilities: list[str] = Field(
        default_factory=list,
        description="Supported capabilities (e.g., text_generation, code_execution)",
    )

    # Tools
    tools: list[ToolDefinition] = Field(
        default_factory=list,
        description="Available tools",
    )

    # I/O Interface
    interface: Optional[InterfaceSchema] = Field(
        None,
        description="Input/output schema definition",
    )
