from __future__ import annotations

"""User-facing builder for `AgentRunner`."""

from dataclasses import dataclass, field

from agentrspy.core import AgentError, LlmProvider, Memory, Tool
from agentrspy.memory import InMemoryMemory
from agentrspy.tools import ToolRegistry

from .runner import AgentConfig, AgentRunner, LoopStrategy


class Agent:
    """User-facing entrypoint for agent construction."""

    @staticmethod
    def builder() -> "AgentBuilder":
        return AgentBuilder()


@dataclass(slots=True)
class AgentBuilder:
    """Builder for `AgentRunner`."""

    llm_provider: LlmProvider | None = None
    memory_backend: Memory = field(default_factory=InMemoryMemory.new)
    tools_registry: ToolRegistry = field(default_factory=ToolRegistry.new)
    system_prompt: str | None = None
    config: AgentConfig = field(default_factory=AgentConfig)

    def system(self, prompt: str) -> "AgentBuilder":
        self.system_prompt = prompt
        return self

    def tools(self, tools: ToolRegistry) -> "AgentBuilder":
        self.tools_registry = tools
        return self

    def tool(self, tool: Tool) -> "AgentBuilder":
        self.tools_registry = self.tools_registry.register(tool)
        return self

    def memory(self, memory: Memory) -> "AgentBuilder":
        self.memory_backend = memory
        return self

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

    def temperature(self, temperature: float) -> "AgentBuilder":
        self.config.temperature = temperature
        return self

    def max_tokens(self, max_tokens: int) -> "AgentBuilder":
        self.config.max_tokens = max_tokens
        return self

    def loop_strategy(self, loop_strategy: LoopStrategy) -> "AgentBuilder":
        self.config.max_steps = loop_strategy.max_steps_hint(self.config.max_steps)
        self.config.loop_strategy = loop_strategy
        return self

    def max_steps(self, max_steps: int) -> "AgentBuilder":
        self.config.max_steps = max_steps
        return self

    def llm(self, llm: LlmProvider) -> "AgentBuilder":
        self.llm_provider = llm
        return self

    def llm_arc(self, llm: LlmProvider) -> "AgentBuilder":
        return self.llm(llm)

    def build(self) -> AgentRunner:
        if self.llm_provider is None:
            raise AgentError.no_llm_provider()
        return AgentRunner(
            llm=self.llm_provider,
            memory=self.memory_backend,
            tools=self.tools_registry,
            system_prompt=self.system_prompt,
            config=self.config,
        )
