// Reliability contract for repeated audio epoch recovery.
//
// Scope: exercise repeated server-side audio recovery cycles without HID, UVC,
// GTK, GStreamer, or physical USB devices.
// Targets: `server/src/upstream_media_runtime.rs`.
// Why: the first-join audio fix should be safe to call during reconnect churn
// without causing heal loops, video resets, or calibration drift.

use lesavka_server::upstream_media_runtime::UpstreamMediaRuntime;

#[test]
fn repeated_audio_epoch_heals_do_not_reset_video_or_calibration() {
    let runtime = UpstreamMediaRuntime::new();
    runtime.set_playout_offsets(162_659, 5_000);
    let camera = runtime.activate_camera();
    let microphone = runtime.activate_microphone();
    let session_id = runtime.snapshot().session_id;

    for _ in 0..5 {
        runtime.soft_recover_microphone();
        assert!(runtime.is_camera_active(camera.generation));
        assert!(!runtime.is_microphone_active(microphone.generation));
        assert_eq!(runtime.playout_offsets(), (162_659, 5_000));
        assert_eq!(runtime.snapshot().session_id, session_id);
    }

    let fresh_microphone = runtime.activate_microphone();
    assert!(runtime.is_microphone_active(fresh_microphone.generation));
    assert!(fresh_microphone.generation > microphone.generation);
    assert_eq!(fresh_microphone.session_id, session_id);
}

#[test]
fn connect_disconnect_cycles_leave_no_stale_microphone_generation_active() {
    let runtime = UpstreamMediaRuntime::new();

    for cycle in 0..20 {
        let camera = runtime.activate_camera();
        let microphone = runtime.activate_microphone();
        let session_id = runtime.snapshot().session_id;

        runtime.soft_recover_microphone();
        assert!(
            runtime.is_camera_active(camera.generation),
            "cycle {cycle}: video generation should survive audio heal"
        );
        assert!(
            !runtime.is_microphone_active(microphone.generation),
            "cycle {cycle}: stale microphone generation should be retired"
        );

        let replacement = runtime.activate_microphone();
        assert_eq!(replacement.session_id, session_id);
        assert!(runtime.is_microphone_active(replacement.generation));

        runtime.close_microphone(replacement.generation);
        runtime.close_camera(camera.generation);
        assert!(
            !runtime.is_camera_active(camera.generation),
            "cycle {cycle}: camera should close cleanly after session"
        );
        assert!(
            !runtime.is_microphone_active(replacement.generation),
            "cycle {cycle}: replacement microphone should close cleanly after session"
        );
    }
}
