#[cfg(all(test, not(coverage)))]
#[allow(clippy::items_after_test_module)]
mod tests {
    use super::{
        MediaV2BundleFacts, MediaV2ScheduledVideo, UpstreamStreamCleanup,
        media_v2_audio_starvation_elapsed,
        media_v2_audio_starvation_heal_after, media_v2_av_skew_elapsed,
        media_v2_av_skew_heal_after, media_v2_frame_step_us, media_v2_handoff_schedule,
        media_v2_has_hevc_recovery_keyframe, media_v2_should_hold_hevc_video_for_recovery,
        media_v2_uac_start_timeout, prepare_media_v2_audio, prepare_media_v2_video,
        retain_freshest_audio_packet, retain_freshest_video_packet, summarize_media_v2_bundle,
    };
    use lesavka_common::lesavka::{AudioPacket, UpstreamMediaBundle, VideoPacket};
    use lesavka_server::camera::CameraCodec;
    use lesavka_server::upstream_media_runtime::{
        UpstreamClientTiming, UpstreamMediaKind, UpstreamMediaRuntime,
    };
    use std::sync::Arc;

    #[tokio::test]
    async fn video_handoff_watch_retains_only_the_newest_scheduled_frame() {
        let (tx, mut rx) =
            tokio::sync::watch::channel::<Option<MediaV2ScheduledVideo>>(None);
        let now = tokio::time::Instant::now();

        for id in [1, 2, 3] {
            tx.send_replace(Some(MediaV2ScheduledVideo {
                packet: VideoPacket {
                    id,
                    ..Default::default()
                },
                due_at: now,
                received_at: now,
            }));
        }

        rx.changed().await.expect("latest frame should be pending");
        let latest = rx
            .borrow_and_update()
            .clone()
            .expect("video handoff frame");
        assert_eq!(latest.packet.id, 3);
    }

    #[test]
    /// Keeps `retain_freshest_video_packet_keeps_only_the_latest_frame` explicit because it sits on relay RPC orchestration, where hardware failures must surface without stopping the server.
    /// Inputs are the typed parameters; output is the return value or side effect.
    fn retain_freshest_video_packet_keeps_only_the_latest_frame() {
        let mut pending = std::collections::VecDeque::from(vec![
            VideoPacket {
                pts: 100,
                ..Default::default()
            },
            VideoPacket {
                pts: 200,
                ..Default::default()
            },
            VideoPacket {
                pts: 300,
                ..Default::default()
            },
        ]);

        let dropped = retain_freshest_video_packet(&mut pending);

        assert_eq!(dropped, 2);
        assert_eq!(pending.len(), 1);
        assert_eq!(pending.front().map(|pkt| pkt.pts), Some(300));
    }

    #[test]
    /// Keeps `retain_freshest_audio_packet_keeps_a_short_live_window` explicit because it sits on relay RPC orchestration, where hardware failures must surface without stopping the server.
    /// Inputs are the typed parameters; output is the return value or side effect.
    fn retain_freshest_audio_packet_keeps_a_short_live_window() {
        let mut pending = (0..10)
            .map(|idx| AudioPacket {
                pts: idx * 100,
                ..Default::default()
            })
            .collect::<std::collections::VecDeque<_>>();

        let dropped = retain_freshest_audio_packet(&mut pending);

        assert_eq!(dropped, 2);
        assert_eq!(pending.len(), 8);
        assert_eq!(pending.front().map(|pkt| pkt.pts), Some(200));
        assert_eq!(pending.back().map(|pkt| pkt.pts), Some(900));
    }

    #[test]
    /// Keeps `enqueue_pending_upstream_video_packet_records_timing_before_scheduler_waits` explicit because it sits on relay RPC orchestration, where hardware failures must surface without stopping the server.
    /// Inputs are the typed parameters; output is the return value or side effect.
    fn enqueue_pending_upstream_video_packet_records_timing_before_scheduler_waits() {
        let runtime = UpstreamMediaRuntime::new();
        let mut pending = std::collections::VecDeque::from(vec![VideoPacket {
            pts: 10,
            client_capture_pts_us: 10,
            client_send_pts_us: 10,
            ..Default::default()
        }]);

        runtime.record_client_timing(
            UpstreamMediaKind::Microphone,
            UpstreamClientTiming {
                capture_pts_us: 20,
                send_pts_us: 20,
                queue_depth: 0,
                queue_age_ms: 0,
            },
        );

        super::enqueue_pending_upstream_video_packet(
            &runtime,
            &mut pending,
            VideoPacket {
                pts: 20,
                client_capture_pts_us: 20,
                client_send_pts_us: 20,
                ..Default::default()
            },
            1,
            2,
            3,
            "test",
        );

        assert_eq!(pending.len(), 1);
        assert_eq!(pending.front().map(|pkt| pkt.pts), Some(20));
        let snapshot = runtime.snapshot();
        assert_eq!(snapshot.client_timing_window_samples, 1);
        assert!(
            snapshot.server_receive_abs_skew_p95_ms.unwrap_or(f64::INFINITY) < 50.0,
            "video timing should be recorded as the packet is enqueued, not after playout waits"
        );
    }

    #[test]
    /// Keeps `media_v2_bundle_summary_uses_client_capture_sidecar_not_packet_pts` explicit because it sits on relay RPC orchestration, where hardware failures must surface without stopping the server.
    /// Inputs are the typed parameters; output is the return value or side effect.
    fn media_v2_bundle_summary_uses_client_capture_sidecar_not_packet_pts() {
        let bundle = UpstreamMediaBundle {
            capture_start_us: 1,
            capture_end_us: 2,
            video: Some(VideoPacket {
                pts: 9_999_000,
                client_capture_pts_us: 1_000_000,
                client_send_pts_us: 1_001_000,
                client_queue_age_ms: 12,
                ..Default::default()
            }),
            audio: vec![AudioPacket {
                pts: 8_888_000,
                client_capture_pts_us: 1_020_000,
                client_send_pts_us: 1_021_000,
                client_queue_age_ms: 34,
                ..Default::default()
            }],
            ..Default::default()
        };

        let summary = summarize_media_v2_bundle(&bundle).expect("summary");

        assert!(summary.has_video);
        assert!(summary.has_audio);
        assert_eq!(summary.capture_start_us, 1_000_000);
        assert_eq!(summary.capture_end_us, 1_020_000);
        assert_eq!(summary.capture_span_us, 20_000);
        assert_eq!(summary.max_queue_age_ms, 34);
    }

    #[test]
    /// Keeps `media_v2_schedule_offsets_outputs_without_creating_split_planner` explicit because it sits on relay RPC orchestration, where hardware failures must surface without stopping the server.
    /// Inputs are the typed parameters; output is the return value or side effect.
    fn media_v2_schedule_offsets_outputs_without_creating_split_planner() {
        let facts = MediaV2BundleFacts {
            has_audio: true,
            has_video: true,
            capture_start_us: 1_000_000,
            capture_end_us: 1_020_000,
            capture_span_us: 20_000,
            max_queue_age_ms: 0,
        };

        let schedule =
            media_v2_handoff_schedule(facts, 0, 979_000).expect("fresh schedule");
        let audio_due = schedule.audio_due_at.expect("audio due");
        let video_due = schedule.video_due_at.expect("video due");

        assert_eq!(schedule.relative_audio_delay.as_millis(), 0);
        assert_eq!(schedule.relative_video_delay.as_millis(), 979);
        assert_eq!(video_due.duration_since(audio_due).as_millis(), 979);
        assert!(schedule.common_delay.as_millis() <= 21);
    }

    #[test]
    fn media_v2_schedule_refuses_bundles_already_past_freshness_budget() {
        let facts = MediaV2BundleFacts {
            has_audio: true,
            has_video: true,
            capture_start_us: 1_000_000,
            capture_end_us: 1_020_000,
            capture_span_us: 20_000,
            max_queue_age_ms: 1_000,
        };

        assert!(media_v2_handoff_schedule(facts, 0, 0).is_none());
    }

    #[test]
    fn media_v2_uac_start_timeout_is_short_and_operator_configurable() {
        temp_env::with_var_unset("LESAVKA_UPSTREAM_V2_UAC_START_TIMEOUT_MS", || {
            assert_eq!(
                media_v2_uac_start_timeout(),
                std::time::Duration::from_millis(750)
            );
        });

        temp_env::with_var("LESAVKA_UPSTREAM_V2_UAC_START_TIMEOUT_MS", Some("125"), || {
            assert_eq!(
                media_v2_uac_start_timeout(),
                std::time::Duration::from_millis(125)
            );
        });
    }

    #[test]
    fn media_v2_audio_starvation_watchdog_is_short_and_disableable() {
        temp_env::with_var_unset("LESAVKA_UPSTREAM_V2_AUDIO_STARVATION_HEAL_MS", || {
            assert_eq!(
                media_v2_audio_starvation_heal_after(),
                Some(std::time::Duration::from_millis(1_500))
            );
        });

        temp_env::with_var(
            "LESAVKA_UPSTREAM_V2_AUDIO_STARVATION_HEAL_MS",
            Some("0"),
            || {
                assert_eq!(media_v2_audio_starvation_heal_after(), None);
            },
        );
    }

    #[test]
    fn media_v2_av_skew_watchdog_is_short_and_disableable() {
        temp_env::with_var_unset("LESAVKA_UPSTREAM_V2_AV_SKEW_HEAL_MS", || {
            assert_eq!(
                media_v2_av_skew_heal_after(),
                Some(std::time::Duration::from_millis(1_500))
            );
        });

        temp_env::with_var("LESAVKA_UPSTREAM_V2_AV_SKEW_HEAL_MS", Some("0"), || {
            assert_eq!(media_v2_av_skew_heal_after(), None);
        });
    }

    #[test]
    fn media_v2_audio_starvation_elapsed_requires_live_video_without_audio() {
        let mut starved_since = None;
        let now = tokio::time::Instant::now();
        let video_only = MediaV2BundleFacts {
            has_audio: false,
            has_video: true,
            capture_start_us: 1_000,
            capture_end_us: 1_000,
            capture_span_us: 0,
            max_queue_age_ms: 0,
        };
        let audio_video = MediaV2BundleFacts {
            has_audio: true,
            has_video: true,
            ..video_only
        };

        assert!(!media_v2_audio_starvation_elapsed(
            true,
            video_only,
            now,
            &mut starved_since,
            Some(std::time::Duration::from_millis(1_500))
        ));
        assert!(starved_since.is_some());
        assert!(!media_v2_audio_starvation_elapsed(
            true,
            video_only,
            now + std::time::Duration::from_millis(1_499),
            &mut starved_since,
            Some(std::time::Duration::from_millis(1_500))
        ));
        assert!(media_v2_audio_starvation_elapsed(
            true,
            video_only,
            now + std::time::Duration::from_millis(1_500),
            &mut starved_since,
            Some(std::time::Duration::from_millis(1_500))
        ));
        assert!(!media_v2_audio_starvation_elapsed(
            true,
            audio_video,
            now + std::time::Duration::from_millis(1_600),
            &mut starved_since,
            Some(std::time::Duration::from_millis(1_500))
        ));
        assert!(starved_since.is_none());
    }

    #[test]
    fn media_v2_av_skew_elapsed_requires_sustained_impossible_capture_span() {
        let mut skewed_since = None;
        let now = tokio::time::Instant::now();
        let skewed = MediaV2BundleFacts {
            has_audio: true,
            has_video: true,
            capture_start_us: 1_000_000,
            capture_end_us: 1_400_001,
            capture_span_us: 400_001,
            max_queue_age_ms: 0,
        };
        let normal = MediaV2BundleFacts {
            capture_end_us: 1_020_000,
            capture_span_us: 20_000,
            ..skewed
        };

        assert!(!media_v2_av_skew_elapsed(
            skewed,
            now,
            &mut skewed_since,
            Some(std::time::Duration::from_millis(1_500))
        ));
        assert!(skewed_since.is_some());
        assert!(!media_v2_av_skew_elapsed(
            skewed,
            now + std::time::Duration::from_millis(1_499),
            &mut skewed_since,
            Some(std::time::Duration::from_millis(1_500))
        ));
        assert!(media_v2_av_skew_elapsed(
            skewed,
            now + std::time::Duration::from_millis(1_500),
            &mut skewed_since,
            Some(std::time::Duration::from_millis(1_500))
        ));
        assert!(!media_v2_av_skew_elapsed(
            normal,
            now + std::time::Duration::from_millis(1_600),
            &mut skewed_since,
            Some(std::time::Duration::from_millis(1_500))
        ));
        assert!(skewed_since.is_none());
    }

    #[test]
    /// Keeps server HEVC drop recovery explicit because late-drop freshness can otherwise corrupt decoded video.
    fn media_v2_hevc_recovery_holds_delta_until_keyframe() {
        let delta = VideoPacket {
            data: vec![0, 0, 0, 1, 0x02, 0x01, 0xaa],
            ..Default::default()
        };
        let keyframe = VideoPacket {
            data: vec![0, 0, 0, 1, 0x26, 0x01, 0xaa],
            ..Default::default()
        };

        assert!(media_v2_should_hold_hevc_video_for_recovery(
            true,
            CameraCodec::Hevc,
            Some(&delta),
        ));
        assert!(!media_v2_should_hold_hevc_video_for_recovery(
            true,
            CameraCodec::Hevc,
            Some(&keyframe),
        ));
        assert!(!media_v2_should_hold_hevc_video_for_recovery(
            true,
            CameraCodec::Mjpeg,
            Some(&delta),
        ));
        assert!(media_v2_has_hevc_recovery_keyframe(
            CameraCodec::Hevc,
            Some(&keyframe),
        ));
    }

    #[test]
    /// Keeps `media_v2_preparation_anchors_audio_and_video_to_one_capture_epoch` explicit because the bundled path must not let network receive cadence become video playout cadence.
    /// Inputs are one bundle's client capture PTS values; output proves audio
    /// and video are planned from the same epoch before handoff workers sleep.
    fn media_v2_preparation_anchors_audio_and_video_to_one_capture_epoch() {
        let runtime = UpstreamMediaRuntime::new();
        runtime.set_playout_offsets(0, 0);
        let epoch = tokio::time::Instant::now() + std::time::Duration::from_secs(1);
        let base = 1_000_000;
        let mut audio = vec![
            AudioPacket {
                client_capture_pts_us: base,
                ..Default::default()
            },
            AudioPacket {
                client_capture_pts_us: base + 10_000,
                ..Default::default()
            },
        ];
        let video = VideoPacket {
            client_capture_pts_us: base + 33_333,
            ..Default::default()
        };

        let scheduled_audio =
            prepare_media_v2_audio(&mut audio, &runtime, base, epoch).expect("audio plan");
        let scheduled_video = prepare_media_v2_video(
            Some(video),
            &runtime,
            base,
            epoch,
            tokio::time::Instant::now(),
            media_v2_frame_step_us(30),
        )
        .expect("video plan");

        assert_eq!(scheduled_audio.packets[0].pts, 0);
        assert_eq!(scheduled_audio.packets[1].pts, 10_000);
        assert_eq!(scheduled_video.packet.pts, 33_333);
        assert_eq!(scheduled_audio.due_at, epoch);
        assert_eq!(
            scheduled_video.due_at.duration_since(epoch).as_micros(),
            33_333
        );
    }

    #[test]
    /// Keeps `legacy_bundled_event_timing_example_documents_quarantined_v1_behavior` explicit because it sits on relay RPC orchestration, where hardware failures must surface without stopping the server.
    /// Inputs are the typed parameters; output is the return value or side effect.
    fn legacy_bundled_event_timing_example_documents_quarantined_v1_behavior() {
        let video = VideoPacket {
            pts: 9_999_000,
            client_capture_pts_us: 1_000_000,
            client_send_pts_us: 1_001_000,
            ..Default::default()
        };
        let audio = AudioPacket {
            pts: 8_888_000,
            client_capture_pts_us: 1_020_000,
            client_send_pts_us: 1_021_000,
            ..Default::default()
        };

        assert_eq!(video.client_capture_pts_us, 1_000_000);
        assert_eq!(audio.client_capture_pts_us, 1_020_000);
    }

    #[test]
    fn upstream_cleanup_guard_closes_its_microphone_generation() {
        let runtime = Arc::new(UpstreamMediaRuntime::new());
        let lease = runtime.activate_microphone();

        {
            let _guard =
                UpstreamStreamCleanup::microphone(runtime.clone(), lease.generation, 1, lease.session_id);
        }

        assert!(!runtime.is_microphone_active(lease.generation));
    }

    #[test]
    fn upstream_cleanup_guard_cannot_close_a_newer_camera_generation() {
        let runtime = Arc::new(UpstreamMediaRuntime::new());
        let first = runtime.activate_camera();
        let second = runtime.activate_camera();

        {
            let _guard =
                UpstreamStreamCleanup::camera(runtime.clone(), first.generation, 2, first.session_id, 7);
        }

        assert!(!runtime.is_camera_active(first.generation));
        assert!(runtime.is_camera_active(second.generation));
    }
}
