"""Actor Runtime for Logos ADK."""
from __future__ import annotations

import threading
from dataclasses import dataclass
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from logos_adk.agent import Agent


@dataclass
class Supervisor:
    """Supervision policy for agent failures."""

    on_failure: str = "restart"
    max_retries: int = 3
    on_max_retries: str = "escalate"


class _DefaultRuntimeHolder:
    """Holds the process-level default Runtime."""

    def __init__(self) -> None:
        self._default: Runtime | None = None

    def get(self) -> Runtime | None:
        return self._default

    def set(self, runtime: Runtime) -> None:
        self._default = runtime

    def get_or_create(self) -> Runtime:
        if self._default is None:
            Runtime()
        assert self._default is not None
        return self._default

    def reset(self) -> None:
        """Reset default runtime. For testing only."""
        self._default = None


_default_runtime_holder = _DefaultRuntimeHolder()


class Runtime:
    """Manages agent lifecycle, message delivery, and supervision."""

    def __init__(self, supervisor: Supervisor | None = None) -> None:
        self.supervisor = supervisor or Supervisor()
        self._agents: dict[str, Agent] = {}
        self._lock = threading.Lock()

        if _default_runtime_holder.get() is None:
            _default_runtime_holder.set(self)

    def set_as_default(self) -> None:
        """Register this runtime as the process-level default."""
        _default_runtime_holder.set(self)

    def spawn(self, agent: Agent) -> None:
        """Register an agent in this runtime."""
        with self._lock:
            if agent.name in self._agents:
                raise ValueError(f"Agent '{agent.name}' already registered in this runtime")
            self._agents[agent.name] = agent
        agent._runtime = self

    def stop(self, agent: Agent) -> None:
        """Unregister an agent from this runtime."""
        with self._lock:
            self._agents.pop(agent.name, None)
        agent._runtime = None

    def get_agent(self, name: str) -> Agent | None:
        """Get a registered agent by name."""
        with self._lock:
            return self._agents.get(name)
