"""AgentBuilder - Fluent API for constructing Agent definitions.

Accepts both string IDs and typed objects for composition:

    pathway = PathwayBuilder("dispatch").tool(...).build()
    skill = SkillBuilder().id("svc").name("SVC").build()

    agent = (
        AgentBuilder()
        .id("researcher")
        .name("Research Agent")
        .instructions("You are a research specialist.")
        .tool("web.*")
        .skill(skill)          # Skill object or string ID
        .pathway(pathway)      # Pathway object or string ID
        .model("reasoning")
        .build()
    )
"""

from __future__ import annotations

import uuid
from typing import TYPE_CHECKING

from core.types import AgentDefinition

if TYPE_CHECKING:
    from core.pathways.pathway import Pathway
    from core.skills.models import Skill


class AgentBuilder:
    """Fluent builder for creating agents.

    Required fields (must be set before build()):
    - id: Unique identifier for the agent (auto-generated if not set)
    - name: Human-readable name (defaults to id if not set)
    """

    def __init__(self) -> None:
        """Initialize a new agent builder with default values."""
        self._id: str | None = None
        self._name: str | None = None
        self._instructions: str = ""
        self._tools: list[str] = []
        self._skills: list[str] = []
        self._handoff_description: str = ""
        self._max_steps: int = 10
        self._model: str = "reasoning"
        self._pathway: str = "react"
        self._temperature: float = 0.7
        self._workspace_id: str | None = None

    def id(self, id: str) -> AgentBuilder:
        self._id = id
        return self

    def name(self, name: str) -> AgentBuilder:
        self._name = name
        return self

    def instructions(self, instructions: str) -> AgentBuilder:
        self._instructions = instructions
        return self

    def tool(self, tool_pattern: str) -> AgentBuilder:
        self._tools.append(tool_pattern)
        return self

    def skill(self, skill_ref: str | Skill) -> AgentBuilder:
        """Add a skill by ID or object.

        Args:
            skill_ref: Skill ID string or a built Skill object.
        """
        self._skills.append(skill_ref if isinstance(skill_ref, str) else skill_ref.id)
        return self

    def handoff_description(self, description: str) -> AgentBuilder:
        self._handoff_description = description
        return self

    def max_steps(self, steps: int) -> AgentBuilder:
        self._max_steps = steps
        return self

    def model(self, model: str) -> AgentBuilder:
        self._model = model
        return self

    def pathway(self, pathway_ref: str | Pathway) -> AgentBuilder:
        """Set the pathway by ID or object.

        Args:
            pathway_ref: Pathway ID string or a built Pathway object.
        """
        self._pathway = pathway_ref if isinstance(pathway_ref, str) else pathway_ref.id
        return self

    def temperature(self, temp: float) -> AgentBuilder:
        self._temperature = temp
        return self

    def workspace(self, workspace_id: str) -> AgentBuilder:
        self._workspace_id = workspace_id
        return self

    def build(self) -> AgentDefinition:
        if not self._id:
            self._id = f"agent_{uuid.uuid4().hex[:8]}"
        if not self._name:
            self._name = self._id

        # Only pass tools if the caller explicitly added them; otherwise
        # let AgentDefinition's Pydantic default apply.
        kwargs: dict = {
            "id": self._id,
            "name": self._name,
            "instructions": self._instructions,
            "skills": self._skills,
            "handoff_description": self._handoff_description,
            "max_steps": self._max_steps,
            "model": self._model,
            "pathway": self._pathway,
            "temperature": self._temperature,
            "workspace_id": self._workspace_id,
        }
        if self._tools:
            kwargs["tools"] = self._tools
        return AgentDefinition(**kwargs)


def agent_builder() -> AgentBuilder:
    """Create a new agent builder."""
    return AgentBuilder()


__all__ = [
    "AgentBuilder",
    "agent_builder",
]
