from __future__ import annotations

import builtins
import importlib
import sys
import types


def test_root_package_does_not_reexport_research_implementations() -> None:
    import sage_libs.sage_privacy as privacy

    assert "register_to_sage" in privacy.__all__
    assert "GradientAscentUnlearner" not in privacy.__all__
    assert "FisherForgettingUnlearner" not in privacy.__all__
    assert "GaussianMechanism" not in privacy.__all__
    assert "LaplaceMechanism" not in privacy.__all__


def test_root_import_no_registration_side_effect(monkeypatch) -> None:
    original_import = builtins.__import__

    def guarded_import(name, globals=None, locals=None, fromlist=(), level=0):
        if name.startswith("sage.libs.privacy.interface"):
            raise AssertionError("root import must not touch sage.libs.privacy.interface")
        return original_import(name, globals, locals, fromlist, level)

    monkeypatch.setattr(builtins, "__import__", guarded_import)

    sys.modules.pop("sage_libs.sage_privacy", None)
    module = importlib.import_module("sage_libs.sage_privacy")
    assert hasattr(module, "register_to_sage")


def test_register_to_sage_is_explicit_and_calls_registry(monkeypatch) -> None:
    calls: list[tuple[str, str, type]] = []

    def register_unlearner(name: str, cls: type) -> None:
        calls.append(("unlearner", name, cls))

    def register_mechanism(name: str, cls: type) -> None:
        calls.append(("mechanism", name, cls))

    sage_module = types.ModuleType("sage")
    libs_module = types.ModuleType("sage.libs")
    privacy_module = types.ModuleType("sage.libs.privacy")
    interface_module = types.ModuleType("sage.libs.privacy.interface")
    interface_module.register_unlearner = register_unlearner
    interface_module.register_mechanism = register_mechanism

    monkeypatch.setitem(sys.modules, "sage", sage_module)
    monkeypatch.setitem(sys.modules, "sage.libs", libs_module)
    monkeypatch.setitem(sys.modules, "sage.libs.privacy", privacy_module)
    monkeypatch.setitem(sys.modules, "sage.libs.privacy.interface", interface_module)

    from sage_libs.sage_privacy import register_to_sage

    register_to_sage()

    assert {item[:2] for item in calls} == {
        ("unlearner", "gradient_ascent"),
        ("unlearner", "fisher_forgetting"),
        ("mechanism", "gaussian"),
        ("mechanism", "laplace"),
    }
