fn network_spread_ms(samples: &VecDeque<(Instant, f32)>) -> f32 {
    if samples.len() < 2 {
        return 0.0;
    }
    let mut values = samples.iter().map(|(_, value)| *value).collect::<Vec<_>>();
    values.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
    let median = values[values.len() / 2];
    let mut deviations = values
        .into_iter()
        .map(|value| (value - median).abs())
        .collect::<Vec<_>>();
    deviations.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
    deviations[deviations.len() / 2]
}

#[cfg(not(coverage))]
/// Apply a remote-audio gain slider update without unwinding through GTK callbacks.
fn apply_audio_gain_change(
    scale: &gtk::Scale,
    state: &Rc<RefCell<LauncherState>>,
    widgets: &super::ui_components::LauncherWidgets,
    child_proc: &Rc<RefCell<Option<RelayChild>>>,
) -> bool {
    let percent = scale
        .value()
        .round()
        .clamp(0.0, MAX_AUDIO_GAIN_PERCENT as f64) as u32;
    let label = {
        let Ok(mut state) = state.try_borrow_mut() else {
            return false;
        };
        if state.audio_gain_percent == percent {
            widgets.audio_gain_value.set_text(&state.audio_gain_label());
            return true;
        }
        state.set_audio_gain_percent(percent);
        state.audio_gain_label()
    };
    widgets.audio_gain_value.set_text(&label);
    let relay_live = child_proc
        .try_borrow()
        .map(|child| child.is_some())
        .unwrap_or(false);
    if relay_live {
        let path = audio_gain_control_path();
        match write_audio_gain_request(&path, percent) {
            Ok(()) => widgets
                .status_label
                .set_text(&format!("Remote audio gain set to {label}.")),
            Err(err) => widgets.status_label.set_text(&format!(
                "Remote audio gain set to {label} for the next relay launch, but live gain control could not be written: {err}"
            )),
        }
    } else {
        widgets.status_label.set_text(&format!(
            "Remote audio gain set to {label} for the next relay launch."
        ));
    }
    true
}

#[cfg(not(coverage))]
/// Apply a microphone uplink gain slider update without unwinding through GTK callbacks.
fn apply_mic_gain_change(
    scale: &gtk::Scale,
    state: &Rc<RefCell<LauncherState>>,
    widgets: &super::ui_components::LauncherWidgets,
    child_proc: &Rc<RefCell<Option<RelayChild>>>,
) -> bool {
    let percent = scale
        .value()
        .round()
        .clamp(0.0, MAX_MIC_GAIN_PERCENT as f64) as u32;
    let label = {
        let Ok(mut state) = state.try_borrow_mut() else {
            return false;
        };
        if state.mic_gain_percent == percent {
            widgets.mic_gain_value.set_text(&state.mic_gain_label());
            return true;
        }
        state.set_mic_gain_percent(percent);
        state.mic_gain_label()
    };
    widgets.mic_gain_value.set_text(&label);
    let relay_live = child_proc
        .try_borrow()
        .map(|child| child.is_some())
        .unwrap_or(false);
    if relay_live {
        let path = mic_gain_control_path();
        match write_mic_gain_request(&path, percent) {
            Ok(()) => widgets.status_label.set_text(&format!("Mic gain set to {label}.")),
            Err(err) => widgets.status_label.set_text(&format!(
                "Mic gain set to {label} for the next relay launch, but live gain control could not be written: {err}"
            )),
        }
    } else {
        widgets.status_label.set_text(&format!(
            "Mic gain set to {label} for the next relay launch."
        ));
    }
    true
}

#[cfg(not(coverage))]
/// Apply a live media soft-pause/resume request without restarting USB gadget functions.
fn apply_media_control_change(
    state_snapshot: &LauncherState,
    widgets: &super::ui_components::LauncherWidgets,
    child_proc: &Rc<RefCell<Option<RelayChild>>>,
    feed_label: &str,
    enabled: bool,
) {
    let relay_live = child_proc
        .try_borrow()
        .map(|child| child.is_some())
        .unwrap_or(false);
    let action = if enabled { "resumed" } else { "soft-paused" };
    if relay_live {
        let path = media_control_path();
        match write_media_control_request(&path, state_snapshot) {
            Ok(()) => widgets
                .status_label
                .set_text(&format!("{feed_label} {action} for the live relay.")),
            Err(err) => widgets.status_label.set_text(&format!(
                "{feed_label} will be {action} on the next relay launch, but the live soft-pause control could not be written: {err}"
            )),
        }
    } else {
        widgets.status_label.set_text(&format!(
            "{feed_label} will start {} on the next relay launch.",
            if enabled { "enabled" } else { "paused" }
        ));
    }
}

#[cfg(not(coverage))]
/// Apply a live media device-selection change by asking the relay child to rebuild that pipeline.
fn apply_live_media_device_change(
    state_snapshot: &LauncherState,
    widgets: &super::ui_components::LauncherWidgets,
    child_proc: &Rc<RefCell<Option<RelayChild>>>,
    feed_label: &str,
) {
    let relay_live = child_proc
        .try_borrow()
        .map(|child| child.is_some())
        .unwrap_or(false);
    if relay_live {
        let path = media_control_path();
        match write_media_control_request(&path, state_snapshot) {
            Ok(()) => widgets.status_label.set_text(&format!(
                "{feed_label} selection applied to the live relay; the stream is restarting."
            )),
            Err(err) => widgets.status_label.set_text(&format!(
                "{feed_label} selection is staged for the next relay launch, but live device control could not be written: {err}"
            )),
        }
    }
}

#[cfg(not(coverage))]
/// Refresh relay capture-power state in the background so GTK stays responsive.
fn request_capture_power_refresh(
    power_tx: std::sync::mpsc::Sender<PowerMessage>,
    server_addr: String,
    delay: Duration,
) {
    std::thread::spawn(move || {
        if !delay.is_zero() {
            std::thread::sleep(delay);
        }
        let result = fetch_capture_power(&server_addr).map_err(|err| err.to_string());
        let _ = power_tx.send(PowerMessage::Refresh(result));
    });
}

#[cfg(not(coverage))]
fn request_capture_power_command(
    power_tx: std::sync::mpsc::Sender<PowerMessage>,
    server_addr: String,
    command: CapturePowerCommand,
) {
    std::thread::spawn(move || {
        let result = set_capture_power_mode(&server_addr, command).map_err(|err| err.to_string());
        let _ = power_tx.send(PowerMessage::Command(result));
    });
}

#[cfg(not(coverage))]
/// Refresh upstream calibration state in the background so the UI can poll safely.
fn request_calibration_refresh(
    calibration_tx: std::sync::mpsc::Sender<CalibrationMessage>,
    server_addr: String,
    delay: Duration,
) {
    std::thread::spawn(move || {
        if !delay.is_zero() {
            std::thread::sleep(delay);
        }
        let result = fetch_calibration(&server_addr).map_err(|err| err.to_string());
        let _ = calibration_tx.send(CalibrationMessage::Refresh(result));
    });
}

#[cfg(not(coverage))]
/// Refresh authoritative upstream sync planner state in the background.
fn request_upstream_sync_refresh(
    upstream_sync_tx: std::sync::mpsc::Sender<UpstreamSyncMessage>,
    server_addr: String,
    delay: Duration,
) {
    std::thread::spawn(move || {
        if !delay.is_zero() {
            std::thread::sleep(delay);
        }
        let result = fetch_upstream_sync(&server_addr).map_err(|err| err.to_string());
        let _ = upstream_sync_tx.send(UpstreamSyncMessage::Refresh(result));
    });
}

#[cfg(not(coverage))]
fn request_calibration_command<F>(
    calibration_tx: std::sync::mpsc::Sender<CalibrationMessage>,
    server_addr: String,
    action: F,
) where
    F: FnOnce(&str) -> anyhow::Result<CalibrationStatus> + Send + 'static,
{
    std::thread::spawn(move || {
        let result = action(&server_addr).map_err(|err| err.to_string());
        let _ = calibration_tx.send(CalibrationMessage::Command(result));
    });
}

#[cfg(not(coverage))]
/// Probe server capabilities on a short-lived runtime without blocking the UI thread.
fn request_handshake_caps(
    caps_tx: std::sync::mpsc::Sender<CapsMessage>,
    server_addr: String,
    delay: Duration,
) {
    std::thread::spawn(move || {
        if !delay.is_zero() {
            std::thread::sleep(delay);
        }
        let runtime = tokio::runtime::Builder::new_current_thread()
            .enable_all()
            .build();
        let probe = match runtime {
            Ok(runtime) => runtime.block_on(probe(&server_addr)),
            Err(_) => HandshakeProbe::default(),
        };
        let _ = caps_tx.send(CapsMessage::Refresh(probe));
    });
}

#[cfg(not(coverage))]
fn unavailable_capture_power(detail: String) -> CapturePowerStatus {
    CapturePowerStatus {
        available: false,
        enabled: false,
        unit: "relay.service".to_string(),
        detail,
        active_leases: 0,
        mode: "auto".to_string(),
        detected_devices: 0,
    }
}

#[cfg(not(coverage))]
fn unavailable_calibration(detail: String) -> CalibrationStatus {
    CalibrationStatus::unavailable(detail)
}

#[cfg(not(coverage))]
fn unavailable_upstream_sync(detail: String) -> UpstreamSyncStatus {
    UpstreamSyncStatus::unavailable(detail)
}

#[cfg(not(coverage))]
fn calibration_summary(calibration: &CalibrationStatus) -> String {
    format!(
        "Upstream A/V calibration: {} audio {:+.1} ms, video {:+.1} ms ({}, {}).",
        calibration.profile,
        calibration.active_audio_offset_us as f64 / 1000.0,
        calibration.active_video_offset_us as f64 / 1000.0,
        calibration.source,
        calibration.confidence
    )
}
