#[cfg(coverage)]
impl UvcConfig {
    /// Builds a bounded UVC mode from environment overrides.
    ///
    /// Inputs: `LESAVKA_UVC_*` mode variables. Output: a packet-safe mode
    /// snapshot. Why: coverage contracts must pin descriptor math without
    /// requiring the real kernel gadget.
    fn from_env() -> Self {
        let width = env_u32("LESAVKA_UVC_WIDTH", 1280);
        let height = env_u32("LESAVKA_UVC_HEIGHT", 720);
        let fps = env_u32("LESAVKA_UVC_FPS", 30).max(1);
        let interval = env_u32("LESAVKA_UVC_INTERVAL", 0);
        let bulk = uvc_bulk_transfer_enabled();
        let mut max_packet = env_u32("LESAVKA_UVC_MAXPACKET", 1024);

        if let Some(limit) = compute_payload_cap(bulk).map(|cap| cap.limit) {
            max_packet = max_packet.min(limit);
        }
        max_packet = if bulk {
            max_packet.min(512)
        } else {
            max_packet.min(1024)
        };
        let frame_size = uvc_frame_size_for_active_mode(width, height, fps, max_packet, bulk);

        let interval = if interval == 0 {
            10_000_000 / fps
        } else {
            interval
        };

        Self {
            width,
            height,
            fps,
            interval,
            max_packet,
            frame_size,
            bulk,
        }
    }
}

#[cfg(coverage)]
impl UvcState {
    /// Creates the control-state mirrors used by UVC request handling tests.
    ///
    /// Inputs: one validated UVC mode. Output: default/probe/commit buffers.
    /// Why: tests need deterministic state transitions for host negotiation.
    fn new(cfg: UvcConfig) -> Self {
        let ctrl_len = stream_ctrl_len();
        let default = build_streaming_control(&cfg, ctrl_len);
        Self {
            cfg,
            ctrl_len,
            default,
            probe: default,
            commit: default,
            cfg_snapshot: None,
            commit_observed: false,
        }
    }
}

#[cfg(coverage)]
fn load_interfaces() -> UvcInterfaces {
    let control = env_u8("LESAVKA_UVC_CTRL_INTF").unwrap_or(UVC_STRING_CONTROL_IDX);
    let streaming = env_u8("LESAVKA_UVC_STREAM_INTF").unwrap_or(UVC_STRING_STREAMING_IDX);
    UvcInterfaces { control, streaming }
}

#[cfg(coverage)]
fn read_interface(path: &str) -> Option<u8> {
    std::fs::read_to_string(path)
        .ok()
        .and_then(|v| v.trim().parse::<u8>().ok())
}

#[cfg(coverage)]
/// Parses a boolean environment flag with a default fallback.
///
/// Inputs: variable name and default value. Output: parsed boolean. Why:
/// UVC safety switches must handle common true/false spellings consistently.
fn env_flag_enabled(name: &str, default: bool) -> bool {
    env::var(name)
        .ok()
        .map(|value| {
            let trimmed = value.trim();
            if trimmed.eq_ignore_ascii_case("0")
                || trimmed.eq_ignore_ascii_case("false")
                || trimmed.eq_ignore_ascii_case("no")
                || trimmed.eq_ignore_ascii_case("off")
            {
                false
            } else if trimmed.eq_ignore_ascii_case("1")
                || trimmed.eq_ignore_ascii_case("true")
                || trimmed.eq_ignore_ascii_case("yes")
                || trimmed.eq_ignore_ascii_case("on")
            {
                true
            } else {
                default
            }
        })
        .unwrap_or(default)
}

#[cfg(coverage)]
/// Decides whether the coverage helper may use bulk transport.
///
/// Inputs: env override plus configfs capabilities. Output: effective mode.
/// Why: tests should not advertise bulk if the gadget tree lacks support.
fn uvc_bulk_transfer_enabled() -> bool {
    if !env_flag_enabled("LESAVKA_UVC_BULK", true) {
        return false;
    }
    uvc_bulk_transfer_enabled_for_base(std::path::Path::new(CONFIGFS_UVC_BASE))
}

#[cfg(coverage)]
/// Checks whether a configfs UVC function exposes the bulk-streaming knob.
///
/// Inputs: configfs function root. Output: effective bulk capability. Why:
/// tests need this branch without depending on the host's real gadget tree.
fn uvc_bulk_transfer_enabled_for_base(base: &std::path::Path) -> bool {
    lesavka_server::uvc_contract::bulk_enabled_from_configfs(
        base,
        env_flag_enabled("LESAVKA_UVC_BULK", true),
    )
}

#[cfg(coverage)]
fn uvc_frame_size_for_active_mode(
    width: u32,
    height: u32,
    fps: u32,
    max_packet: u32,
    bulk: bool,
) -> u32 {
    let derived = derived_uvc_frame_max_bytes_for_transport(fps, max_packet, bulk)
        .min(u32::MAX as usize) as u32;
    env_u32_opt("LESAVKA_UVC_FRAME_SIZE")
        .filter(|value| *value > 0)
        .unwrap_or(derived)
        .min(derived)
        .max((width.saturating_mul(height) / 32).max(64 * 1024).min(derived))
}
