#[cfg(not(coverage))]
fn push_preview_packet(appsrc: &gst_app::AppSrc, pkt: VideoPacket) {
    let mut buf = gst::Buffer::from_slice(pkt.data);
    if let Some(buf) = buf.get_mut() {
        buf.set_pts(Some(gst::ClockTime::from_useconds(pkt.pts)));
    }
    let _ = appsrc.push_buffer(buf);
}

#[cfg(not(coverage))]
#[derive(Clone, Copy)]
enum PreviewCapsKind {
    Stream,
    Decoded,
}

#[cfg(not(coverage))]
fn record_preview_caps(
    shared: &Arc<Mutex<SharedPreviewState>>,
    element: &gst::Element,
    pad_name: &str,
    kind: PreviewCapsKind,
) {
    let Some(pad) = element.static_pad(pad_name) else {
        return;
    };
    let Some(caps) = pad.current_caps() else {
        return;
    };
    let caps_label = preview_caps_summary(&caps);
    if caps_label.is_empty() {
        return;
    }
    if let Ok(mut slot) = shared.lock() {
        match kind {
            PreviewCapsKind::Stream => slot.telemetry.note_stream_caps(&caps_label),
            PreviewCapsKind::Decoded => slot.telemetry.note_decoded_caps(&caps_label),
        }
    }
}

#[cfg(not(coverage))]
fn preview_caps_summary(caps: &impl std::fmt::Display) -> String {
    caps.to_string()
}

#[cfg(not(coverage))]
fn record_preview_packet(shared: &Arc<Mutex<SharedPreviewState>>, pkt: &VideoPacket) {
    if let Ok(mut slot) = shared.lock() {
        slot.telemetry.record_packet(
            pkt.seq,
            pkt.effective_fps,
            pkt.dropped_total,
            pkt.queue_depth,
            pkt.server_source_gap_peak_ms,
            pkt.server_send_gap_peak_ms,
            pkt.server_queue_peak,
            &pkt.server_encoder_label,
            pkt.server_process_cpu_tenths,
        );
    }
}

#[cfg(not(coverage))]
fn sample_to_frame(sample: &gst::Sample) -> Option<PreviewFrame> {
    let caps = sample.caps()?;
    let structure = caps.structure(0)?;
    let width = structure.get::<i32>("width").ok()?;
    let height = structure.get::<i32>("height").ok()?;
    let buffer = sample.buffer()?;
    let map = buffer.map_readable().ok()?;
    let rgba = map.as_slice().to_vec();
    let stride = rgba.len() / height.max(1) as usize;
    Some(PreviewFrame {
        width,
        height,
        stride,
        rgba,
    })
}

#[cfg(not(coverage))]
fn preview_decoder_label(element: &gst::Element) -> Option<String> {
    let factory = element.factory()?;
    let klass = factory.klass().to_ascii_lowercase();
    if !klass.contains("decoder") || !klass.contains("video") {
        return None;
    }
    Some(factory.name().to_string())
}

#[cfg(not(coverage))]
fn preview_bitrate(var: &str, default: u32) -> u32 {
    std::env::var(var)
        .ok()
        .and_then(|raw| raw.parse::<u32>().ok())
        .unwrap_or(default)
}

#[cfg(not(coverage))]
fn preview_dimension(var: &str, default: i32) -> i32 {
    std::env::var(var)
        .ok()
        .and_then(|raw| raw.parse::<i32>().ok())
        .filter(|value| *value > 0)
        .unwrap_or(default)
}

#[cfg(not(coverage))]
fn sanitize_preview_request(
    requested_width: i32,
    requested_height: i32,
    requested_fps: u32,
    max_bitrate_kbit: u32,
) -> (i32, i32, u32, u32) {
    let requested_width = requested_width.max(2);
    let requested_height = requested_height.max(2);
    let requested_fps = requested_fps.max(1);
    let max_bitrate_kbit = max_bitrate_kbit.max(800);
    (
        requested_width.min(INLINE_PREVIEW_REQUEST_WIDTH),
        requested_height.min(INLINE_PREVIEW_REQUEST_HEIGHT),
        requested_fps.min(INLINE_PREVIEW_REQUEST_FPS),
        max_bitrate_kbit.min(INLINE_PREVIEW_MAX_KBIT),
    )
}

#[cfg(not(coverage))]
#[cfg(not(coverage))]
fn events_per_second(events: &VecDeque<Instant>, now: Instant) -> f32 {
    let Some(oldest) = events.front().copied() else {
        return 0.0;
    };
    let span = now
        .saturating_duration_since(oldest)
        .as_secs_f32()
        .clamp(0.25, TELEMETRY_WINDOW.as_secs_f32());
    events.len() as f32 / span
}

#[cfg(not(coverage))]
fn trim_instant_queue(queue: &mut VecDeque<Instant>, now: Instant) {
    while let Some(oldest) = queue.front().copied() {
        if now.saturating_duration_since(oldest) > TELEMETRY_WINDOW {
            let _ = queue.pop_front();
        } else {
            break;
        }
    }
}

#[cfg(not(coverage))]
fn trim_value_queue<T>(queue: &mut VecDeque<(Instant, T)>, now: Instant) {
    while let Some((oldest, _)) = queue.front() {
        if now.saturating_duration_since(*oldest) > TELEMETRY_WINDOW {
            let _ = queue.pop_front();
        } else {
            break;
        }
    }
}

#[cfg(not(coverage))]
fn compute_jitter_ms(samples: &VecDeque<(Instant, f32)>) -> f32 {
    if samples.len() < 2 {
        return 0.0;
    }
    let mean = samples.iter().map(|(_, value)| *value).sum::<f32>() / samples.len() as f32;
    samples
        .iter()
        .map(|(_, value)| (value - mean).abs())
        .sum::<f32>()
        / samples.len() as f32
}

#[cfg(not(coverage))]
fn compute_peak_gap_ms(samples: &VecDeque<(Instant, f32)>) -> f32 {
    samples.iter().map(|(_, value)| *value).fold(0.0, f32::max)
}
