"""Tests for LifespanServices.from_app() extraction (Issue #2135).

Validates that the typed container correctly extracts all factory-produced
services from app.state and NexusFS internals, and handles missing/None
values gracefully.
"""

from types import SimpleNamespace
from unittest.mock import MagicMock

from nexus.server.lifespan.services_container import LifespanServices

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _make_app(**state_attrs) -> MagicMock:
    """Create a minimal FastAPI-like app stub with given state attributes."""
    app = MagicMock()
    app.state = SimpleNamespace(**state_attrs)
    return app


def _make_nexus_fs(**attrs) -> SimpleNamespace:
    """Create a NexusFS stub with given attributes.

    Includes a service() method that returns None (simulates empty ServiceRegistry).
    Pass _service_map={"name": val} to simulate registered services.
    """
    _service_map = attrs.pop("_service_map", {})
    defaults = {
        "SessionLocal": None,
        "_sql_engine": None,
        "workflow_engine": None,
        "_snapshot_service": None,
        "config": None,
        "service_coordinator": None,
        "_agent_registry": None,
    }
    defaults.update(attrs)
    ns = SimpleNamespace(**defaults)
    ns.service = lambda name: _service_map.get(name)
    return ns


# ---------------------------------------------------------------------------
# from_app() — core extraction
# ---------------------------------------------------------------------------


class TestFromAppExtraction:
    """Test that from_app() extracts all factory services."""

    def test_bare_app_produces_all_none(self) -> None:
        """App with no nexus_fs yields container with all None."""
        app = _make_app()
        svc = LifespanServices.from_app(app)

        assert svc.nexus_fs is None
        assert svc.database_url is None
        assert svc.record_store is None
        assert svc.event_bus is None
        assert svc.rebac_manager is None

    def test_extracts_top_level_state(self) -> None:
        """Top-level app.state attributes are extracted."""
        app = _make_app(
            nexus_fs=None,
            database_url="postgresql://localhost/test",
            record_store="fake_rs",
            zone_id="zone-42",
            deployment_profile="lite",
            deployment_mode="federated",
            profile_tuning="fake_tuning",
            thread_pool_size=80,
        )
        svc = LifespanServices.from_app(app)

        assert svc.database_url == "postgresql://localhost/test"
        assert svc.record_store == "fake_rs"
        assert svc.zone_id == "zone-42"
        assert svc.deployment_profile == "lite"
        assert svc.deployment_mode == "federated"
        assert svc.profile_tuning == "fake_tuning"
        assert svc.thread_pool_size == 80

    def test_extracts_nexus_fs_internals(self) -> None:
        """NexusFS private attributes + service registry entries are extracted."""
        nx = _make_nexus_fs(
            SessionLocal="session_factory",
            _sql_engine="sql_engine",
            workflow_engine="wf_engine",
            config="nexus_cfg",
            _event_bus="event_bus",
            _service_map={
                "entity_registry": "entity_reg",
                "permission_enforcer": "perm_enf",
                "rebac_manager": "rebac_mgr",
                "async_namespace_manager": "ns_mgr",
                "snapshot_service": "snap_svc",
            },
        )
        app = _make_app(nexus_fs=nx)
        svc = LifespanServices.from_app(app)

        assert svc.nexus_fs is nx
        assert svc.session_factory == "session_factory"
        assert svc.sql_engine == "sql_engine"
        assert svc.entity_registry == "entity_reg"
        assert svc.permission_enforcer == "perm_enf"
        assert svc.rebac_manager == "rebac_mgr"
        assert svc.event_bus == "event_bus"
        assert svc.coordination_client is None  # sentinel deleted from NexusFS
        assert svc.workflow_engine == "wf_engine"
        assert svc.snapshot_service == "snap_svc"
        assert svc.namespace_manager == "ns_mgr"
        assert svc.nexus_config == "nexus_cfg"


class TestFromAppSystemServices:
    """Test extraction from ServiceRegistry (previously _system_services)."""

    def test_extracts_agent_registry_from_kernel_handle(self) -> None:
        """AgentRegistry resolves from `nx._kernel.agent_registry` (the
        Rust SSOT handle); the Python shim was deleted in the
        feat/agent-registry-python-fold PR."""
        agent_registry = object()
        kernel_stub = SimpleNamespace(agent_registry=agent_registry)
        nx = _make_nexus_fs(_kernel=kernel_stub)
        app = _make_app(nexus_fs=nx)
        svc = LifespanServices.from_app(app)

        assert svc.agent_registry is agent_registry

    def test_extracts_system_services(self) -> None:
        """System services (eviction_manager, etc.) are extracted via nx.service()."""
        nx = _make_nexus_fs(
            _service_map={
                "eviction_manager": "em",
                "write_observer": "write_obs",
                "zone_lifecycle": "zl",
            },
        )
        app = _make_app(nexus_fs=nx)
        svc = LifespanServices.from_app(app)

        assert svc.eviction_manager == "em"
        assert svc.write_observer == "write_obs"
        assert svc.zone_lifecycle == "zl"

    def test_empty_service_registry_yields_none(self) -> None:
        """When no services registered, all system service fields are None."""
        nx = _make_nexus_fs()
        app = _make_app(nexus_fs=nx)
        svc = LifespanServices.from_app(app)

        assert svc.eviction_manager is None


class TestFromAppObservability:
    """Test extraction of observability_subsystem from ServiceRegistry."""

    def test_extracts_observability_subsystem(self) -> None:
        """observability_subsystem extracted from ServiceRegistry."""
        nx = _make_nexus_fs(_service_map={"observability_subsystem": "obs_sub"})
        app = _make_app(nexus_fs=nx)
        svc = LifespanServices.from_app(app)

        assert svc.observability_subsystem == "obs_sub"

    def test_empty_registry_yields_none(self) -> None:
        """When no service registered, observability_subsystem is None."""
        nx = _make_nexus_fs()
        app = _make_app(nexus_fs=nx)
        svc = LifespanServices.from_app(app)

        assert svc.observability_subsystem is None


class TestFromAppDefaults:
    """Test default values when attributes are absent from app.state."""

    def test_deployment_profile_defaults_to_full(self) -> None:
        app = _make_app()
        svc = LifespanServices.from_app(app)
        assert svc.deployment_profile == "full"

    def test_deployment_mode_defaults_to_standalone(self) -> None:
        app = _make_app()
        svc = LifespanServices.from_app(app)
        assert svc.deployment_mode == "standalone"

    def test_thread_pool_size_defaults_to_40(self) -> None:
        app = _make_app()
        svc = LifespanServices.from_app(app)
        assert svc.thread_pool_size == 40

    def test_enabled_bricks_defaults_to_empty_frozenset(self) -> None:
        app = _make_app()
        svc = LifespanServices.from_app(app)
        assert svc.enabled_bricks == frozenset()


class TestFromAppEdgeCases:
    """Edge cases for from_app() robustness."""

    def test_nexus_fs_without_optional_attributes(self) -> None:
        """NexusFS missing some private attrs doesn't crash."""
        # Use a SimpleNamespace with only _system_services
        nx = SimpleNamespace(_system_services=None)
        app = _make_app(nexus_fs=nx)

        # Should not raise even though nx has no SessionLocal, etc.
        svc = LifespanServices.from_app(app)
        assert svc.nexus_fs is nx
        assert svc.write_observer is None  # extracted from _system_services (None here)
        assert svc.rebac_manager is None

    def test_observability_registry_extracted(self) -> None:
        """observability_registry from app.state is extracted."""
        app = _make_app(observability_registry="obs_reg")
        svc = LifespanServices.from_app(app)
        assert svc.observability_registry == "obs_reg"
