// Contract guardrails for uplink queue freshness budgets.
//
// Scope: source-level checks over client uplink queue constants.
// Targets: `client/src/app/uplink_media/`, `client/src/sync_probe/capture.rs`.
// Why: lip-sync quality depends on bounded queue age; accidental widening can
// create near-second video lag under load.

const UPLINK_MEDIA_QUEUE_SRC: &str = include_str!(concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/client/src/app/uplink_media/bundled_media_queue.rs"
));
const MEDIA_SOURCE_REQUIREMENTS_SRC: &str = include_str!(concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/client/src/app/uplink_media/media_source_requirements.rs"
));
const VOICE_LOOP_SRC: &str = include_str!(concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/client/src/app/uplink_media/voice_loop.rs"
));
const CAMERA_LOOP_SRC: &str = include_str!(concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/client/src/app/uplink_media/camera_loop.rs"
));
const SYNC_PROBE_CAPTURE_SRC: &str = include_str!(concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/client/src/sync_probe/capture.rs"
));

fn queue_block<'a>(src: &'a str, queue_const: &str) -> &'a str {
    let marker = format!("const {queue_const}:");
    let start = src
        .find(&marker)
        .unwrap_or_else(|| panic!("missing queue constant marker: {marker}"));
    let tail = &src[start..];
    let end = tail
        .find("};")
        .unwrap_or_else(|| panic!("missing queue terminator for {queue_const}"));
    &tail[..end]
}

fn parse_queue_capacity(block: &str, queue_const: &str) -> u64 {
    let marker = "capacity:";
    let start = block
        .find(marker)
        .unwrap_or_else(|| panic!("missing capacity for {queue_const}"));
    let tail = &block[start + marker.len()..];
    let value = tail.trim_start().split(',').next().unwrap_or("").trim();
    value
        .parse::<u64>()
        .unwrap_or_else(|_| panic!("invalid capacity value for {queue_const}: {value}"))
}

fn parse_queue_max_age_ms(block: &str, queue_const: &str) -> u64 {
    let millis_marker = "max_age: Duration::from_millis(";
    if let Some(start) = block.find(millis_marker) {
        let tail = &block[start + millis_marker.len()..];
        let value = tail.split(')').next().unwrap_or("").trim();
        return value
            .parse::<u64>()
            .unwrap_or_else(|_| panic!("invalid millis max_age for {queue_const}: {value}"));
    }

    let secs_marker = "max_age: Duration::from_secs(";
    if let Some(start) = block.find(secs_marker) {
        let tail = &block[start + secs_marker.len()..];
        let value = tail.split(')').next().unwrap_or("").trim();
        let seconds = value
            .parse::<u64>()
            .unwrap_or_else(|_| panic!("invalid seconds max_age for {queue_const}: {value}"));
        return seconds.saturating_mul(1_000);
    }

    panic!("missing max_age for {queue_const}");
}

fn assert_queue_policy(block: &str, queue_const: &str, policy: &str) {
    let expected = format!("policy: crate::uplink_fresh_queue::FreshQueuePolicy::{policy}");
    assert!(
        block.contains(&expected),
        "{queue_const} should use {policy} policy to preserve the intended live-media behavior"
    );
}

#[test]
fn camera_uplink_queue_freshness_budget_stays_within_lipsync_window() {
    let block = queue_block(UPLINK_MEDIA_QUEUE_SRC, "VIDEO_UPLINK_QUEUE");
    let max_age_ms = parse_queue_max_age_ms(block, "VIDEO_UPLINK_QUEUE");
    assert!(
        max_age_ms <= 350,
        "VIDEO_UPLINK_QUEUE max_age is {max_age_ms}ms; keep it <= 350ms to prevent ~1s video drift"
    );
    assert_queue_policy(block, "VIDEO_UPLINK_QUEUE", "LatestOnly");
}

#[test]
fn microphone_uplink_queue_freshness_budget_stays_within_live_audio_window() {
    let block = queue_block(UPLINK_MEDIA_QUEUE_SRC, "AUDIO_UPLINK_QUEUE");
    let max_age_ms = parse_queue_max_age_ms(block, "AUDIO_UPLINK_QUEUE");
    assert!(
        max_age_ms <= 400,
        "AUDIO_UPLINK_QUEUE max_age is {max_age_ms}ms; keep it <= 400ms for live calls"
    );
    assert_queue_policy(block, "AUDIO_UPLINK_QUEUE", "DrainOldest");
    let capacity = parse_queue_capacity(block, "AUDIO_UPLINK_QUEUE");
    assert!(
        capacity <= 64,
        "AUDIO_UPLINK_QUEUE capacity is {capacity}; keep audio continuity bounded"
    );
}

#[test]
fn camera_uplink_queue_capacity_remains_bounded() {
    let block = queue_block(UPLINK_MEDIA_QUEUE_SRC, "VIDEO_UPLINK_QUEUE");
    let capacity = parse_queue_capacity(block, "VIDEO_UPLINK_QUEUE");
    assert!(
        capacity <= 32,
        "VIDEO_UPLINK_QUEUE capacity is {capacity}; larger queues amplify tail-latency under stalls"
    );
}

#[test]
fn sync_probe_video_queue_uses_same_freshness_budget() {
    let block = queue_block(SYNC_PROBE_CAPTURE_SRC, "PROBE_VIDEO_QUEUE");
    let max_age_ms = parse_queue_max_age_ms(block, "PROBE_VIDEO_QUEUE");
    assert!(
        max_age_ms <= 350,
        "PROBE_VIDEO_QUEUE max_age is {max_age_ms}ms; keep probe and runtime freshness policies aligned"
    );
    assert_queue_policy(block, "PROBE_VIDEO_QUEUE", "LatestOnly");
}

#[test]
fn sync_probe_audio_queue_preserves_bounded_marker_continuity() {
    let block = queue_block(SYNC_PROBE_CAPTURE_SRC, "PROBE_AUDIO_QUEUE");
    let max_age_ms = parse_queue_max_age_ms(block, "PROBE_AUDIO_QUEUE");
    assert!(
        max_age_ms <= 400,
        "PROBE_AUDIO_QUEUE max_age is {max_age_ms}ms; keep probe audio continuity bounded"
    );
    assert_queue_policy(block, "PROBE_AUDIO_QUEUE", "DrainOldest");
}

#[test]
fn strict_explicit_media_source_failures_abort_the_headless_probe_client() {
    let source = [
        MEDIA_SOURCE_REQUIREMENTS_SRC,
        VOICE_LOOP_SRC,
        CAMERA_LOOP_SRC,
    ]
    .join("\n");
    for expected in [
        "LESAVKA_REQUIRE_EXPLICIT_MEDIA_SOURCES",
        "abort_if_required_media_source_failed",
        "required {kind} source '{source}' failed to start",
        "std::process::exit(2)",
        "abort_if_required_media_source_failed(\"microphone\"",
        "abort_if_required_media_source_failed(\"camera\"",
    ] {
        assert!(
            source.contains(expected),
            "required-source setup failures must be fatal in strict probe mode: missing {expected}"
        );
    }
}
