"""Architectural tier placement regression tests (Issues #2360, #2366).

These tests verify that key modules remain in their correct architectural tier
per NEXUS-LEGO-ARCHITECTURE.md. They act as living documentation — if a future
refactor accidentally moves a file, these tests will catch it.
"""

import importlib

# KERNEL_REQUIRED_METHODS is auto-generated by scripts/codegen_kernel_abi.py.
# Importing from there ensures the test always checks the same method set
# that _rust_compat.py validates at runtime — single source of truth.
from nexus._kernel_api_groups import KERNEL_REQUIRED_METHODS

_PIPE_PRIMITIVES = {m for m in KERNEL_REQUIRED_METHODS if "pipe" in m}


class TestPipeTierPlacement:
    """pipe.py (PipeBackend protocol + exceptions) is a kernel VFS primitive — stays in core/.
    PipeManager (fs/pipe.c equivalent) is now a Rust-native kernel primitive exposed via
    nexus_runtime.PyKernel — no Python module for it.

    Issue #2366: PipeManager is a kernel primitive per KERNEL-ARCHITECTURE.md.
    Post IPC-Rust-ification (2026-04-07): PipeManager lives in the Rust kernel binary,
    accessed through nexus_runtime.PyKernel.{create_pipe, destroy_pipe, pipe_read_nowait,
    pipe_write_nowait, ...}.
    """

    def test_pipe_backend_protocol_in_core(self) -> None:
        mod = importlib.import_module("nexus.core.pipe")
        assert hasattr(mod, "PipeBackend")

    def test_pipe_manager_in_rust_kernel(self) -> None:
        """All pipe primitives in KERNEL_REQUIRED_METHODS must exist on nexus_runtime.PyKernel.

        Method list is sourced from _kernel_api_groups.py (auto-generated),
        so this test and the runtime check in _rust_compat.py stay in sync.
        """
        nexus_runtime = importlib.import_module("nexus_runtime")
        kernel_cls = nexus_runtime.PyKernel
        for method in _PIPE_PRIMITIVES:
            assert hasattr(kernel_cls, method), (
                f"nexus_runtime.PyKernel missing pipe primitive: {method}"
            )


class TestSchedulerTierPlacement:
    """Scheduler is a system service — MUST be in system_services/ and wired via factory (Issue #2360)."""

    def test_scheduler_protocol_in_contracts(self) -> None:
        mod = importlib.import_module("nexus.contracts.protocols.scheduler")
        assert hasattr(mod, "SchedulerProtocol")
        assert hasattr(mod, "CreditsReservationProtocol")
        assert hasattr(mod, "NullCreditsReservation")

    def test_in_memory_scheduler_in_system_services(self) -> None:
        mod = importlib.import_module("nexus.services.scheduler.in_memory")
        assert hasattr(mod, "InMemoryScheduler")

    def test_classify_agent_request_in_system_services(self) -> None:
        mod = importlib.import_module("nexus.services.scheduler.policies.classifier")
        assert hasattr(mod, "classify_agent_request")

    def test_scheduler_service_in_system_services(self) -> None:
        mod = importlib.import_module("nexus.services.scheduler.service")
        assert hasattr(mod, "SchedulerService")
