"""ServiceContainer — boot-time services, frozen after creation.

Created once by ``Runtime.create()`` and shared across all executions.
Uses concrete types directly — protocols only where real extensibility exists.
"""

from __future__ import annotations

from pydantic import BaseModel

from core.pathways.service import PathwayService  # noqa: TC001 (Pydantic needs at runtime)
from core.protocols.services import (  # noqa: TC001
    PathwayVMLike,
    StateStoreLike,
)
from infrastructure.mcp.client import McpClientService  # noqa: TC001
from persistence.service import StudioDomainService  # noqa: TC001
from persistence.store import StudioStore  # noqa: TC001


class ServiceContainer(BaseModel):
    """Immutable bag of boot-time services injected into every Context.

    Frozen after creation — services are set once during ``Runtime.create()``
    and never mutated.  Nodes access them via ``ctx.services.<name>``.

    The ``runtime`` field provides access to the owning Runtime for tools
    that need agent execution (e.g. ``agent.turn``, ``agent.list``).
    """

    model_config = {"arbitrary_types_allowed": True, "frozen": True}

    # The owning runtime — gives tools access to turn() and agent_repo
    runtime: object | None = None

    pathway_service: PathwayService | None = None
    pathway_executor: PathwayVMLike | None = None
    state_store: StateStoreLike | None = None
    mcp_client: McpClientService | None = None
    studio_store: StudioStore | None = None
    domain: StudioDomainService | None = None


__all__ = ["ServiceContainer"]
