"""Agent context for sharing state across the agent lifecycle."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass
class AgentContext:
    """Context object passed through the agent lifecycle.

    This allows sharing state between:
    - The agent and its tools
    - Different steps in the agent loop
    - Hooks and middleware
    - Parent and child agents (for multi-agent scenarios)
    """

    # Unique identifier for this run
    run_id: str = ""

    # User-provided input that started this run
    user_input: str = ""

    # Current step number
    step: int = 0

    # Arbitrary state that tools and hooks can read/write
    state: dict[str, Any] = field(default_factory=dict)

    # Metadata about the run (model, config, etc.)
    metadata: dict[str, Any] = field(default_factory=dict)

    # Parent context for nested agent calls
    parent: AgentContext | None = None

    # Accumulated data from the run
    tool_calls: list[dict[str, Any]] = field(default_factory=list)
    tool_results: list[dict[str, Any]] = field(default_factory=list)

    def get(self, key: str, default: Any = None) -> Any:
        """Get a value from state."""
        return self.state.get(key, default)

    def set(self, key: str, value: Any) -> None:
        """Set a value in state."""
        self.state[key] = value

    def update(self, **kwargs: Any) -> None:
        """Update multiple state values."""
        self.state.update(kwargs)

    def child(self, **overrides: Any) -> AgentContext:
        """Create a child context for nested agent calls."""
        return AgentContext(
            parent=self,
            metadata=self.metadata.copy(),
            state=self.state.copy(),
            **overrides,
        )

    def record_tool_call(
        self,
        name: str,
        args: dict[str, Any],
        result: str,
        success: bool,
    ) -> None:
        """Record a tool call for observability."""
        self.tool_calls.append({"name": name, "args": args})
        self.tool_results.append({"name": name, "result": result, "success": success})
