#![cfg(not(target_arch = "wasm32"))]

use std::fs;
use std::path::{Path, PathBuf};
use std::time::{Instant, SystemTime, UNIX_EPOCH};

use scena::{
    AdapterLimitsReport, Angle, Assets, Backend, Capabilities, Color, DirectionalLight,
    GeometryDesc, GpuAdapterReport, MaterialDesc, NotPreparedReason, PerspectiveCamera, PointLight,
    Primitive, RenderError, Renderer, RendererOptions, Scene, SpotLight, SurfaceEvent, Transform,
    Vec3,
};

const CAMERA_DISTANCE_FOR_NDC_FIXTURES: f32 = 1.732_050_8;
const STATIC_GLTF_PROOF_FIXTURE: &str = "tests/assets/gltf/non_ndc_camera_scene.gltf";
const BENCHMARK_BASELINE_PATH: &str = "tests/fixtures/m9-baselines.json";
const BENCHMARK_SAMPLE_COUNT: usize = 100;
const DEDICATED_4K_SAMPLE_COUNT: usize = 100;
const HEADLESS_CPU_LANE: &str = "headless-cpu";
const PBR_DIRECTIONAL_RED_PPM: &str = "pbr-directional-red.ppm";
const PBR_POINT_GREEN_PPM: &str = "pbr-point-green.ppm";
const PBR_SPOT_BLUE_PPM: &str = "pbr-spot-blue.ppm";

fn root() -> &'static Path {
    Path::new(env!("CARGO_MANIFEST_DIR"))
}

fn current_lane() -> &'static str {
    if cfg!(target_os = "macos") {
        "macos-metal"
    } else if cfg!(target_os = "windows") {
        "windows-dx12"
    } else {
        "linux-native-vulkan"
    }
}

fn platform_dir() -> PathBuf {
    root().join("target/gate-artifacts/m9-platform")
}

fn lane_dir() -> PathBuf {
    platform_dir().join(current_lane())
}

fn headless_cpu_dir() -> PathBuf {
    platform_dir().join(HEADLESS_CPU_LANE)
}

#[test]
fn m9_platform_rendered_output_suite_writes_release_artifacts() {
    let lane = current_lane();
    let artifact_dir = lane_dir();
    fs::create_dir_all(&artifact_dir).expect("artifact dir");

    let default = render_default_scene_platform(96, 64);
    let default_ppm = artifact_dir.join("default-scene.ppm");
    write_ppm(&default_ppm, default.width, default.height, &default.frame);
    assert!(
        default.nonblack_pixels > 0,
        "default scene renders nonblack pixels"
    );

    let static_gltf = render_static_gltf_platform(96, 64);
    let static_gltf_ppm = artifact_dir.join("static-gltf.ppm");
    write_ppm(
        &static_gltf_ppm,
        static_gltf.width,
        static_gltf.height,
        &static_gltf.frame,
    );
    assert!(
        static_gltf.nonblack_pixels > 0,
        "static glTF fixture renders nonblack pixels"
    );

    let pbr_lights = render_pbr_light_suite_platform(96, 64);
    for proof in &pbr_lights {
        write_ppm(
            &proof.ppm_path,
            proof.artifact.width,
            proof.artifact.height,
            &proof.artifact.frame,
        );
    }

    let default_gpu_proof = production_claim_for_gpu(&default);
    let static_gltf_gpu_proof = production_claim_for_gpu(&static_gltf);
    let pbr_light_gpu_proof = pbr_lights
        .iter()
        .all(|proof| production_claim_for_gpu(&proof.artifact) && proof.color_assertion_passed);
    let capabilities = capability_json(lane, &default);
    let capability_path = artifact_dir.join("capabilities.json");
    write_json(&capability_path, &capabilities);

    let proof = serde_json::json!({
        "schema": "scena.m9.platform_render.v1",
        "lane": lane,
        "os": std::env::consts::OS,
        "backend": format!("{:?}", default.capabilities.backend),
        "host_gpu_attempted": true,
        "host_gpu_available": default.host_gpu_available,
        "host_gpu_error": default.host_gpu_error,
        "gpu_proof": default_gpu_proof && static_gltf_gpu_proof,
        "fallback_policy": "cpu fallback is diagnostic only and never satisfies GPU rendered-output claims",
        "commit": current_commit_label(),
        "commit_sha": current_commit_label(),
        "timestamp_unix_seconds": current_timestamp_unix_seconds(),
        "test_names": [
            "m9_platform_rendered_output_suite_writes_release_artifacts",
            "m9_capability_matrix_artifact_covers_required_lanes",
            "m9_surface_context_loss_artifact_records_required_sequence"
        ],
        "artifact_paths": [
            path_string(&default_ppm),
            path_string(&static_gltf_ppm),
            path_string(&pbr_lights[0].ppm_path),
            path_string(&pbr_lights[1].ppm_path),
            path_string(&pbr_lights[2].ppm_path),
            path_string(&capability_path),
            path_string(&artifact_dir.join("rendered-output.json"))
        ],
        "default_scene": {
            "proof_class": "harness-smoke",
            "production_claim": false,
            "gpu_proof": default_gpu_proof,
            "backend": format!("{:?}", default.capabilities.backend),
            "host_gpu_available": default.host_gpu_available,
            "host_gpu_error": default.host_gpu_error,
            "adapter": adapter_metadata(default.adapter.as_ref()),
            "renderer_settings": screenshot_renderer_settings(&default),
            "color_management": screenshot_color_management(),
            "tolerance": screenshot_tolerance_metadata(),
            "screenshot": path_string(&default_ppm),
            "width": default.width,
            "height": default.height,
            "draw_calls": default.draw_calls,
            "nonblack_pixels": default.nonblack_pixels,
        },
        "static_gltf": {
            "source": STATIC_GLTF_PROOF_FIXTURE,
            "proof_class": static_gltf_proof_class(static_gltf_gpu_proof),
            "production_claim": static_gltf_gpu_proof,
            "gpu_proof": static_gltf_gpu_proof,
            "backend": format!("{:?}", static_gltf.capabilities.backend),
            "host_gpu_available": static_gltf.host_gpu_available,
            "host_gpu_error": static_gltf.host_gpu_error,
            "adapter": adapter_metadata(static_gltf.adapter.as_ref()),
            "asset_provenance": asset_provenance(STATIC_GLTF_PROOF_FIXTURE),
            "renderer_settings": screenshot_renderer_settings(&static_gltf),
            "color_management": screenshot_color_management(),
            "tolerance": screenshot_tolerance_metadata(),
            "screenshot": path_string(&static_gltf_ppm),
            "width": static_gltf.width,
            "height": static_gltf.height,
            "draw_calls": static_gltf.draw_calls,
            "nonblack_pixels": static_gltf.nonblack_pixels,
        },
        "pbr_lights": {
            "proof_class": "native-pbr-punctual-light",
            "production_claim": pbr_light_gpu_proof,
            "gpu_proof": pbr_light_gpu_proof,
            "fallback_policy": "CPU fallback records diagnostics only and never satisfies native PBR light proof",
            "lights": pbr_lights.iter().map(PbrLightProof::to_json).collect::<Vec<_>>(),
        },
        "capabilities": path_string(&capability_path),
    });
    write_json(&artifact_dir.join("rendered-output.json"), &proof);

    write_headless_cpu_lane_artifacts();
    write_benchmark_artifact(lane);
}

#[test]
fn m9_cpu_fallback_artifacts_do_not_claim_gpu_rendered_output() {
    let fallback = RenderedArtifact {
        width: 1,
        height: 1,
        frame: vec![0, 0, 0, 255],
        nonblack_pixels: 0,
        draw_calls: 0,
        capabilities: Capabilities::for_backend(Backend::Headless),
        host_gpu_available: false,
        host_gpu_error: Some("adapter unavailable".to_string()),
        adapter: None,
    };

    assert!(!production_claim_for_gpu(&fallback));
    assert_eq!(
        static_gltf_proof_class(production_claim_for_gpu(&fallback)),
        "cpu-fallback-camera-framed-non-ndc"
    );
}

#[test]
fn m9_screenshot_metadata_records_renderer_color_and_tolerance_contract() {
    let artifact = RenderedArtifact {
        width: 96,
        height: 64,
        frame: vec![0, 0, 0, 255],
        nonblack_pixels: 0,
        draw_calls: 0,
        capabilities: Capabilities::for_backend(Backend::Headless),
        host_gpu_available: false,
        host_gpu_error: None,
        adapter: None,
    };

    let settings = screenshot_renderer_settings(&artifact);
    assert_eq!(settings["width"], 96);
    assert_eq!(settings["height"], 64);
    assert_eq!(settings["backend"], "Headless");
    assert_eq!(settings["color_target_format"], "Rgba8UnormSrgb");
    assert_eq!(
        screenshot_color_management()["output_encoding"],
        "srgb8-after-aces"
    );
    assert_eq!(
        screenshot_tolerance_metadata()["policy"],
        "native-rendered-output-smoke"
    );
}

#[test]
fn m9_adapter_metadata_records_actual_gpu_identity_when_available() {
    let report = GpuAdapterReport {
        name: "test adapter".to_string(),
        backend: "Vulkan".to_string(),
        device_type: "DiscreteGpu".to_string(),
        vendor: 0x10de,
        device: 0x1234,
        driver: "test-driver".to_string(),
        driver_info: "test-driver-info".to_string(),
        features: "TEXTURE_COMPRESSION_BC".to_string(),
        limits: AdapterLimitsReport {
            max_texture_dimension_2d: 8192,
            max_bind_groups: 4,
            max_uniform_buffer_binding_size: 65536,
            max_vertex_attributes: 16,
        },
    };

    let metadata = adapter_metadata(Some(&report));
    assert_eq!(metadata["name"], "test adapter");
    assert_eq!(metadata["backend"], "Vulkan");
    assert_eq!(metadata["limits"]["max_texture_dimension_2d"], 8192);
    assert_eq!(adapter_metadata(None)["available"], false);
}

#[test]
fn m9_capability_matrix_artifact_covers_required_lanes() {
    fs::create_dir_all(platform_dir()).expect("platform artifact dir");
    let measured_current_lane = render_default_scene_platform(32, 24);
    let measured_headless_cpu = render_default_scene_headless_cpu(32, 24);
    let matrix = serde_json::json!({
        "schema": "scena.capabilities.v1",
        "status": "incomplete",
        "status_reason": "current runner records a measured lane row; public release requires measured adapter artifacts from every required lane",
        "commit": current_commit_label(),
        "commit_sha": current_commit_label(),
        "timestamp_unix_seconds": current_timestamp_unix_seconds(),
        "test_names": [
            "m9_capability_matrix_artifact_covers_required_lanes"
        ],
        "artifact_paths": [
            path_string(&platform_dir().join("m9-capability-matrix.json"))
        ],
        "lanes": [
            capability_matrix_row("linux-native-vulkan", &measured_current_lane, &measured_headless_cpu),
            capability_matrix_row("linux-webgl2-chromium", &measured_current_lane, &measured_headless_cpu),
            capability_matrix_row("linux-webgpu-chromium", &measured_current_lane, &measured_headless_cpu),
            capability_matrix_row("macos-metal", &measured_current_lane, &measured_headless_cpu),
            capability_matrix_row("windows-dx12", &measured_current_lane, &measured_headless_cpu),
            capability_matrix_row("wasm32-unknown-unknown", &measured_current_lane, &measured_headless_cpu),
            capability_matrix_row(HEADLESS_CPU_LANE, &measured_current_lane, &measured_headless_cpu),
        ],
    });
    let lanes = matrix["lanes"].as_array().expect("lanes array");
    for lane in [
        "linux-native-vulkan",
        "linux-webgl2-chromium",
        "linux-webgpu-chromium",
        "macos-metal",
        "windows-dx12",
        "wasm32-unknown-unknown",
        HEADLESS_CPU_LANE,
    ] {
        assert!(
            lanes.iter().any(|entry| entry["lane"] == lane),
            "missing capability lane {lane}"
        );
    }
    let forbidden_factory_source = ["factory", "contract"].join("-");
    assert!(
        lanes
            .iter()
            .all(|entry| entry["measurement_source"] != forbidden_factory_source),
        "capability matrix must not synthesize non-current platform capabilities from factory constants"
    );
    let current_row = lanes
        .iter()
        .find(|entry| entry["lane"] == current_lane())
        .expect("current native lane row exists");
    assert_eq!(current_row["measurement_source"], "lane-renderer-runtime");
    assert!(
        current_row.get("adapter").is_some(),
        "measured lane rows must include adapter metadata, even when no adapter is available"
    );
    write_json(&platform_dir().join("m9-capability-matrix.json"), &matrix);
}

#[test]
fn m9_surface_context_loss_artifact_records_required_sequence() {
    let lane = current_lane();
    let artifact_dir = lane_dir();
    fs::create_dir_all(&artifact_dir).expect("artifact dir");

    let (mut scene, camera) = scene_with_triangle();
    let mut renderer = Renderer::headless(32, 32).expect("headless renderer builds");
    renderer.prepare(&mut scene).expect("initial prepare");
    renderer.render(&scene, camera).expect("initial render");
    renderer
        .handle_surface_event(SurfaceEvent::Resize {
            width: 48,
            height: 32,
        })
        .expect("resize accepted");
    let target_changed = matches!(
        renderer.render(&scene, camera),
        Err(RenderError::NotPrepared {
            reason: NotPreparedReason::TargetChanged { .. }
        })
    );
    renderer.prepare(&mut scene).expect("resize prepare");
    renderer.render(&scene, camera).expect("resize render");
    renderer
        .handle_surface_event(SurfaceEvent::Lost)
        .expect("surface lost accepted");
    let surface_lost = matches!(
        renderer.render(&scene, camera),
        Err(RenderError::SurfaceLost { recoverable: true })
    );

    let artifact = serde_json::json!({
        "schema": "scena.m9.surface_context_loss.v1",
        "lane": lane,
        "backend": "Headless",
        "event_sequence": [
            "prepare",
            "render",
            "resize",
            "not-prepared-target-changed",
            "reprepare-after-resize",
            "render-after-resize",
            "surface-lost"
        ],
        "target_changed_requires_prepare": target_changed,
        "surface_lost_is_structured": surface_lost,
        "final_prepare": "ok",
        "diagnostics": [],
    });
    assert!(target_changed, "resize requires explicit prepare");
    assert!(surface_lost, "surface loss is structured");
    write_json(&artifact_dir.join("surface-context-loss.json"), &artifact);
}

#[test]
fn m9_asset_provenance_records_source_path_and_hash() {
    let provenance = asset_provenance(STATIC_GLTF_PROOF_FIXTURE);

    assert_eq!(provenance["path"], STATIC_GLTF_PROOF_FIXTURE);
    assert!(
        provenance["hash"]
            .as_str()
            .is_some_and(|hash| hash.starts_with("fnv1a64:")),
        "asset provenance must include a stable source hash"
    );
}

#[test]
fn m9_static_gltf_proof_uses_non_ndc_camera_framed_asset() {
    let fixture = std::fs::read_to_string(root().join(STATIC_GLTF_PROOF_FIXTURE))
        .expect("static glTF proof fixture is readable");

    assert!(
        fixture.contains("\"min\": [2.0, -0.5, 0.0]")
            && fixture.contains("\"max\": [3.0, 0.5, 0.0]"),
        "M9 static glTF proof must use a camera-framed source asset outside raw NDC coordinates",
    );
}

fn render_default_scene_platform(width: u32, height: u32) -> RenderedArtifact {
    let (mut scene, camera) = scene_with_triangle();
    render_scene_platform(width, height, &mut scene, None, camera)
}

fn render_default_scene_headless_cpu(width: u32, height: u32) -> RenderedArtifact {
    let (mut scene, camera) = scene_with_triangle();
    render_scene_headless_cpu(width, height, &mut scene, None, camera)
}

fn render_static_gltf_platform(width: u32, height: u32) -> RenderedArtifact {
    let assets = Assets::new();
    let scene_asset = pollster::block_on(assets.load_scene(STATIC_GLTF_PROOF_FIXTURE))
        .expect("static glTF fixture loads");
    let mut scene = Scene::new();
    let import = scene
        .instantiate(&scene_asset)
        .expect("static glTF instantiates");
    let camera = scene.add_default_camera().expect("camera inserts");
    if let Some(bounds) = import.bounds_world(&scene) {
        scene.frame(camera, bounds).expect("camera frames glTF");
    }
    render_scene_platform(width, height, &mut scene, Some(&assets), camera)
}

fn render_static_gltf_headless_cpu(width: u32, height: u32) -> RenderedArtifact {
    let assets = Assets::new();
    let scene_asset = pollster::block_on(assets.load_scene(STATIC_GLTF_PROOF_FIXTURE))
        .expect("static glTF fixture loads");
    let mut scene = Scene::new();
    let import = scene
        .instantiate(&scene_asset)
        .expect("static glTF instantiates");
    let camera = scene.add_default_camera().expect("camera inserts");
    if let Some(bounds) = import.bounds_world(&scene) {
        scene.frame(camera, bounds).expect("camera frames glTF");
    }
    render_scene_headless_cpu(width, height, &mut scene, Some(&assets), camera)
}

fn render_pbr_light_suite_platform(width: u32, height: u32) -> Vec<PbrLightProof> {
    [
        PbrLightKind::DirectionalRed,
        PbrLightKind::PointGreen,
        PbrLightKind::SpotBlue,
    ]
    .into_iter()
    .map(|kind| {
        let (mut scene, assets, camera) = pbr_light_scene(kind);
        let artifact = render_scene_platform(width, height, &mut scene, Some(&assets), camera);
        let center = sample_rgb(&artifact.frame, width, height, width / 2, height / 2);
        let color_assertion_passed = kind.assert_expected_tint(center);
        assert!(
            artifact.nonblack_pixels > 0,
            "PBR {kind:?} proof should render visible pixels"
        );
        assert!(
            color_assertion_passed,
            "PBR {kind:?} proof should tint the center pixel as expected; center={center:?}"
        );
        PbrLightProof {
            kind,
            center,
            color_assertion_passed,
            ppm_path: lane_dir().join(kind.ppm_filename()),
            artifact,
        }
    })
    .collect()
}

fn render_pbr_light_suite_headless_cpu(width: u32, height: u32) -> Vec<PbrLightProof> {
    [
        PbrLightKind::DirectionalRed,
        PbrLightKind::PointGreen,
        PbrLightKind::SpotBlue,
    ]
    .into_iter()
    .map(|kind| {
        let (mut scene, assets, camera) = pbr_light_scene(kind);
        let artifact = render_scene_headless_cpu(width, height, &mut scene, Some(&assets), camera);
        let center = sample_rgb(&artifact.frame, width, height, width / 2, height / 2);
        let color_assertion_passed = kind.assert_expected_tint(center);
        let ppm_path = headless_cpu_dir().join(kind.ppm_filename());
        write_ppm(&ppm_path, artifact.width, artifact.height, &artifact.frame);
        PbrLightProof {
            kind,
            center,
            color_assertion_passed,
            ppm_path,
            artifact,
        }
    })
    .collect()
}

fn pbr_light_scene(kind: PbrLightKind) -> (Scene, Assets, scena::CameraKey) {
    let assets = Assets::new();
    let geometry = assets.create_geometry(GeometryDesc::box_xyz(0.65, 0.65, 0.05));
    let material = assets.create_material(
        MaterialDesc::pbr_metallic_roughness(Color::from_linear_rgb(0.25, 0.25, 0.25), 0.0, 0.8)
            .with_double_sided(true),
    );
    let mut scene = Scene::new();
    scene
        .mesh(geometry, material)
        .add()
        .expect("PBR mesh inserts");
    match kind {
        PbrLightKind::DirectionalRed => {
            scene
                .directional_light(
                    DirectionalLight::default()
                        .with_color(Color::from_linear_rgb(1.0, 0.0, 0.0))
                        .with_illuminance_lux(12_000.0),
                )
                .add()
                .expect("directional light inserts");
        }
        PbrLightKind::PointGreen => {
            scene
                .point_light(
                    PointLight::default()
                        .with_color(Color::from_linear_rgb(0.0, 1.0, 0.0))
                        .with_intensity_candela(900.0)
                        .with_range(5.0),
                )
                .transform(Transform::at(Vec3::new(0.0, 0.0, 1.0)))
                .add()
                .expect("point light inserts");
        }
        PbrLightKind::SpotBlue => {
            scene
                .spot_light(
                    SpotLight::default()
                        .with_color(Color::from_linear_rgb(0.0, 0.0, 1.0))
                        .with_intensity_candela(1_000.0)
                        .with_range(5.0)
                        .with_inner_cone_angle(Angle::from_degrees(20.0))
                        .with_outer_cone_angle(Angle::from_degrees(35.0)),
                )
                .transform(Transform::at(Vec3::new(0.0, 0.0, 1.0)))
                .add()
                .expect("spot light inserts");
        }
    }
    let camera = scene.add_default_camera().expect("camera inserts");
    (scene, assets, camera)
}

fn render_scene_platform(
    width: u32,
    height: u32,
    scene: &mut Scene,
    assets: Option<&Assets>,
    camera: scena::CameraKey,
) -> RenderedArtifact {
    let mut host_gpu_available = true;
    let mut host_gpu_error = None;
    let mut renderer = match Renderer::headless_gpu(width, height) {
        Ok(renderer) => renderer,
        Err(error) => {
            host_gpu_available = false;
            host_gpu_error = Some(format!("{error:?}"));
            Renderer::headless(width, height).expect("headless fallback renderer builds")
        }
    };
    if let Some(assets) = assets {
        renderer
            .prepare_with_assets(scene, assets)
            .expect("asset scene prepares");
    } else {
        renderer.prepare(scene).expect("scene prepares");
    }
    let outcome = renderer.render(scene, camera).expect("scene renders");
    let frame = renderer.frame_rgba8().to_vec();
    let nonblack_pixels = nonblack_pixels(&frame);
    let adapter = renderer.gpu_adapter_report();
    RenderedArtifact {
        width,
        height,
        frame,
        nonblack_pixels,
        draw_calls: outcome.draw_calls,
        capabilities: *renderer.capabilities(),
        host_gpu_available,
        host_gpu_error,
        adapter,
    }
}

fn render_scene_headless_cpu(
    width: u32,
    height: u32,
    scene: &mut Scene,
    assets: Option<&Assets>,
    camera: scena::CameraKey,
) -> RenderedArtifact {
    let mut renderer = Renderer::headless(width, height).expect("headless renderer builds");
    if let Some(assets) = assets {
        renderer
            .prepare_with_assets(scene, assets)
            .expect("asset scene prepares");
    } else {
        renderer.prepare(scene).expect("scene prepares");
    }
    let outcome = renderer.render(scene, camera).expect("scene renders");
    let frame = renderer.frame_rgba8().to_vec();
    let nonblack_pixels = nonblack_pixels(&frame);
    RenderedArtifact {
        width,
        height,
        frame,
        nonblack_pixels,
        draw_calls: outcome.draw_calls,
        capabilities: *renderer.capabilities(),
        host_gpu_available: false,
        host_gpu_error: None,
        adapter: None,
    }
}

fn write_headless_cpu_lane_artifacts() {
    let artifact_dir = headless_cpu_dir();
    fs::create_dir_all(&artifact_dir).expect("headless CPU artifact dir");

    let default = render_default_scene_headless_cpu(96, 64);
    let default_ppm = artifact_dir.join("default-scene.ppm");
    write_ppm(&default_ppm, default.width, default.height, &default.frame);
    assert!(
        default.nonblack_pixels > 0,
        "headless CPU default scene renders nonblack pixels"
    );

    let static_gltf = render_static_gltf_headless_cpu(96, 64);
    let static_gltf_ppm = artifact_dir.join("static-gltf.ppm");
    write_ppm(
        &static_gltf_ppm,
        static_gltf.width,
        static_gltf.height,
        &static_gltf.frame,
    );
    assert!(
        static_gltf.nonblack_pixels > 0,
        "headless CPU static glTF fixture renders nonblack pixels"
    );

    let capabilities = capability_json(HEADLESS_CPU_LANE, &static_gltf);
    let capability_path = artifact_dir.join("capabilities.json");
    write_json(&capability_path, &capabilities);

    let headless_cpu_production_claim = true;
    let proof = serde_json::json!({
        "schema": "scena.m9.platform_render.v1",
        "lane": HEADLESS_CPU_LANE,
        "os": std::env::consts::OS,
        "backend": "Headless",
        "headless_cpu_proof": true,
        "gpu_proof": false,
        "fallback_policy": "headless CPU is a separate software proof lane and never satisfies native GPU claims",
        "commit": current_commit_label(),
        "commit_sha": current_commit_label(),
        "timestamp_unix_seconds": current_timestamp_unix_seconds(),
        "test_names": [
            "m9_platform_rendered_output_suite_writes_release_artifacts"
        ],
        "artifact_paths": [
            path_string(&default_ppm),
            path_string(&static_gltf_ppm),
            path_string(&capability_path),
            path_string(&artifact_dir.join("rendered-output.json"))
        ],
        "default_scene": {
            "proof_class": "headless-cpu-harness-smoke",
            "production_claim": false,
            "backend": "Headless",
            "adapter": adapter_metadata(None),
            "renderer_settings": screenshot_renderer_settings(&default),
            "color_management": screenshot_color_management(),
            "tolerance": screenshot_tolerance_metadata(),
            "screenshot": path_string(&default_ppm),
            "width": default.width,
            "height": default.height,
            "draw_calls": default.draw_calls,
            "nonblack_pixels": default.nonblack_pixels,
        },
        "static_gltf": {
            "source": STATIC_GLTF_PROOF_FIXTURE,
            "proof_class": "cpu-camera-framed-non-ndc",
            "production_claim": headless_cpu_production_claim,
            "backend": "Headless",
            "adapter": adapter_metadata(None),
            "asset_provenance": asset_provenance(STATIC_GLTF_PROOF_FIXTURE),
            "renderer_settings": screenshot_renderer_settings(&static_gltf),
            "color_management": screenshot_color_management(),
            "tolerance": screenshot_tolerance_metadata(),
            "screenshot": path_string(&static_gltf_ppm),
            "width": static_gltf.width,
            "height": static_gltf.height,
            "draw_calls": static_gltf.draw_calls,
            "nonblack_pixels": static_gltf.nonblack_pixels,
        },
        "pbr_lights": {
            "proof_class": "headless-cpu-pbr-punctual-light",
            "production_claim": headless_cpu_production_claim,
            "gpu_proof": false,
            "lights": render_pbr_light_suite_headless_cpu(96, 64)
                .iter()
                .map(PbrLightProof::to_json)
                .collect::<Vec<_>>(),
        },
        "capabilities": path_string(&capability_path),
    });
    write_json(&artifact_dir.join("rendered-output.json"), &proof);
}

fn production_claim_for_gpu(artifact: &RenderedArtifact) -> bool {
    artifact.host_gpu_available
        && matches!(
            artifact.capabilities.backend,
            Backend::HeadlessGpu | Backend::NativeSurface
        )
}

fn static_gltf_proof_class(gpu_proof: bool) -> &'static str {
    if gpu_proof {
        "camera-framed-non-ndc"
    } else {
        "cpu-fallback-camera-framed-non-ndc"
    }
}

fn scene_with_triangle() -> (Scene, scena::CameraKey) {
    let mut scene = Scene::new();
    let camera = scene
        .add_perspective_camera(
            scene.root(),
            PerspectiveCamera::default(),
            Transform::at(Vec3::new(0.0, 0.0, CAMERA_DISTANCE_FOR_NDC_FIXTURES)),
        )
        .expect("camera inserts");
    scene.set_active_camera(camera).expect("active camera");
    scene
        .add_renderable(
            scene.root(),
            vec![Primitive::unlit_triangle()],
            Transform::default(),
        )
        .expect("triangle inserts");
    (scene, camera)
}

fn write_benchmark_artifact(lane: &str) {
    let mut rows = vec![
        benchmark_static_viewer(),
        benchmark_standard_model_viewer_gltf(),
        benchmark_larger_industrial_gltf(),
        benchmark_high_instance_scene(),
        benchmark_idle_render_on_change(),
        benchmark_headless_4k(),
    ];
    let baseline = benchmark_baseline();
    let baseline_comparison = apply_benchmark_baselines(&mut rows, &baseline);
    let artifact = serde_json::json!({
        "schema": "scena.m9.benchmarks.v1",
        "lane": lane,
        "regression_threshold_percent": 5.0,
        "baseline_comparison": baseline_comparison,
        "rows": rows,
    });
    write_json(&platform_dir().join("m9-benchmarks.json"), &artifact);
}

fn write_dedicated_4k_benchmark_artifact() -> serde_json::Value {
    let mut rows = vec![benchmark_headless_4k_measured(DEDICATED_4K_SAMPLE_COUNT)];
    let baseline = benchmark_baseline();
    let baseline_comparison = apply_benchmark_baselines(&mut rows, &baseline);
    let artifact = serde_json::json!({
        "schema": "scena.m9.benchmarks.v1",
        "lane": "headless-4k-performance",
        "regression_threshold_percent": 5.0,
        "baseline_comparison": baseline_comparison,
        "rows": rows,
    });
    fs::create_dir_all(platform_dir()).expect("platform artifact dir for headless-4k");
    write_json(&platform_dir().join("m9-benchmarks-4k.json"), &artifact);
    artifact
}

fn benchmark_baseline() -> serde_json::Value {
    let text = fs::read_to_string(root().join(BENCHMARK_BASELINE_PATH))
        .expect("benchmark baseline file is readable");
    serde_json::from_str(&text).expect("benchmark baseline file is valid JSON")
}

fn apply_benchmark_baselines(
    rows: &mut [serde_json::Value],
    baseline: &serde_json::Value,
) -> serde_json::Value {
    let mut status = "passed";
    let minimum_sample_count = baseline
        .get("minimum_sample_count")
        .and_then(serde_json::Value::as_u64)
        .unwrap_or(BENCHMARK_SAMPLE_COUNT as u64);

    for row in rows {
        if row.get("status").and_then(serde_json::Value::as_str)
            == Some("deferred-to-dedicated-performance-lane")
        {
            row["baseline_comparison"] = serde_json::json!({
                "status": "deferred",
                "reason": "dedicated performance lane required before this row becomes a release blocker",
            });
            continue;
        }

        let Some(row_baseline) = benchmark_baseline_for_row(row, baseline) else {
            status = "failed";
            row["baseline_comparison"] = serde_json::json!({
                "status": "failed",
                "reason": "missing stored baseline row",
            });
            continue;
        };

        let p95_frame_ms = row
            .get("p95_frame_ms")
            .and_then(serde_json::Value::as_f64)
            .unwrap_or(f64::INFINITY);
        let baseline_p95_frame_ms = row_baseline
            .get("p95_frame_ms")
            .and_then(serde_json::Value::as_f64)
            .unwrap_or(0.0);
        let allowed_regression_percent = row_baseline
            .get("allowed_regression_percent")
            .and_then(serde_json::Value::as_f64)
            .unwrap_or(5.0);
        let row_minimum_sample_count = row_baseline
            .get("minimum_sample_count")
            .and_then(serde_json::Value::as_u64)
            .unwrap_or(minimum_sample_count);
        let sample_count = row
            .get("sample_count")
            .and_then(serde_json::Value::as_u64)
            .unwrap_or(0);
        let allowed_p95 = baseline_p95_frame_ms * (1.0 + allowed_regression_percent / 100.0);
        let regression_percent = if baseline_p95_frame_ms > 0.0 {
            ((p95_frame_ms - baseline_p95_frame_ms) / baseline_p95_frame_ms) * 100.0
        } else {
            f64::INFINITY
        };
        let row_status = if sample_count >= row_minimum_sample_count && p95_frame_ms <= allowed_p95
        {
            "passed"
        } else {
            status = "failed";
            "failed"
        };

        row["baseline_comparison"] = serde_json::json!({
            "status": row_status,
            "baseline_p95_frame_ms": baseline_p95_frame_ms,
            "allowed_regression_percent": allowed_regression_percent,
            "allowed_p95_frame_ms": allowed_p95,
            "regression_percent": regression_percent,
            "minimum_sample_count": row_minimum_sample_count,
        });
    }

    serde_json::json!({
        "status": status,
        "baseline_path": BENCHMARK_BASELINE_PATH,
        "baseline_sha256": asset_source_hash(BENCHMARK_BASELINE_PATH),
        "metric": "p95_frame_ms",
        "minimum_sample_count": minimum_sample_count,
    })
}

fn benchmark_baseline_for_row<'a>(
    row: &serde_json::Value,
    baseline: &'a serde_json::Value,
) -> Option<&'a serde_json::Value> {
    let scene = row.get("scene").and_then(serde_json::Value::as_str)?;
    let backend = row.get("backend").and_then(serde_json::Value::as_str)?;
    baseline
        .get("rows")
        .and_then(serde_json::Value::as_array)?
        .iter()
        .find(|candidate| {
            candidate.get("scene").and_then(serde_json::Value::as_str) == Some(scene)
                && candidate.get("backend").and_then(serde_json::Value::as_str) == Some(backend)
        })
}

fn benchmark_static_viewer() -> serde_json::Value {
    let (mut scene, camera) = scene_with_triangle();
    benchmark_scene(
        "static-viewer",
        128,
        128,
        "builtin:unlit-triangle",
        &mut scene,
        None,
        camera,
    )
}

fn benchmark_standard_model_viewer_gltf() -> serde_json::Value {
    let assets = Assets::new();
    let scene_asset =
        pollster::block_on(assets.load_scene(STATIC_GLTF_PROOF_FIXTURE)).expect("mesh glTF loads");
    let mut scene = Scene::new();
    let import = scene
        .instantiate(&scene_asset)
        .expect("mesh glTF instantiates");
    let camera = scene.add_default_camera().expect("camera inserts");
    if let Some(bounds) = import.bounds_world(&scene) {
        scene
            .frame(camera, bounds)
            .expect("camera frames benchmark mesh glTF");
    }
    benchmark_scene(
        "standard-model-viewer-gltf",
        128,
        128,
        STATIC_GLTF_PROOF_FIXTURE,
        &mut scene,
        Some(&assets),
        camera,
    )
}

fn benchmark_larger_industrial_gltf() -> serde_json::Value {
    let assets = Assets::new();
    let scene_asset =
        pollster::block_on(assets.load_scene("tests/assets/gltf/khronos/BrainStem/BrainStem.gltf"))
            .expect("BrainStem glTF loads");
    let mut scene = Scene::new();
    let import = scene
        .instantiate(&scene_asset)
        .expect("BrainStem instantiates");
    let camera = scene.add_default_camera().expect("camera inserts");
    if let Some(bounds) = import.bounds_world(&scene) {
        scene
            .frame(camera, bounds)
            .expect("camera frames BrainStem");
    }
    benchmark_scene(
        "larger-industrial-gltf",
        128,
        128,
        "tests/assets/gltf/khronos/BrainStem/BrainStem.gltf",
        &mut scene,
        Some(&assets),
        camera,
    )
}

fn benchmark_high_instance_scene() -> serde_json::Value {
    let assets = Assets::new();
    let geometry = assets.create_geometry(GeometryDesc::box_xyz(0.1, 0.1, 0.1));
    let material = assets.create_material(MaterialDesc::unlit(Color::from_srgb_u8(80, 190, 140)));
    let mut scene = Scene::new();
    let set = scene
        .add_instance_set(scene.root(), geometry, material, Transform::default())
        .expect("instance set inserts");
    scene
        .reserve_instances(set, 128)
        .expect("reserve instances");
    for index in 0..128 {
        let x = index % 16;
        let y = index / 16;
        scene
            .push_instance(
                set,
                Transform::at(Vec3::new(x as f32 * 0.13 - 1.0, y as f32 * 0.13 - 0.5, 0.0)),
            )
            .expect("instance inserts");
    }
    let camera = scene.add_default_camera().expect("camera inserts");
    benchmark_scene(
        "high-instance",
        128,
        128,
        "generated:128-box-instances",
        &mut scene,
        Some(&assets),
        camera,
    )
}

fn benchmark_idle_render_on_change() -> serde_json::Value {
    let (mut scene, camera) = scene_with_triangle();
    let mut renderer = Renderer::headless_with_options(
        64,
        64,
        RendererOptions::default().with_render_mode(scena::RenderMode::OnChange),
    )
    .expect("renderer builds");
    renderer.prepare(&mut scene).expect("scene prepares");
    renderer.render(&scene, camera).expect("warm render");
    let mut samples = Vec::with_capacity(BENCHMARK_SAMPLE_COUNT);
    let mut outcome = None;
    for _ in 0..BENCHMARK_SAMPLE_COUNT {
        let start = Instant::now();
        let next = renderer.render(&scene, camera).expect("idle render skips");
        samples.push(start.elapsed().as_secs_f64() * 1000.0);
        outcome = Some(next);
    }
    let outcome = outcome.expect("benchmark loop records an outcome");
    benchmark_row(BenchmarkRowInput {
        scene: "idle",
        backend: renderer.capabilities().backend,
        samples: &samples,
        draw_calls: outcome.draw_calls,
        skipped: outcome.skipped,
        fixture: BenchmarkFixture {
            width: 64,
            height: 64,
            source: "builtin:unlit-triangle-on-change",
            sample_count_policy: "100 timed idle render calls after one warm render",
        },
        prepare_ms: 0.0,
        warmup_frame_ms: None,
    })
}

fn benchmark_headless_4k() -> serde_json::Value {
    serde_json::json!({
        "scene": "headless-4k",
        "backend": "Headless",
        "status": "deferred-to-dedicated-performance-lane",
        "sample_count": 0,
        "fixture": {
            "source": "builtin:unlit-triangle",
            "width": 3840,
            "height": 2160,
            "sample_count_policy": "not measured in cargo test; requires dedicated 4K performance lane with 100+ timed render samples",
        },
        "regression_threshold_percent": 5.0,
    })
}

fn benchmark_headless_4k_measured(sample_count: usize) -> serde_json::Value {
    let (mut scene, camera) = scene_with_triangle();
    benchmark_scene_with_sample_count(
        BenchmarkSceneInput {
            name: "headless-4k",
            width: 3840,
            height: 2160,
            fixture_source: "builtin:unlit-triangle",
            sample_count,
            sample_count_policy: "dedicated performance lane with 100 timed render calls after one warm render",
        },
        &mut scene,
        None,
        camera,
    )
}

#[test]
fn m9_benchmark_rows_use_distribution_not_single_sample() {
    let (mut scene, camera) = scene_with_triangle();
    let row = benchmark_scene(
        "benchmark-contract",
        64,
        64,
        "builtin:unlit-triangle",
        &mut scene,
        None,
        camera,
    );

    assert_eq!(row["sample_count"], 100);
    assert!(
        row["p50_frame_ms"].as_f64().is_some(),
        "benchmark row records p50"
    );
    assert!(
        row["p95_frame_ms"].as_f64().is_some(),
        "benchmark row records p95"
    );
    assert!(
        row["min_frame_ms"].as_f64().is_some(),
        "benchmark row records minimum"
    );
    assert!(
        row["max_frame_ms"].as_f64().is_some(),
        "benchmark row records maximum"
    );
    assert!(
        row["stddev_frame_ms"].as_f64().is_some(),
        "benchmark row records standard deviation"
    );
    assert_eq!(row["fixture"]["width"], 64);
    assert_eq!(row["fixture"]["height"], 64);
}

#[test]
fn m9_benchmark_rows_record_stored_baseline_comparison() {
    let mut rows = vec![
        serde_json::json!({
            "scene": "static-viewer",
            "backend": "Headless",
            "sample_count": 100,
            "p95_frame_ms": 10.0,
        }),
        serde_json::json!({
            "scene": "headless-4k",
            "status": "deferred-to-dedicated-performance-lane",
            "sample_count": 0,
        }),
    ];
    let baseline = serde_json::json!({
        "minimum_sample_count": 100,
        "rows": [
            {
                "scene": "static-viewer",
                "backend": "Headless",
                "p95_frame_ms": 12.0,
                "allowed_regression_percent": 5.0
            }
        ]
    });

    let summary = apply_benchmark_baselines(&mut rows, &baseline);

    assert_eq!(summary["status"], "passed");
    assert_eq!(summary["baseline_path"], BENCHMARK_BASELINE_PATH);
    assert_eq!(summary["metric"], "p95_frame_ms");
    assert_eq!(rows[0]["baseline_comparison"]["status"], "passed");
    assert_eq!(
        rows[1]["baseline_comparison"]["status"], "deferred",
        "dedicated-lane benchmark rows must be explicit deferrals, not silent misses"
    );
}

#[test]
fn m9_dedicated_headless_4k_benchmark_writes_release_blocker_artifact() {
    if std::env::var_os("SCENA_RUN_DEDICATED_4K_BENCHMARK").is_none() {
        fs::create_dir_all(platform_dir()).expect("platform artifact dir");
        let artifact_path = platform_dir().join("m9-benchmarks-4k-required.json");
        let artifact = serde_json::json!({
            "schema": "scena.m9.benchmark_4k_required.v1",
            "status": "fail-closed",
            "release_evidence": false,
            "reason": "SCENA_RUN_DEDICATED_4K_BENCHMARK is not set in the normal cargo-test lane",
            "run_hint": "Set SCENA_RUN_DEDICATED_4K_BENCHMARK=1 on the dedicated performance lane to write m9-benchmarks-4k.json.",
            "required_artifact": path_string(&platform_dir().join("m9-benchmarks-4k.json")),
        });
        write_json(&artifact_path, &artifact);
        assert!(
            artifact_path.is_file(),
            "normal suite must record fail-closed 4K benchmark requirement metadata"
        );
        return;
    }

    let artifact = write_dedicated_4k_benchmark_artifact();
    let rows = artifact["rows"].as_array().expect("benchmark rows");
    assert_eq!(rows.len(), 1);
    assert_eq!(rows[0]["scene"], "headless-4k");
    assert_eq!(rows[0]["sample_count"], DEDICATED_4K_SAMPLE_COUNT as u64);
    assert_ne!(
        rows[0]["status"].as_str(),
        Some("deferred-to-dedicated-performance-lane"),
        "dedicated 4K lane must produce a measured row, not the normal-suite deferral"
    );
    assert_eq!(
        artifact["baseline_comparison"]["baseline_path"],
        BENCHMARK_BASELINE_PATH
    );
    assert!(
        platform_dir().join("m9-benchmarks-4k.json").is_file(),
        "dedicated 4K benchmark artifact must be written for release-readiness"
    );
}

#[test]
fn m9_benchmark_baseline_comparison_fails_significant_regressions() {
    let mut rows = vec![serde_json::json!({
        "scene": "static-viewer",
        "backend": "Headless",
        "sample_count": 100,
        "p95_frame_ms": 12.0,
    })];
    let baseline = serde_json::json!({
        "minimum_sample_count": 100,
        "rows": [
            {
                "scene": "static-viewer",
                "backend": "Headless",
                "p95_frame_ms": 10.0,
                "allowed_regression_percent": 5.0
            }
        ]
    });

    let summary = apply_benchmark_baselines(&mut rows, &baseline);

    assert_eq!(summary["status"], "failed");
    assert_eq!(rows[0]["baseline_comparison"]["status"], "failed");
    assert_eq!(rows[0]["baseline_comparison"]["regression_percent"], 20.0);
}

fn benchmark_scene(
    name: &str,
    width: u32,
    height: u32,
    fixture_source: &str,
    scene: &mut Scene,
    assets: Option<&Assets>,
    camera: scena::CameraKey,
) -> serde_json::Value {
    benchmark_scene_with_sample_count(
        BenchmarkSceneInput {
            name,
            width,
            height,
            fixture_source,
            sample_count: BENCHMARK_SAMPLE_COUNT,
            sample_count_policy: "100 timed render calls after one warm render",
        },
        scene,
        assets,
        camera,
    )
}

struct BenchmarkSceneInput<'a> {
    name: &'a str,
    width: u32,
    height: u32,
    fixture_source: &'a str,
    sample_count: usize,
    sample_count_policy: &'a str,
}

fn benchmark_scene_with_sample_count(
    input: BenchmarkSceneInput<'_>,
    scene: &mut Scene,
    assets: Option<&Assets>,
    camera: scena::CameraKey,
) -> serde_json::Value {
    assert!(
        input.sample_count > 0,
        "benchmark sample count must be nonzero"
    );
    let mut renderer = Renderer::headless(input.width, input.height).expect("renderer builds");
    let start = Instant::now();
    if let Some(assets) = assets {
        renderer
            .prepare_with_assets(scene, assets)
            .expect("asset scene prepares");
    } else {
        renderer.prepare(scene).expect("scene prepares");
    }
    let prepare_ms = start.elapsed().as_secs_f64() * 1000.0;
    let start = Instant::now();
    let warmup = renderer.render(scene, camera).expect("warm scene render");
    let warmup_frame_ms = start.elapsed().as_secs_f64() * 1000.0;
    let mut samples = Vec::with_capacity(input.sample_count);
    let mut outcome = warmup;
    for _ in 0..input.sample_count {
        let start = Instant::now();
        outcome = renderer.render(scene, camera).expect("scene renders");
        samples.push(start.elapsed().as_secs_f64() * 1000.0);
    }
    benchmark_row(BenchmarkRowInput {
        scene: input.name,
        backend: renderer.capabilities().backend,
        samples: &samples,
        draw_calls: outcome.draw_calls,
        skipped: outcome.skipped,
        fixture: BenchmarkFixture {
            width: input.width,
            height: input.height,
            source: input.fixture_source,
            sample_count_policy: input.sample_count_policy,
        },
        prepare_ms,
        warmup_frame_ms: Some(warmup_frame_ms),
    })
}

struct BenchmarkFixture<'a> {
    width: u32,
    height: u32,
    source: &'a str,
    sample_count_policy: &'a str,
}

struct BenchmarkRowInput<'a> {
    scene: &'a str,
    backend: Backend,
    samples: &'a [f64],
    draw_calls: u64,
    skipped: bool,
    fixture: BenchmarkFixture<'a>,
    prepare_ms: f64,
    warmup_frame_ms: Option<f64>,
}

fn benchmark_row(input: BenchmarkRowInput<'_>) -> serde_json::Value {
    let distribution = benchmark_distribution(input.samples);
    serde_json::json!({
        "scene": input.scene,
        "backend": format!("{:?}", input.backend),
        "sample_count": distribution.sample_count,
        "median_frame_ms": distribution.p50_frame_ms,
        "p50_frame_ms": distribution.p50_frame_ms,
        "p95_frame_ms": distribution.p95_frame_ms,
        "min_frame_ms": distribution.min_frame_ms,
        "max_frame_ms": distribution.max_frame_ms,
        "stddev_frame_ms": distribution.stddev_frame_ms,
        "prepare_ms": input.prepare_ms,
        "warmup_frame_ms": input.warmup_frame_ms,
        "fixture": {
            "source": input.fixture.source,
            "source_hash": asset_source_hash_if_file(input.fixture.source),
            "width": input.fixture.width,
            "height": input.fixture.height,
            "sample_count_policy": input.fixture.sample_count_policy,
        },
        "draw_calls": input.draw_calls,
        "skipped": input.skipped,
        "regression_threshold_percent": 5.0,
    })
}

struct BenchmarkDistribution {
    sample_count: usize,
    min_frame_ms: f64,
    p50_frame_ms: f64,
    p95_frame_ms: f64,
    max_frame_ms: f64,
    stddev_frame_ms: f64,
}

fn benchmark_distribution(samples: &[f64]) -> BenchmarkDistribution {
    assert!(
        !samples.is_empty(),
        "benchmark distribution requires at least one sample"
    );
    let mut sorted = samples.to_vec();
    sorted.sort_by(f64::total_cmp);
    let sample_count = sorted.len();
    let min_frame_ms = sorted[0];
    let max_frame_ms = sorted[sample_count - 1];
    let p50_frame_ms = percentile_nearest_rank(&sorted, 0.50);
    let p95_frame_ms = percentile_nearest_rank(&sorted, 0.95);
    let mean = sorted.iter().sum::<f64>() / sample_count as f64;
    let variance = sorted
        .iter()
        .map(|sample| {
            let delta = sample - mean;
            delta * delta
        })
        .sum::<f64>()
        / sample_count as f64;
    BenchmarkDistribution {
        sample_count,
        min_frame_ms,
        p50_frame_ms,
        p95_frame_ms,
        max_frame_ms,
        stddev_frame_ms: variance.sqrt(),
    }
}

fn percentile_nearest_rank(sorted_samples: &[f64], percentile: f64) -> f64 {
    debug_assert!(!sorted_samples.is_empty());
    let rank = (sorted_samples.len() as f64 * percentile).ceil() as usize;
    let index = rank.saturating_sub(1).min(sorted_samples.len() - 1);
    sorted_samples[index]
}

fn capability_matrix_row(
    lane: &str,
    measured_current_lane: &RenderedArtifact,
    measured_headless_cpu: &RenderedArtifact,
) -> serde_json::Value {
    if lane == current_lane() {
        lane_capability_from_artifact(lane, measured_current_lane)
    } else if lane == HEADLESS_CPU_LANE {
        lane_capability_from_artifact(lane, measured_headless_cpu)
    } else {
        missing_lane_capability(lane)
    }
}

fn lane_capability_from_artifact(lane: &str, artifact: &RenderedArtifact) -> serde_json::Value {
    let mut row = lane_capability(lane, artifact.capabilities, "lane-renderer-runtime");
    row["status"] = serde_json::json!("measured");
    row["adapter"] = adapter_metadata(artifact.adapter.as_ref());
    row["host_gpu_available"] = serde_json::json!(artifact.host_gpu_available);
    row["host_gpu_error"] = serde_json::json!(artifact.host_gpu_error);
    row["commit"] = serde_json::json!(current_commit_label());
    row["commit_sha"] = serde_json::json!(current_commit_label());
    row["timestamp_unix_seconds"] = serde_json::json!(current_timestamp_unix_seconds());
    row
}

fn missing_lane_capability(lane: &str) -> serde_json::Value {
    serde_json::json!({
        "lane": lane,
        "status": "missing-measurement",
        "measurement_source": "missing-lane-artifact",
        "capabilities": serde_json::Value::Null,
        "adapter": { "available": false },
        "host_gpu_available": false,
        "host_gpu_error": "required lane must upload its own measured capabilities.json",
        "diagnostics": [
            "no factory capability constants are accepted as platform proof"
        ],
    })
}

fn lane_capability(
    lane: &str,
    capabilities: Capabilities,
    measurement_source: &str,
) -> serde_json::Value {
    serde_json::json!({
        "lane": lane,
        "measurement_source": measurement_source,
        "capabilities": capability_fields(capabilities),
        "diagnostics": capabilities
            .diagnostics()
            .into_iter()
            .map(|diagnostic| diagnostic.message)
            .collect::<Vec<_>>(),
    })
}

fn capability_json(lane: &str, artifact: &RenderedArtifact) -> serde_json::Value {
    let capabilities = artifact.capabilities;
    serde_json::json!({
        "schema": "scena.capabilities.v1",
        "lane": lane,
        "measurement_source": "lane-renderer-runtime",
        "commit": current_commit_label(),
        "commit_sha": current_commit_label(),
        "timestamp_unix_seconds": current_timestamp_unix_seconds(),
        "backend": format!("{:?}", capabilities.backend),
        "hardware_tier": format!("{:?}", capabilities.hardware_tier),
        "adapter": adapter_metadata(artifact.adapter.as_ref()),
        "features": capability_fields(capabilities),
        "diagnostics": capabilities
            .diagnostics()
            .into_iter()
            .map(|diagnostic| diagnostic.message)
            .collect::<Vec<_>>(),
    })
}

fn adapter_metadata(report: Option<&GpuAdapterReport>) -> serde_json::Value {
    let Some(report) = report else {
        return serde_json::json!({ "available": false });
    };
    serde_json::json!({
        "available": true,
        "name": report.name,
        "backend": report.backend,
        "device_type": report.device_type,
        "vendor": report.vendor,
        "device": report.device,
        "driver": report.driver,
        "driver_info": report.driver_info,
        "features": report.features,
        "limits": {
            "max_texture_dimension_2d": report.limits.max_texture_dimension_2d,
            "max_bind_groups": report.limits.max_bind_groups,
            "max_uniform_buffer_binding_size": report.limits.max_uniform_buffer_binding_size,
            "max_vertex_attributes": report.limits.max_vertex_attributes,
        },
    })
}

fn capability_fields(capabilities: Capabilities) -> serde_json::Value {
    serde_json::json!({
        "forward_pbr": { "state": format!("{:?}", capabilities.forward_pbr) },
        "directional_shadows": { "state": format!("{:?}", capabilities.directional_shadows) },
        "point_shadows": { "state": format!("{:?}", capabilities.point_shadows) },
        "spot_shadows": { "state": format!("{:?}", capabilities.spot_shadows) },
        "bloom": { "state": format!("{:?}", capabilities.bloom) },
        "screen_space_ambient_occlusion": { "state": format!("{:?}", capabilities.screen_space_ambient_occlusion) },
        "wide_gamut_output": { "state": format!("{:?}", capabilities.wide_gamut_output) },
        "texture_compression_basisu": { "state": format!("{:?}", capabilities.texture_compression_basisu) },
        "hardware_instancing": { "state": format!("{:?}", capabilities.hardware_instancing) },
        "texture_arrays": {
            "state": format!("{:?}", capabilities.texture_arrays),
            "max_layers": capabilities.max_texture_array_layers,
        },
        "fragment_high_precision": { "state": format!("{:?}", capabilities.fragment_high_precision) },
        "uniform_buffers": {
            "state": format!("{:?}", capabilities.uniform_buffers),
            "max_bytes": capabilities.uniform_buffer_max_bytes,
        },
        "clipping_planes": {
            "state": "Supported",
            "default": capabilities.default_clipping_planes,
            "max": capabilities.max_clipping_planes,
        },
        "gpu_frustum_culling": { "state": format!("{:?}", capabilities.gpu_frustum_culling) },
        "per_instance_culling": { "state": format!("{:?}", capabilities.per_instance_culling) },
        "compute_shaders": { "state": format!("{:?}", capabilities.compute_shaders) },
        "storage_buffers": { "state": format!("{:?}", capabilities.storage_buffers) },
        "reversed_z_depth": { "state": format!("{:?}", capabilities.reversed_z_depth) },
        "readback_headless_screenshots": { "state": format!("{:?}", capabilities.readback_headless_screenshots) },
    })
}

fn write_ppm(path: &Path, width: u32, height: u32, rgba: &[u8]) {
    let mut ppm = format!("P6\n{width} {height}\n255\n").into_bytes();
    for pixel in rgba.chunks_exact(4) {
        ppm.extend_from_slice(&pixel[0..3]);
    }
    fs::write(path, ppm).expect("ppm writes");
}

fn write_json(path: &Path, value: &serde_json::Value) {
    let body = serde_json::to_string_pretty(value).expect("json serializes");
    fs::write(path, format!("{body}\n")).expect("json writes");
}

fn nonblack_pixels(rgba: &[u8]) -> usize {
    rgba.chunks_exact(4)
        .filter(|pixel| pixel[0] != 0 || pixel[1] != 0 || pixel[2] != 0)
        .count()
}

fn sample_rgb(rgba: &[u8], width: u32, _height: u32, x: u32, y: u32) -> [u8; 3] {
    let index = ((y * width + x) * 4) as usize;
    [rgba[index], rgba[index + 1], rgba[index + 2]]
}

fn path_string(path: &Path) -> String {
    path.strip_prefix(root())
        .unwrap_or(path)
        .display()
        .to_string()
}

fn asset_provenance(relative_path: &str) -> serde_json::Value {
    serde_json::json!({
        "path": relative_path,
        "hash": asset_source_hash(relative_path),
    })
}

fn screenshot_renderer_settings(artifact: &RenderedArtifact) -> serde_json::Value {
    serde_json::json!({
        "width": artifact.width,
        "height": artifact.height,
        "backend": format!("{:?}", artifact.capabilities.backend),
        "color_target_format": artifact.capabilities.color_target_format,
        "output_stage": format!("{:?}", artifact.capabilities.output_stage),
        "alpha_pipeline": format!("{:?}", artifact.capabilities.alpha_pipeline),
        "readback_headless_screenshots": format!("{:?}", artifact.capabilities.readback_headless_screenshots),
    })
}

fn screenshot_color_management() -> serde_json::Value {
    serde_json::json!({
        "scene_input": "linear-scene-referred",
        "tone_mapper": "aces",
        "output_encoding": "srgb8-after-aces",
    })
}

fn screenshot_tolerance_metadata() -> serde_json::Value {
    serde_json::json!({
        "policy": "native-rendered-output-smoke",
        "max_abs_diff": 8,
        "mean_abs_diff": 2.0,
        "comparison_space": "srgb8",
    })
}

fn asset_source_hash_if_file(relative_path: &str) -> Option<String> {
    root()
        .join(relative_path)
        .is_file()
        .then(|| asset_source_hash(relative_path))
}

fn current_commit_label() -> String {
    std::env::var("GITHUB_SHA").unwrap_or_else(|_| "local-checkout".to_string())
}

fn current_timestamp_unix_seconds() -> u64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map(|duration| duration.as_secs())
        .unwrap_or(0)
}

fn asset_source_hash(relative_path: &str) -> String {
    let bytes = fs::read(root().join(relative_path)).expect("asset provenance source is readable");
    format!("fnv1a64:{:016x}", fnv1a64(&bytes))
}

fn fnv1a64(bytes: &[u8]) -> u64 {
    let mut hash = 0xcbf2_9ce4_8422_2325u64;
    for byte in bytes {
        hash ^= u64::from(*byte);
        hash = hash.wrapping_mul(0x0000_0100_0000_01b3);
    }
    hash
}

struct RenderedArtifact {
    width: u32,
    height: u32,
    frame: Vec<u8>,
    nonblack_pixels: usize,
    draw_calls: u64,
    capabilities: Capabilities,
    host_gpu_available: bool,
    host_gpu_error: Option<String>,
    adapter: Option<GpuAdapterReport>,
}

#[derive(Clone, Copy, Debug)]
enum PbrLightKind {
    DirectionalRed,
    PointGreen,
    SpotBlue,
}

impl PbrLightKind {
    const fn ppm_filename(self) -> &'static str {
        match self {
            Self::DirectionalRed => PBR_DIRECTIONAL_RED_PPM,
            Self::PointGreen => PBR_POINT_GREEN_PPM,
            Self::SpotBlue => PBR_SPOT_BLUE_PPM,
        }
    }

    const fn light_type(self) -> &'static str {
        match self {
            Self::DirectionalRed => "directional",
            Self::PointGreen => "point",
            Self::SpotBlue => "spot",
        }
    }

    const fn expected_channel(self) -> &'static str {
        match self {
            Self::DirectionalRed => "red",
            Self::PointGreen => "green",
            Self::SpotBlue => "blue",
        }
    }

    fn assert_expected_tint(self, rgb: [u8; 3]) -> bool {
        let r = rgb[0] as i16;
        let g = rgb[1] as i16;
        let b = rgb[2] as i16;
        match self {
            Self::DirectionalRed => r >= g + 8 && r >= b + 8,
            Self::PointGreen => g >= r + 8 && g >= b + 8,
            Self::SpotBlue => b >= r + 8 && b >= g + 8,
        }
    }
}

struct PbrLightProof {
    kind: PbrLightKind,
    center: [u8; 3],
    color_assertion_passed: bool,
    ppm_path: PathBuf,
    artifact: RenderedArtifact,
}

impl PbrLightProof {
    fn to_json(&self) -> serde_json::Value {
        serde_json::json!({
            "light_type": self.kind.light_type(),
            "expected_channel": self.kind.expected_channel(),
            "proof_class": "native-pbr-punctual-light",
            "production_claim": production_claim_for_gpu(&self.artifact) && self.color_assertion_passed,
            "gpu_proof": production_claim_for_gpu(&self.artifact) && self.color_assertion_passed,
            "backend": format!("{:?}", self.artifact.capabilities.backend),
            "host_gpu_available": self.artifact.host_gpu_available,
            "host_gpu_error": self.artifact.host_gpu_error,
            "adapter": adapter_metadata(self.artifact.adapter.as_ref()),
            "renderer_settings": screenshot_renderer_settings(&self.artifact),
            "color_management": screenshot_color_management(),
            "tolerance": screenshot_tolerance_metadata(),
            "screenshot": path_string(&self.ppm_path),
            "width": self.artifact.width,
            "height": self.artifact.height,
            "draw_calls": self.artifact.draw_calls,
            "nonblack_pixels": self.artifact.nonblack_pixels,
            "center_rgb": self.center,
            "color_assertion_passed": self.color_assertion_passed,
        })
    }
}
