#!/usr/bin/env python3
"""Audit issue 76's native SimpleRenderer ownership and evidence boundary."""

from __future__ import annotations

from pathlib import Path
import re

import generate_api_shims


ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / "crates" / "libremetaverse-rendering-simple" / "src" / "simple_renderer.rs"
GENERATED = ROOT / "crates" / "libremetaverse-rendering-simple" / "src" / "generated.rs"
MANIFEST = ROOT / "crates" / "libremetaverse-rendering-simple" / "Cargo.toml"
COMPAT = ROOT / "tests" / "compat" / "tests" / "rendering_shims.rs"
REFERENCE = (
    ROOT
    / "crates"
    / "libremetaverse-rendering-simple"
    / "tests"
    / "reference_pipeline.rs"
)
DOC = ROOT / "crates" / "libremetaverse-rendering-simple" / "README.md"
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")

TYPE = "T:LibreMetaverse.Rendering.SimpleRenderer"
MEMBERS = {
    "M:LibreMetaverse.Rendering.SimpleRenderer.#ctor",
    "M:LibreMetaverse.Rendering.SimpleRenderer.GenerateFacetedMesh(LibreMetaverse.Primitive,LibreMetaverse.Rendering.DetailLevel)",
    "M:LibreMetaverse.Rendering.SimpleRenderer.GenerateFacetedSculptMesh(LibreMetaverse.Primitive,LibreMetaverse.Imaging.ManagedImage,LibreMetaverse.Rendering.DetailLevel)",
    "M:LibreMetaverse.Rendering.SimpleRenderer.GenerateSimpleMesh(LibreMetaverse.Primitive,LibreMetaverse.Rendering.DetailLevel)",
    "M:LibreMetaverse.Rendering.SimpleRenderer.GenerateSimpleSculptMesh(LibreMetaverse.Primitive,LibreMetaverse.Imaging.ManagedImage,LibreMetaverse.Rendering.DetailLevel)",
    "M:LibreMetaverse.Rendering.SimpleRenderer.TransformTexCoords(System.Collections.Generic.List{LibreMetaverse.Rendering.Vertex},LibreMetaverse.Vector3,LibreMetaverse.Primitive.TextureEntryFace,LibreMetaverse.Vector3)",
}


def require_markers(path: Path, markers: tuple[str, ...]) -> None:
    text = path.read_text()
    missing = [marker for marker in markers if marker not in text]
    if missing:
        raise SystemExit(f"{path.name}: audit evidence missing: " + ", ".join(missing))


def main() -> None:
    if generate_api_shims.NATIVE_DECLARATIONS.get(TYPE) != (
        "crate::simple_renderer::SimpleRenderer"
    ):
        raise SystemExit("issue 76 SimpleRenderer native declaration is missing")
    missing = sorted(MEMBERS - set(generate_api_shims.NATIVE_MEMBER_BODIES))
    if missing:
        raise SystemExit("issue 76 native members missing: " + ", ".join(missing))
    for source in (SOURCE, GENERATED):
        if STUB_RE.search(source.read_text()):
            raise SystemExit(f"issue 76 owned Rust stubs remain in {source.name}")

    require_markers(SOURCE, (
        "impl IRendering for SimpleRenderer", "PrimMesh", "SculptMesh",
        "MAX_FACE_VERTICES", "checked_add", "u16::try_from", "checked_vertex",
        "texture_for_face", "MappingType::Planar", "Error::Rendering",
        "mesh sculpt requires a decoded mesh asset",
    ))
    manifest = MANIFEST.read_text()
    if "libremetaverse-prim-mesher" not in manifest:
        raise SystemExit("issue 76 must depend on the checked PrimMesher crate")
    forbidden = ("skia", "voice", "libremetaverse-rlv", "libremetaverse-lsl")
    leaked = [name for name in forbidden if name in manifest.lower()]
    if leaked:
        raise SystemExit("issue 76 dependency boundary leaked: " + ", ".join(leaked))

    require_markers(COMPAT, (
        "matches_golden_mesh", "0x3d2b_10e3_7da0_3d2e",
        "maps_default_and_per_face_texture_metadata", "transforms_default_and_planar",
        "generates_deterministic_sculpt_geometry", "trait_dispatch_returns_geometry",
        "reports_source_context", "rejects_non_finite_texture_inputs",
    ))
    require_markers(REFERENCE, (
        "every_profile_path_and_lod_produces_checked_geometry",
        "ProfileCurve::RightTriangle", "PathCurve::Flexible", "DetailLevel::Highest",
        "every_sculpt_topology_produces_checked_geometry_at_each_lod",
        "SculptType::Cylinder", "SculptType::Sphere", "SculptType::Torus",
    ))
    require_markers(DOC, (
        "all four `DetailLevel`", "65,536", "Error::Rendering",
        "source primitive UUID", "MeshFoundry", "prim-local coordinates",
    ))
    require_markers(WORKFLOW, ("required-gate",))
    print(
        "issue 76 audit: native prim/sculpt conversion, face metadata, texture mapping, "
        "bounded errors, deterministic evidence, dependency isolation, and docs are present"
    )


if __name__ == "__main__":
    main()
