from __future__ import annotations

import importlib
import sys
from types import ModuleType


def _reload_modules() -> None:
    for name in ["cadis", "cadis._api", "cadis._manager", "cadis._sdk"]:
        sys.modules.pop(name, None)


def test_lookup_does_not_auto_install_dataset() -> None:
    class _GlobalLookupImpl:
        @classmethod
        def from_defaults(cls):
            return cls()

        def lookup(self, lat: float, lon: float):
            return {
                "lookup_status": "ok",
                "world_context": {"country": {"iso2": "TW", "name": "Taiwan"}},
            }

    cadis_world = ModuleType("cadis.world")
    cadis_world.GlobalLookup = _GlobalLookupImpl
    sys.modules["cadis.world"] = cadis_world
    cadis_runtime = ModuleType("cadis.runtime")
    cadis_runtime.inspect_dataset = lambda dataset_dir: {"state": {"dataset": {"status": "missing"}}}
    sys.modules["cadis.runtime"] = cadis_runtime

    _reload_modules()
    cadis = importlib.import_module("cadis")

    from pathlib import Path
    import tempfile
    import os

    with tempfile.TemporaryDirectory() as td:
        cache_root = Path(td)
        os.environ["CADIS_CACHE_DIR"] = str(cache_root)
        try:
            payload = cadis.lookup(25.03, 121.56)
        finally:
            os.environ.pop("CADIS_CACHE_DIR", None)

    assert payload["execution"]["lookup_status"] == "failed"
    assert payload["state"]["dataset"]["status"] == "missing"
    assert "world_context" not in payload


def test_bootstrap_and_lookup_sdk_flow() -> None:
    class _GlobalLookupImpl:
        @classmethod
        def from_defaults(cls):
            return cls()

        def lookup(self, lat: float, lon: float):
            return {
                "lookup_status": "ok",
                "world_context": {"country": {"iso2": "TW", "name": "Taiwan"}},
            }

    class _Runtime:
        calls = 0

        def __init__(self, *, dataset_dir: str):
            self.dataset_dir = dataset_dir

        def lookup(self, lat: float, lon: float):
            _Runtime.calls += 1
            return {"lookup_status": "ok", "result": {"admin_hierarchy": []}}

    cadis_world = ModuleType("cadis.world")
    cadis_world.GlobalLookup = _GlobalLookupImpl
    sys.modules["cadis.world"] = cadis_world

    cadis_cdn = ModuleType("cadis.cdn")
    cadis_cdn.parse_version_for_sort = lambda raw: (1, 0, 0)
    cadis_cdn.install_dataset = lambda **kwargs: {
        "country_iso2": "TW",
        "dataset_id": "tw.admin",
        "dataset_version": "v1.0.0",
        "dataset_dir": "/tmp/cadis/TW/tw.admin/v1.0.0",
    }
    sys.modules["cadis.cdn"] = cadis_cdn

    cadis_runtime = ModuleType("cadis.runtime")
    cadis_runtime.inspect_dataset = lambda dataset_dir: {"state": {"dataset": {"status": "ready"}}}
    cadis_runtime.bootstrap_dataset = lambda dataset_dir: {"bootstrap_status": "ready"}
    cadis_runtime.CadisRuntime = _Runtime
    sys.modules["cadis.runtime"] = cadis_runtime

    _reload_modules()
    cadis = importlib.import_module("cadis")
    sdk = cadis.CadisSDK()

    bootstrap = sdk.bootstrap("TW")
    assert bootstrap["bootstrap_status"] == "ready"

    payload = sdk.lookup(25.03, 121.56)
    assert payload["execution"]["lookup_status"] == "ok"
    assert _Runtime.calls == 1
    assert "world_context" not in payload


def test_lookup_reports_invalid_for_corrupted_local_dataset() -> None:
    class _GlobalLookupImpl:
        @classmethod
        def from_defaults(cls):
            return cls()

        def lookup(self, lat: float, lon: float):
            return {
                "lookup_status": "ok",
                "world_context": {"country": {"iso2": "TW", "name": "Taiwan"}},
            }

    cadis_world = ModuleType("cadis.world")
    cadis_world.GlobalLookup = _GlobalLookupImpl
    sys.modules["cadis.world"] = cadis_world

    cadis_runtime = ModuleType("cadis.runtime")
    cadis_runtime.inspect_dataset = lambda dataset_dir: {
        "state": {"dataset": {"status": "invalid"}}
    }
    sys.modules["cadis.runtime"] = cadis_runtime

    cadis_cdn = ModuleType("cadis.cdn")
    cadis_cdn.parse_version_for_sort = lambda raw: (1, 0, 0)
    sys.modules["cadis.cdn"] = cadis_cdn

    _reload_modules()
    cadis = importlib.import_module("cadis")

    from pathlib import Path
    import tempfile

    with tempfile.TemporaryDirectory() as td:
        cache_root = Path(td)
        version_dir = cache_root / "TW" / "tw.admin" / "v1.0.0"
        version_dir.mkdir(parents=True)
        # Ensure cadis uses this temp cache root.
        import os

        os.environ["CADIS_CACHE_DIR"] = str(cache_root)
        try:
            payload = cadis.lookup(25.03, 121.56)
        finally:
            os.environ.pop("CADIS_CACHE_DIR", None)

    assert payload["execution"]["lookup_status"] == "failed"
    assert payload["state"]["dataset"]["status"] == "invalid"
    assert "world_context" not in payload


def test_lookup_world_boundary_uses_state_world_only() -> None:
    class _GlobalLookupImpl:
        @classmethod
        def from_defaults(cls):
            return cls()

        def lookup(self, lat: float, lon: float):
            return {
                "lookup_status": "ok",
                "world_context": {
                    "world_result": {"type": "open_sea", "name": "Open Sea"},
                },
            }

    cadis_world = ModuleType("cadis.world")
    cadis_world.GlobalLookup = _GlobalLookupImpl
    sys.modules["cadis.world"] = cadis_world

    _reload_modules()
    cadis = importlib.import_module("cadis")
    payload = cadis.lookup(0.0, -160.0)

    assert payload["execution"]["lookup_status"] == "failed"
    assert payload["state"]["world"]["classification"] == "open_sea"
    assert payload["state"]["world"]["name"] == "Open Sea"
    assert "label" not in payload["state"]["world"]
    assert "world_context" not in payload


def test_reinstall_uses_force_reinstall_path() -> None:
    class _GlobalLookupImpl:
        @classmethod
        def from_defaults(cls):
            return cls()

        def lookup(self, lat: float, lon: float):
            return {
                "lookup_status": "ok",
                "world_context": {"country": {"iso2": "TW", "name": "Taiwan"}},
            }

    cadis_world = ModuleType("cadis.world")
    cadis_world.GlobalLookup = _GlobalLookupImpl
    sys.modules["cadis.world"] = cadis_world

    install_args: dict[str, object] = {}
    cadis_cdn = ModuleType("cadis.cdn")
    cadis_cdn.parse_version_for_sort = lambda raw: (1, 0, 0)

    def _install_dataset(**kwargs):
        install_args.update(kwargs)
        return {
            "country_iso2": "TW",
            "dataset_id": "tw.admin",
            "dataset_version": "v1.0.0",
            "dataset_dir": "/tmp/cadis/TW/tw.admin/v1.0.0",
        }

    cadis_cdn.install_dataset = _install_dataset
    sys.modules["cadis.cdn"] = cadis_cdn

    cadis_runtime = ModuleType("cadis.runtime")
    cadis_runtime.inspect_dataset = lambda dataset_dir: {"state": {"dataset": {"status": "ready"}}}
    cadis_runtime.bootstrap_dataset = lambda dataset_dir: {"bootstrap_status": "ready"}
    cadis_runtime.CadisRuntime = lambda **kwargs: object()
    sys.modules["cadis.runtime"] = cadis_runtime

    _reload_modules()
    cadis = importlib.import_module("cadis")
    out = cadis.reinstall("TW")

    assert out["bootstrap_status"] == "ready"
    assert install_args.get("force_reinstall") is True
