"""AZ-281 — EngineFilenameSchema helper AC tests.

Verifies the contract at ``_docs/02_document/contracts/shared_helpers/engine_filename_schema.md`` v1.0.0.
"""

from __future__ import annotations

import ast
import random
from pathlib import Path

import pytest

from gps_denied_onboard._types.manifests import EngineCacheKey, HostCapabilities
from gps_denied_onboard.helpers import EngineFilenameSchema, EngineFilenameSchemaError


def test_ac1_reference_example_builds_exact_string() -> None:
    assert (
        EngineFilenameSchema.build("ultravpr", 87, "6.2", "10.3", "fp16")
        == "ultravpr__sm87_jp6.2_trt10.3_fp16.engine"
    )


def test_ac2_roundtrip_identity_over_10_random_tuples() -> None:
    rng = random.Random(2026)
    for _ in range(10):
        model = rng.choice(["ultravpr", "netvlad", "megaloc", "selavpr", "salad", "mix_vpr"])
        sm = rng.choice([72, 86, 87])
        jp = rng.choice(["5.1", "6.0", "6.2", "6.3"])
        trt = rng.choice(["8.6", "10.0", "10.3", "10.4"])
        prec = rng.choice(["fp16", "int8", "mixed"])
        filename = EngineFilenameSchema.build(model, sm, jp, trt, prec)
        parsed = EngineFilenameSchema.parse(filename)
        assert parsed == EngineCacheKey(model, sm, jp, trt, prec)


def test_ac3_matches_host_exact_match() -> None:
    filename = EngineFilenameSchema.build("ultravpr", 87, "6.2", "10.3", "fp16")
    host = HostCapabilities(sm=87, jetpack="6.2", trt="10.3")
    assert EngineFilenameSchema.matches_host(filename, host) is True


def test_ac4_matches_host_tuple_mismatch_returns_false() -> None:
    filename = EngineFilenameSchema.build("ultravpr", 87, "6.2", "10.3", "fp16")
    host_mismatch = HostCapabilities(sm=72, jetpack="6.2", trt="10.3")
    assert EngineFilenameSchema.matches_host(filename, host_mismatch) is False
    host_mismatch_trt = HostCapabilities(sm=87, jetpack="6.2", trt="10.4")
    assert EngineFilenameSchema.matches_host(filename, host_mismatch_trt) is False


def test_ac5_precision_enum_strictness() -> None:
    with pytest.raises(EngineFilenameSchemaError, match=r"precision"):
        EngineFilenameSchema.build("ultravpr", 87, "6.2", "10.3", "bf16")


def test_ac6_model_name_character_set_rejection() -> None:
    with pytest.raises(EngineFilenameSchemaError, match=r"a-z0-9_"):
        EngineFilenameSchema.build("UltraVPR", 87, "6.2", "10.3", "fp16")


def test_ac7_reserved_separator_collision_rejected() -> None:
    with pytest.raises(EngineFilenameSchemaError, match=r"__"):
        EngineFilenameSchema.build("ultra__vpr", 87, "6.2", "10.3", "fp16")


def test_ac8_three_segment_version_rejected() -> None:
    with pytest.raises(EngineFilenameSchemaError, match=r"major.*minor"):
        EngineFilenameSchema.build("ultravpr", 87, "6.2.1", "10.3", "fp16")


def test_ac9_parse_rejects_malformed_filename() -> None:
    with pytest.raises(EngineFilenameSchemaError):
        EngineFilenameSchema.parse("not_an_engine_file.engine")


def test_ac10_parse_requires_engine_suffix() -> None:
    with pytest.raises(EngineFilenameSchemaError, match=r"\.engine"):
        EngineFilenameSchema.parse("ultravpr__sm87_jp6.2_trt10.3_fp16")


def test_ac11_no_upward_imports_to_components() -> None:
    module_path = (
        Path(__file__).resolve().parents[2]
        / "src"
        / "gps_denied_onboard"
        / "helpers"
        / "engine_filename_schema.py"
    )
    tree = ast.parse(module_path.read_text(encoding="utf-8"))
    bad: list[str] = []
    for node in ast.walk(tree):
        if isinstance(node, ast.ImportFrom) and node.module:
            if node.module.startswith("gps_denied_onboard.components"):
                bad.append(node.module)
        elif isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name.startswith("gps_denied_onboard.components"):
                    bad.append(alias.name)
    assert not bad, f"engine_filename_schema must not import components.*; found: {bad}"
