"""Typed singleton registry for domain services.

Usage::

    from shared.services.registry import services

    # Register at app startup
    services.blog = SqlBlogService()

    # Query anywhere
    if services.has("calendar"):
        entries = await services.calendar.pending_entries(session, ...)

    # Or use stubs for absent domains
    summary = await services.cart.cart_summary(session, ...)
"""
from __future__ import annotations

from shared.contracts.protocols import (
    BlogService,
    CalendarService,
    MarketService,
    CartService,
    FederationService,
)


class _ServiceRegistry:
    """Central registry holding one implementation per domain.

    Properties return the registered implementation or raise
    ``RuntimeError`` if nothing is registered.  Use ``has(name)``
    to check before access when the domain might be absent.
    """

    def __init__(self) -> None:
        self._blog: BlogService | None = None
        self._calendar: CalendarService | None = None
        self._market: MarketService | None = None
        self._cart: CartService | None = None
        self._federation: FederationService | None = None

    # -- blog -----------------------------------------------------------------
    @property
    def blog(self) -> BlogService:
        if self._blog is None:
            raise RuntimeError("BlogService not registered")
        return self._blog

    @blog.setter
    def blog(self, impl: BlogService) -> None:
        self._blog = impl

    # -- calendar -------------------------------------------------------------
    @property
    def calendar(self) -> CalendarService:
        if self._calendar is None:
            raise RuntimeError("CalendarService not registered")
        return self._calendar

    @calendar.setter
    def calendar(self, impl: CalendarService) -> None:
        self._calendar = impl

    # -- market ---------------------------------------------------------------
    @property
    def market(self) -> MarketService:
        if self._market is None:
            raise RuntimeError("MarketService not registered")
        return self._market

    @market.setter
    def market(self, impl: MarketService) -> None:
        self._market = impl

    # -- cart -----------------------------------------------------------------
    @property
    def cart(self) -> CartService:
        if self._cart is None:
            raise RuntimeError("CartService not registered")
        return self._cart

    @cart.setter
    def cart(self, impl: CartService) -> None:
        self._cart = impl

    # -- federation -----------------------------------------------------------
    @property
    def federation(self) -> FederationService:
        if self._federation is None:
            raise RuntimeError("FederationService not registered")
        return self._federation

    @federation.setter
    def federation(self, impl: FederationService) -> None:
        self._federation = impl

    # -- introspection --------------------------------------------------------
    def has(self, name: str) -> bool:
        """Check whether a domain service is registered."""
        return getattr(self, f"_{name}", None) is not None


# Module-level singleton — import this everywhere.
services = _ServiceRegistry()
