// Downstream blackout recovery contracts.
//
// Scope: keep the eye-video stream observable when frames stop arriving or
// queues overflow.
// Targets: `server/src/video/eye_capture.rs` and `server/src/video/stream_core.rs`.
// Why: black-screen episodes should become measurable recovery events, not
// silent UI mysteries.

const SERVER_EYE_CAPTURE: &str = include_str!("../../../../server/src/video/eye_capture.rs");
const SERVER_STREAM_CORE: &str = include_str!("../../../../server/src/video/stream_core.rs");

#[test]
fn first_frame_and_midstream_blackouts_have_separate_watchdogs() {
    let first_frame = SERVER_EYE_CAPTURE
        .find("LESAVKA_EYE_FIRST_FRAME_TIMEOUT_MS")
        .expect("first-frame timeout marker");
    let midstream = SERVER_EYE_CAPTURE
        .find("eye_stall_warn_timeout()")
        .expect("midstream stall timeout marker");

    assert!(
        first_frame < midstream,
        "initial no-video failures should be reported before midstream stall monitoring starts"
    );
    for marker in [
        "capture produced no frames within",
        "downstream eye stream has produced no samples since the last frame",
        "last_sample_wall_ms",
        "first_sample_seen",
        "stall_watchdog_alive",
    ] {
        assert!(
            SERVER_EYE_CAPTURE.contains(marker),
            "blackout recovery should preserve marker {marker}"
        );
    }
}

#[test]
fn blackout_warning_defaults_are_bounded_below_ten_seconds() {
    for marker in [
        "unwrap_or(5_000)",
        "Duration::from_millis(millis.max(500))",
        "(millis > 0).then_some",
    ] {
        assert!(
            SERVER_STREAM_CORE.contains(marker),
            "stall warning timeout should preserve bounded marker {marker}"
        );
    }
}

#[test]
fn overflow_recovery_waits_for_idr_before_resuming_after_drops() {
    let full_branch = SERVER_EYE_CAPTURE
        .find("TrySendError::Full")
        .expect("overflow branch");
    let wait_for_idr = SERVER_EYE_CAPTURE
        .find("wait_for_idr.store(true")
        .expect("IDR recovery marker");
    let clear_idr = SERVER_EYE_CAPTURE
        .find("wait_for_idr.store(false")
        .expect("IDR clear marker");

    assert!(
        full_branch < wait_for_idr,
        "queue overflow should arm IDR recovery"
    );
    assert!(
        clear_idr < full_branch,
        "successful IDR sends should clear recovery before later overflow can re-arm it"
    );
}
