import importlib
import sys
from pathlib import Path

import pytest

from iisi_app_core.bootstrap import ModuleAutoloadError, autoload


def _create_pkg_file(path: Path, content: str = "") -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")


def test_autoload_imports_all_modules_except_init(tmp_path: Path) -> None:
    pkg_root = tmp_path / "samplepkg_autoload"
    _create_pkg_file(pkg_root / "__init__.py")
    _create_pkg_file(pkg_root / "a.py")
    _create_pkg_file(pkg_root / "sub" / "__init__.py")
    _create_pkg_file(pkg_root / "sub" / "b.py")

    sys.path.insert(0, str(tmp_path))
    try:
        package = importlib.import_module("samplepkg_autoload")
    finally:
        sys.path.remove(str(tmp_path))

    modules = autoload(package)
    again = autoload(package)

    assert [module.__name__ for module in modules] == ["samplepkg_autoload.a", "samplepkg_autoload.sub.b"]
    assert [module.__name__ for module in again] == ["samplepkg_autoload.a", "samplepkg_autoload.sub.b"]


def test_autoload_rejects_non_package_input() -> None:
    with pytest.raises(TypeError):
        autoload(object())


def test_autoload_wraps_module_import_errors(tmp_path: Path) -> None:
    pkg_root = tmp_path / "brokenpkg_autoload"
    _create_pkg_file(pkg_root / "__init__.py")
    _create_pkg_file(pkg_root / "broken.py", "raise RuntimeError('boom')\n")

    sys.path.insert(0, str(tmp_path))
    try:
        package = importlib.import_module("brokenpkg_autoload")
        with pytest.raises(ModuleAutoloadError) as exc:
            autoload(package)
    finally:
        sys.path.remove(str(tmp_path))

    assert exc.value.module_name == "brokenpkg_autoload.broken"
