use crate::opus::decoder::{
    MODE_CELT_ONLY, MODE_HYBRID, MODE_SILK_ONLY, OPUS_BANDWIDTH_WIDEBAND, OPUS_OK, OpusDecoder,
};
use crate::opus::encoder::{
    OPUS_APPLICATION_AUDIO, OPUS_APPLICATION_RESTRICTED_LOWDELAY, OPUS_APPLICATION_VOIP,
    OPUS_FRAMESIZE_5_MS, OPUS_FRAMESIZE_10_MS, OPUS_FRAMESIZE_40_MS, OPUS_FRAMESIZE_60_MS,
    OPUS_SIGNAL_MUSIC, OPUS_SIGNAL_VOICE, OpusEncoder,
};
use crate::opus::multistream::{OpusMSDecoder, OpusMSEncoder};

pub fn patterned_pcm_i16(frame_size: usize, channels: usize, seed: i32) -> Vec<i16> {
    (0..frame_size * channels)
        .map(|i| {
            let base = ((i as i32 * 7919 + seed * 911) % 28000) - 14000;
            if channels == 2 && i % 2 == 1 {
                (base / 2) as i16
            } else {
                base as i16
            }
        })
        .collect()
}

fn patterned_pcm_f32(frame_size: usize, channels: usize, seed: i32) -> Vec<f32> {
    patterned_pcm_i16(frame_size, channels, seed)
        .into_iter()
        .map(|sample| sample as f32 / 32768.0)
        .collect()
}

#[test]
fn public_api_silk_only_roundtrip_and_plc() {
    let mut enc = OpusEncoder::new(16000, 1, OPUS_APPLICATION_VOIP).unwrap();
    assert_eq!(enc.set_force_mode(MODE_SILK_ONLY), OPUS_OK);
    assert_eq!(enc.set_bitrate(32000), OPUS_OK);
    assert_eq!(enc.set_vbr(1), OPUS_OK);
    assert_eq!(enc.set_vbr_constraint(1), OPUS_OK);
    assert_eq!(enc.set_inband_fec(1), OPUS_OK);
    assert_eq!(enc.set_packet_loss_perc(20), OPUS_OK);
    assert_eq!(enc.set_dtx(1), OPUS_OK);
    assert_eq!(enc.set_signal(OPUS_SIGNAL_VOICE), OPUS_OK);
    assert_eq!(enc.set_expert_frame_duration(OPUS_FRAMESIZE_40_MS), OPUS_OK);
    assert_eq!(enc.get_expert_frame_duration(), OPUS_FRAMESIZE_40_MS);
    assert_eq!(enc.get_channels(), 1);
    assert_eq!(enc.get_sample_rate(), 16000);

    let mut dec = OpusDecoder::new(16000, 1).unwrap();

    for frame_idx in 0..3 {
        let pcm = patterned_pcm_i16(640, 1, 100 + frame_idx * 17);
        let mut packet = vec![0u8; 1500];
        let packet_capacity = packet.len() as i32;
        let len = enc.encode(&pcm, 640, &mut packet, packet_capacity).unwrap();
        let packet = &packet[..len as usize];

        assert!(len > 1);
        assert_eq!(enc.get_mode(), MODE_SILK_ONLY);
        assert!(enc.get_final_range() > 0);
        assert_eq!(dec.get_nb_samples(packet).unwrap(), 640);

        let mut out = vec![0i16; 640];
        let decoded = dec.decode(Some(packet), &mut out, 640, false).unwrap();
        assert_eq!(decoded, 640);
        assert!(out.iter().any(|&sample| sample != 0));
        assert_eq!(dec.get_last_packet_duration(), 640);

        let mut fec_out = vec![0i16; 640];
        let decoded_fec = dec.decode(Some(packet), &mut fec_out, 640, true).unwrap();
        assert_eq!(decoded_fec, 640);
    }

    let mut plc = vec![0i16; 640];
    assert_eq!(dec.decode(None, &mut plc, 640, false).unwrap(), 640);
}

#[test]
fn public_api_restricted_lowdelay_float_roundtrip() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_RESTRICTED_LOWDELAY).unwrap();
    assert_eq!(enc.set_vbr(0), OPUS_OK);
    assert_eq!(enc.set_complexity(10), OPUS_OK);
    assert_eq!(enc.set_expert_frame_duration(OPUS_FRAMESIZE_5_MS), OPUS_OK);
    assert_eq!(enc.set_phase_inversion_disabled(1), OPUS_OK);
    assert_eq!(enc.set_force_channels(2), OPUS_OK);

    let pcm = patterned_pcm_f32(240, 2, 43);
    let mut packet = vec![0u8; 1500];
    let packet_capacity = packet.len() as i32;
    let len = enc
        .encode_float(&pcm, 240, &mut packet, packet_capacity)
        .unwrap();
    let packet = &packet[..len as usize];

    assert!(len > 0);
    assert_eq!(enc.get_mode(), MODE_CELT_ONLY);
    assert!(enc.get_final_range() > 0);

    let mut dec = OpusDecoder::new(48000, 2).unwrap();
    dec.set_phase_inversion_disabled(true);

    let mut out = vec![0f32; 240 * 2];
    let decoded = dec
        .decode_float(Some(packet), &mut out, 240, false)
        .unwrap();
    assert_eq!(decoded, 240);
    assert!(out.iter().any(|sample| sample.abs() > 1e-4));
}

#[test]
fn public_api_decode24_roundtrip() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    let pcm = patterned_pcm_i16(960, 1, 77);
    let mut packet = vec![0u8; 1500];
    let packet_capacity = packet.len() as i32;
    let len = enc.encode(&pcm, 960, &mut packet, packet_capacity).unwrap();
    let packet = &packet[..len as usize];

    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    let mut pcm24 = vec![0i32; 960];
    let decoded = dec.decode24(Some(packet), &mut pcm24, 960, false).unwrap();
    assert_eq!(decoded, 960);
    assert!(pcm24.iter().any(|&sample| sample != 0));
}

#[test]
fn public_api_multistream_surround_roundtrip() {
    let (mut enc, streams, coupled, mapping) =
        OpusMSEncoder::new_surround(48000, 6, 1, OPUS_APPLICATION_AUDIO).unwrap();
    let mut dec = OpusMSDecoder::new(48000, 6, streams, coupled, &mapping).unwrap();

    assert_eq!(enc.nb_streams(), streams);
    assert_eq!(enc.nb_coupled_streams(), coupled);

    let pcm = patterned_pcm_i16(960, 6, 9);
    let mut packet = vec![0u8; 4000];
    let packet_capacity = packet.len() as i32;
    let len = enc.encode(&pcm, 960, &mut packet, packet_capacity).unwrap();
    assert!(len > 0);
    assert!(enc.get_final_range() > 0);

    let mut out = vec![0i16; 960 * 6];
    let decoded = dec
        .decode(Some(&packet[..len as usize]), len, &mut out, 960, false)
        .unwrap();
    assert_eq!(decoded, 960);
    assert!(out.iter().any(|&sample| sample != 0));
    assert!(dec.get_final_range() > 0);
}

// ===========================================================================
// Coverage improvement: comprehensive encode/decode matrix
// ===========================================================================

/// Encode `n_frames` frames and return all packets.
fn encode_frames(
    enc: &mut OpusEncoder,
    frame_size: usize,
    channels: usize,
    n_frames: usize,
) -> Vec<Vec<u8>> {
    let mut packets = Vec::new();
    for i in 0..n_frames {
        let pcm = patterned_pcm_i16(frame_size, channels, 100 + i as i32 * 13);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, frame_size as i32, &mut pkt, 1500).unwrap();
        packets.push(pkt[..len as usize].to_vec());
    }
    packets
}

/// Decode a packet (or PLC if None) and verify output.
fn decode_packet(dec: &mut OpusDecoder, pkt: Option<&[u8]>, frame_size: i32) -> Vec<i16> {
    let channels = dec.get_channels() as usize;
    let mut out = vec![0i16; frame_size as usize * channels];
    let decoded = dec.decode(pkt, &mut out, frame_size, false).unwrap();
    assert_eq!(decoded, frame_size);
    out
}

#[test]
fn coverage_silk_narrowband_8khz_mono() {
    let mut enc = OpusEncoder::new(8000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_bitrate(12000);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(8000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 160, 1, 5);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 160);
    }
    // PLC
    decode_packet(&mut dec, None, 160);
}

#[test]
fn coverage_silk_mediumband_12khz_stereo() {
    let mut enc = OpusEncoder::new(12000, 2, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_bitrate(24000);
    enc.set_complexity(5);
    let mut dec = OpusDecoder::new(12000, 2).unwrap();
    let pkts = encode_frames(&mut enc, 240, 2, 5);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 240);
    }
}

#[test]
fn coverage_silk_wideband_16khz_fec() {
    let mut enc = OpusEncoder::new(16000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_bitrate(32000);
    enc.set_inband_fec(1);
    enc.set_packet_loss_perc(25);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(16000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 320, 1, 8);
    // Normal decode
    for pkt in &pkts[..4] {
        decode_packet(&mut dec, Some(pkt), 320);
    }
    // FEC decode (look-ahead)
    let mut out = vec![0i16; 320];
    dec.decode(Some(&pkts[5]), &mut out, 320, true).unwrap();
    // Resume normal
    decode_packet(&mut dec, Some(&pkts[6]), 320);
}

#[test]
fn coverage_celt_only_48khz_mono_cbr() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_force_mode(MODE_CELT_ONLY);
    enc.set_bitrate(64000);
    enc.set_vbr(0); // CBR
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 960, 1, 5);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
}

#[test]
fn coverage_celt_only_48khz_stereo_vbr() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_force_mode(MODE_CELT_ONLY);
    enc.set_bitrate(128000);
    enc.set_vbr(1);
    enc.set_vbr_constraint(1);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(48000, 2).unwrap();
    let pkts = encode_frames(&mut enc, 960, 2, 5);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
}

#[test]
fn coverage_hybrid_mode_48khz() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_force_mode(MODE_HYBRID);
    enc.set_bitrate(48000);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 960, 1, 5);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
}

#[test]
fn coverage_hybrid_stereo_with_fec() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_force_mode(MODE_HYBRID);
    enc.set_bitrate(64000);
    enc.set_inband_fec(1);
    enc.set_packet_loss_perc(15);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(48000, 2).unwrap();
    let pkts = encode_frames(&mut enc, 960, 2, 8);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
}

#[test]
fn coverage_dtx_silence_detection() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(32000);
    enc.set_dtx(1);
    enc.set_vbr(1);
    enc.set_complexity(5);
    // Encode active speech first
    for i in 0..3 {
        let pcm = patterned_pcm_i16(960, 1, i * 17);
        let mut pkt = vec![0u8; 1500];
        enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
    }
    // Then encode silence → should eventually emit DTX packets, but the
    // primary contract of this test is just "encoding 20 frames of silence
    // with DTX enabled does not panic"; whether DTX actually fires on the
    // first 20 frames depends on internal adaptation state and isn't
    // asserted here.
    let silence = vec![0i16; 960];
    for _ in 0..20 {
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&silence, 960, &mut pkt, 1500).unwrap();
        if len == 1 {
            // DTX frame observed — further iterations would add no signal.
            break;
        }
    }
}

#[test]
fn coverage_restricted_lowdelay_5ms() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_RESTRICTED_LOWDELAY).unwrap();
    enc.set_bitrate(64000);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_5_MS);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 240, 1, 5);
    for pkt in &pkts {
        let mut out = vec![0i16; 240];
        dec.decode(Some(pkt), &mut out, 240, false).unwrap();
    }
}

#[test]
fn coverage_restricted_lowdelay_10ms_stereo() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_RESTRICTED_LOWDELAY).unwrap();
    enc.set_bitrate(128000);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_10_MS);
    let mut dec = OpusDecoder::new(48000, 2).unwrap();
    let pkts = encode_frames(&mut enc, 480, 2, 5);
    for pkt in &pkts {
        let mut out = vec![0i16; 480 * 2];
        dec.decode(Some(pkt), &mut out, 480, false).unwrap();
    }
}

#[test]
fn coverage_40ms_multiframe_silk() {
    let mut enc = OpusEncoder::new(16000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(24000);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_40_MS);
    let mut dec = OpusDecoder::new(16000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 640, 1, 3);
    for pkt in &pkts {
        let mut out = vec![0i16; 640];
        dec.decode(Some(pkt), &mut out, 640, false).unwrap();
    }
}

#[test]
fn coverage_60ms_multiframe_silk() {
    let mut enc = OpusEncoder::new(16000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(32000);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_60_MS);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(16000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 960, 1, 3);
    for pkt in &pkts {
        let mut out = vec![0i16; 960];
        dec.decode(Some(pkt), &mut out, 960, false).unwrap();
    }
}

#[test]
fn coverage_force_channels_mono_in_stereo_encoder() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_bitrate(64000);
    enc.set_force_channels(1); // Force mono output
    let pcm = patterned_pcm_i16(960, 2, 42);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
    assert!(len > 0);
}

#[test]
fn coverage_signal_type_music() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_bitrate(96000);
    enc.set_signal(OPUS_SIGNAL_MUSIC);
    enc.set_complexity(10);
    let pkts = encode_frames(&mut enc, 960, 1, 5);
    assert!(pkts.iter().all(|p| !p.is_empty()));
}

#[test]
fn coverage_complexity_sweep() {
    for complexity in [0, 1, 2, 5, 8, 10] {
        let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
        enc.set_bitrate(64000);
        enc.set_complexity(complexity);
        let pcm = patterned_pcm_i16(960, 1, complexity);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
        assert!(len > 0, "complexity {} failed", complexity);
    }
}

#[test]
fn coverage_sample_rate_sweep_silk() {
    for &rate in &[8000, 12000, 16000, 24000] {
        let frame_size = rate / 50; // 20ms
        let mut enc = OpusEncoder::new(rate, 1, OPUS_APPLICATION_VOIP).unwrap();
        enc.set_bitrate(24000);
        enc.set_force_mode(MODE_SILK_ONLY);
        let mut dec = OpusDecoder::new(rate, 1).unwrap();
        let pcm = patterned_pcm_i16(frame_size as usize, 1, rate);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, frame_size, &mut pkt, 1500).unwrap();
        let mut out = vec![0i16; frame_size as usize];
        dec.decode(Some(&pkt[..len as usize]), &mut out, frame_size, false)
            .unwrap();
    }
}

#[test]
fn coverage_decode_at_different_output_rates() {
    // Encode at 48kHz, decode at various rates
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_bitrate(64000);
    let pcm = patterned_pcm_i16(960, 1, 99);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
    let pkt = &pkt[..len as usize];

    for &rate in &[8000, 12000, 16000, 24000, 48000] {
        let frame_size = rate / 50;
        let mut dec = OpusDecoder::new(rate, 1).unwrap();
        let mut out = vec![0i16; frame_size as usize];
        dec.decode(Some(pkt), &mut out, frame_size, false).unwrap();
    }
}

#[test]
fn coverage_plc_progressive_decay() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(32000);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    // Prime with real data
    let pkts = encode_frames(&mut enc, 960, 1, 3);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
    // Multiple consecutive PLC frames → progressive decay
    for _ in 0..10 {
        decode_packet(&mut dec, None, 960);
    }
}

#[test]
fn coverage_encode_float_celt_stereo() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_force_mode(MODE_CELT_ONLY);
    enc.set_bitrate(128000);
    let pcm = patterned_pcm_f32(960, 2, 55);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode_float(&pcm, 960, &mut pkt, 1500).unwrap();
    assert!(len > 0);
}

#[test]
fn coverage_encode_float_silk_mono() {
    let mut enc = OpusEncoder::new(16000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(16000);
    let pcm = patterned_pcm_f32(320, 1, 66);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode_float(&pcm, 320, &mut pkt, 1500).unwrap();
    assert!(len > 0);
}

#[test]
fn coverage_decode_float_and_decode24() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_bitrate(64000);
    let pcm = patterned_pcm_i16(960, 1, 77);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
    let pkt = &pkt[..len as usize];

    // decode_float
    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    let mut out_f32 = vec![0f32; 960];
    dec.decode_float(Some(pkt), &mut out_f32, 960, false)
        .unwrap();
    assert!(out_f32.iter().any(|s| s.abs() > 1e-4));

    // decode24
    let mut dec2 = OpusDecoder::new(48000, 1).unwrap();
    let mut out_i32 = vec![0i32; 960];
    dec2.decode24(Some(pkt), &mut out_i32, 960, false).unwrap();
    assert!(out_i32.iter().any(|&s| s != 0));
}

#[test]
fn coverage_low_bitrate_silk_stereo_10ms() {
    let mut enc = OpusEncoder::new(16000, 2, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(12000);
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_complexity(10);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_10_MS);
    let mut dec = OpusDecoder::new(16000, 2).unwrap();
    let pkts = encode_frames(&mut enc, 160, 2, 5);
    for pkt in &pkts {
        let mut out = vec![0i16; 160 * 2];
        dec.decode(Some(pkt), &mut out, 160, false).unwrap();
    }
}

#[test]
fn coverage_high_bitrate_celt_mono_cbr_10ms() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_force_mode(MODE_CELT_ONLY);
    enc.set_bitrate(256000);
    enc.set_vbr(0);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_10_MS);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 480, 1, 3);
    for pkt in &pkts {
        let mut out = vec![0i16; 480];
        dec.decode(Some(pkt), &mut out, 480, false).unwrap();
    }
}

#[test]
fn coverage_mode_transition_silk_to_celt() {
    // Start in SILK, switch to CELT → exercises transition and redundancy paths
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(32000);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();

    // SILK frames
    enc.set_force_mode(MODE_SILK_ONLY);
    let pkts = encode_frames(&mut enc, 960, 1, 3);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
    // Switch to CELT
    enc.set_force_mode(MODE_CELT_ONLY);
    let pkts = encode_frames(&mut enc, 960, 1, 3);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
}

#[test]
fn coverage_mode_transition_celt_to_silk() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(32000);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();

    // CELT frames
    enc.set_force_mode(MODE_CELT_ONLY);
    let pkts = encode_frames(&mut enc, 960, 1, 3);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
    // Switch to SILK
    enc.set_force_mode(MODE_SILK_ONLY);
    let pkts = encode_frames(&mut enc, 960, 1, 3);
    for pkt in &pkts {
        decode_packet(&mut dec, Some(pkt), 960);
    }
}

#[test]
fn coverage_multistream_stereo_encode_decode() {
    let (mut enc, streams, coupled, mapping) =
        OpusMSEncoder::new_surround(48000, 2, 1, OPUS_APPLICATION_AUDIO).unwrap();
    let mut dec = OpusMSDecoder::new(48000, 2, streams, coupled, &mapping).unwrap();

    let pcm = patterned_pcm_i16(960, 2, 42);
    let mut pkt = vec![0u8; 4000];
    let len = enc.encode(&pcm, 960, &mut pkt, 4000).unwrap();

    let mut out = vec![0i16; 960 * 2];
    dec.decode(Some(&pkt[..len as usize]), len, &mut out, 960, false)
        .unwrap();
    assert!(out.iter().any(|&s| s != 0));
}

#[test]
fn coverage_decoder_gain_and_pitch() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(32000);
    let pcm = patterned_pcm_i16(960, 1, 88);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();

    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    dec.set_gain(256).unwrap(); // +1 dB
    let mut out = vec![0i16; 960];
    dec.decode(Some(&pkt[..len as usize]), &mut out, 960, false)
        .unwrap();
    let pitch = dec.get_pitch();
    // Pitch may or may not be > 0 depending on mode, just ensure no panic
    let _ = pitch;
}

#[test]
fn coverage_silk_24khz_superwideband() {
    let mut enc = OpusEncoder::new(24000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(32000);
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(24000, 1).unwrap();
    let pkts = encode_frames(&mut enc, 480, 1, 5);
    for pkt in &pkts {
        let mut out = vec![0i16; 480];
        dec.decode(Some(pkt), &mut out, 480, false).unwrap();
    }
}

#[test]
fn coverage_silk_stereo_high_complexity_wideband() {
    let mut enc = OpusEncoder::new(16000, 2, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(48000);
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_complexity(10);
    enc.set_inband_fec(1);
    enc.set_packet_loss_perc(10);
    let mut dec = OpusDecoder::new(16000, 2).unwrap();
    let pkts = encode_frames(&mut enc, 320, 2, 5);
    for pkt in &pkts {
        let mut out = vec![0i16; 320 * 2];
        dec.decode(Some(pkt), &mut out, 320, false).unwrap();
    }
}

#[test]
fn coverage_cbr_40ms_celt_stereo() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_force_mode(MODE_CELT_ONLY);
    enc.set_bitrate(96000);
    enc.set_vbr(0);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_40_MS);
    let mut dec = OpusDecoder::new(48000, 2).unwrap();
    let pkts = encode_frames(&mut enc, 1920, 2, 3);
    for pkt in &pkts {
        let mut out = vec![0i16; 1920 * 2];
        dec.decode(Some(pkt), &mut out, 1920, false).unwrap();
    }
}

// ===========================================================================
// Additional coverage: deep encoder/decoder path tests
// ===========================================================================

/// DTX with SILK — encode silence frames at VOIP mode until DTX 1-byte packets appear.
/// Targets encoder.rs lines 2202-2206 (SILK DTX producing 0-byte → 1-byte TOC-only).
#[test]
fn coverage_dtx_silk_voip_silence_packets() {
    let mut enc = OpusEncoder::new(16000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_bitrate(16000);
    enc.set_dtx(1);
    enc.set_vbr(1);
    enc.set_signal(OPUS_SIGNAL_VOICE);

    // Prime with active speech first to build up state
    for i in 0..5 {
        let pcm = patterned_pcm_i16(320, 1, 5000 + i * 13);
        let mut pkt = vec![0u8; 1500];
        enc.encode(&pcm, 320, &mut pkt, 1500).unwrap();
    }

    // Now encode silence — SILK DTX should eventually produce 1-byte packets
    let silence = vec![0i16; 320];
    let mut dtx_found = false;
    for _ in 0..40 {
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&silence, 320, &mut pkt, 1500).unwrap();
        if len == 1 {
            dtx_found = true;
            break;
        }
    }
    assert!(
        dtx_found,
        "DTX should produce 1-byte TOC-only packet after sustained silence"
    );
}

/// Low bitrate stereo width: stereo encoder at 12000bps.
/// Targets encoder.rs lines 1552-1565 (stereo width at low equiv_rate < 16000).
#[test]
fn coverage_stereo_width_low_bitrate() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(12000);
    enc.set_vbr(1);
    enc.set_signal(OPUS_SIGNAL_VOICE);

    let mut dec = OpusDecoder::new(48000, 2).unwrap();
    // Encode several frames to let stereo width stabilize at low rate
    for i in 0..5 {
        let pcm = patterned_pcm_i16(960, 2, 5100 + i * 7);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
        assert!(len > 0);
        let mut out = vec![0i16; 960 * 2];
        dec.decode(Some(&pkt[..len as usize]), &mut out, 960, false)
            .unwrap();
    }
}

/// High bitrate stereo width: stereo encoder at 64000bps CELT mode.
/// Targets encoder.rs lines 1552-1565 (stereo width at high equiv_rate > 32000).
#[test]
fn coverage_stereo_width_high_bitrate_celt() {
    let mut enc = OpusEncoder::new(48000, 2, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_force_mode(MODE_CELT_ONLY);
    enc.set_bitrate(64000);
    enc.set_vbr(1);
    enc.set_signal(OPUS_SIGNAL_MUSIC);

    let mut dec = OpusDecoder::new(48000, 2).unwrap();
    for i in 0..5 {
        let pcm = patterned_pcm_i16(960, 2, 5200 + i * 11);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
        assert!(len > 0);
        let mut out = vec![0i16; 960 * 2];
        dec.decode(Some(&pkt[..len as usize]), &mut out, 960, false)
            .unwrap();
    }
}

/// 5ms SILK override: set SILK mode + 5ms frames, should internally force CELT.
/// Targets encoder.rs lines 1447-1449 (frame_size < fs/100 forces CELT_ONLY).
#[test]
fn coverage_5ms_silk_override_to_celt() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_bitrate(32000);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_5_MS);

    // 5ms at 48kHz = 240 samples, which is < fs/100 = 480
    let pcm = patterned_pcm_i16(240, 1, 5300);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode(&pcm, 240, &mut pkt, 1500).unwrap();
    assert!(len > 0);
    // Even though we forced SILK, 5ms frames must force CELT
    assert_eq!(enc.get_mode(), MODE_CELT_ONLY);
}

/// Voice ratio positive path: encode VOIP with voice_ratio >= 0.
/// Targets encoder.rs lines 1341-1346 (voice_ratio >= 0 path in voice estimation).
/// Note: voice_ratio is reset to -1 at the start of each encode call (fixed-point path),
/// so we verify it was set before encoding (the encode path reads it internally).
#[test]
fn coverage_voice_ratio_positive() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_voice_ratio(50);
    assert_eq!(enc.get_voice_ratio(), 50);
    enc.set_bitrate(32000);
    enc.set_vbr(1);

    let pcm = patterned_pcm_i16(960, 1, 5400);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
    assert!(len > 0);
    // voice_ratio is reset to -1 after encoding (C reference behavior)
    assert_eq!(enc.get_voice_ratio(), -1);
}

/// Mode transition SILK→CELT with redundancy: encode several SILK frames,
/// then force CELT to trigger the redundancy path.
/// Targets encoder.rs lines 1460-1472 and decoder.rs lines 812-823
/// (CELT redundancy decode, silk→celt transition).
#[test]
fn coverage_silk_to_celt_redundancy() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(48000);
    enc.set_vbr(1);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();

    // Establish SILK mode
    enc.set_force_mode(MODE_SILK_ONLY);
    for i in 0..5 {
        let pcm = patterned_pcm_i16(960, 1, 5500 + i * 13);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
        decode_packet(&mut dec, Some(&pkt[..len as usize]), 960);
    }

    // Now switch to CELT — should trigger silk→celt transition with redundancy.
    // The first frame after transition uses the prev mode (SILK) with a to_celt flag;
    // subsequent frames will be CELT_ONLY.
    enc.set_force_mode(MODE_CELT_ONLY);
    for i in 0..5 {
        let pcm = patterned_pcm_i16(960, 1, 5600 + i * 7);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
        decode_packet(&mut dec, Some(&pkt[..len as usize]), 960);
    }
    assert_eq!(enc.get_mode(), MODE_CELT_ONLY);
}

/// Mode transition CELT→SILK with short frames (redundancy = false).
/// Targets encoder.rs lines 1470-1472 (frame_size < fs/100 → redundancy=false).
#[test]
fn coverage_celt_to_silk_short_frames_no_redundancy() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(32000);
    enc.set_vbr(1);
    enc.set_expert_frame_duration(OPUS_FRAMESIZE_5_MS);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();

    // Establish CELT mode with 5ms frames
    enc.set_force_mode(MODE_CELT_ONLY);
    for i in 0..5 {
        let pcm = patterned_pcm_i16(240, 1, 5700 + i * 11);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 240, &mut pkt, 1500).unwrap();
        let mut out = vec![0i16; 240];
        dec.decode(Some(&pkt[..len as usize]), &mut out, 240, false)
            .unwrap();
    }

    // Switch to SILK — but 5ms < fs/100, so SILK is overridden to CELT
    // and no redundancy happens due to short frame size
    enc.set_force_mode(MODE_SILK_ONLY);
    for i in 0..3 {
        let pcm = patterned_pcm_i16(240, 1, 5800 + i * 7);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 240, &mut pkt, 1500).unwrap();
        let mut out = vec![0i16; 240];
        dec.decode(Some(&pkt[..len as usize]), &mut out, 240, false)
            .unwrap();
    }
    // With 5ms frames, mode should be CELT regardless of SILK request
    assert_eq!(enc.get_mode(), MODE_CELT_ONLY);
}

/// Hybrid→SILK transition: encode hybrid mode, then switch to SILK.
/// Targets decoder.rs lines 962-969 (CELT fade-out on hybrid→SILK transition).
#[test]
fn coverage_hybrid_to_silk_transition() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_bitrate(48000);
    enc.set_vbr(1);
    enc.set_complexity(10);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();

    // Establish hybrid mode
    enc.set_force_mode(MODE_HYBRID);
    for i in 0..5 {
        let pcm = patterned_pcm_i16(960, 1, 5900 + i * 13);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
        decode_packet(&mut dec, Some(&pkt[..len as usize]), 960);
    }
    assert_eq!(enc.get_mode(), MODE_HYBRID);

    // Switch to SILK — decoder should exercise the hybrid→SILK fade-out path
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_bandwidth(OPUS_BANDWIDTH_WIDEBAND);
    for i in 0..3 {
        let pcm = patterned_pcm_i16(960, 1, 6000 + i * 7);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
        decode_packet(&mut dec, Some(&pkt[..len as usize]), 960);
    }
}

/// CBR constraint test: CBR mode with constrained bitrate.
/// Targets encoder.rs lines 1607-1608, 2577-2583 (CBR padding path).
#[test]
fn coverage_cbr_constraint_padding() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_force_mode(MODE_CELT_ONLY);
    enc.set_bitrate(32000);
    enc.set_vbr(0); // CBR

    let pcm = patterned_pcm_i16(960, 1, 6100);
    let mut pkt = vec![0u8; 1500];
    let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
    assert!(len > 0);

    // Encode a second frame — CBR should produce consistent sizes
    let pcm2 = patterned_pcm_i16(960, 1, 6101);
    let mut pkt2 = vec![0u8; 1500];
    let len2 = enc.encode(&pcm2, 960, &mut pkt2, 1500).unwrap();
    assert!(len2 > 0);
}

/// Comprehensive encoder configuration sweep: exercise many internal branches
/// in a single test with minimal test LOC. Each configuration encodes several
/// frames and decodes them, exercising different mode/bandwidth/rate combinations.
#[test]
fn coverage_comprehensive_encoder_sweep() {
    // (rate, ch, app, mode, bw, bitrate, vbr, frame_ms, complexity, signal)
    type SweepCfg = (
        i32,
        i32,
        i32,
        Option<i32>,
        Option<i32>,
        i32,
        i32,
        i32,
        i32,
        Option<i32>,
    );
    let configs: &[SweepCfg] = &[
        // 16kHz SILK mono at different complexities
        (
            16000,
            1,
            OPUS_APPLICATION_VOIP,
            Some(MODE_SILK_ONLY),
            None,
            8000,
            1,
            20,
            0,
            Some(OPUS_SIGNAL_VOICE),
        ),
        (
            16000,
            1,
            OPUS_APPLICATION_VOIP,
            Some(MODE_SILK_ONLY),
            None,
            44000,
            1,
            20,
            10,
            Some(OPUS_SIGNAL_VOICE),
        ),
        // 8kHz SILK narrowband stereo (exercises resampler + stereo paths)
        (
            8000,
            2,
            OPUS_APPLICATION_VOIP,
            Some(MODE_SILK_ONLY),
            None,
            24000,
            1,
            20,
            5,
            Some(OPUS_SIGNAL_VOICE),
        ),
        // 24kHz SILK SWB (exercises SWB coding paths)
        (
            24000,
            1,
            OPUS_APPLICATION_VOIP,
            Some(MODE_SILK_ONLY),
            None,
            32000,
            1,
            20,
            5,
            None,
        ),
        // 48kHz CELT CBR mono at very low bitrate (exercises minimum-rate paths)
        (
            48000,
            1,
            OPUS_APPLICATION_AUDIO,
            Some(MODE_CELT_ONLY),
            None,
            6000,
            0,
            20,
            5,
            Some(OPUS_SIGNAL_MUSIC),
        ),
        // 48kHz CELT VBR stereo at high bitrate (exercises stereo decisions)
        (
            48000,
            2,
            OPUS_APPLICATION_AUDIO,
            Some(MODE_CELT_ONLY),
            None,
            128000,
            1,
            20,
            10,
            Some(OPUS_SIGNAL_MUSIC),
        ),
        // 48kHz Hybrid mono (exercises hybrid start band, SILK+CELT split)
        (
            48000,
            1,
            OPUS_APPLICATION_AUDIO,
            Some(MODE_HYBRID),
            None,
            40000,
            1,
            20,
            5,
            None,
        ),
        // 48kHz Hybrid stereo (exercises hybrid stereo width)
        (
            48000,
            2,
            OPUS_APPLICATION_AUDIO,
            Some(MODE_HYBRID),
            None,
            48000,
            1,
            20,
            5,
            None,
        ),
        // 48kHz auto mode at medium bitrate (lets encoder pick mode)
        (
            48000,
            1,
            OPUS_APPLICATION_AUDIO,
            None,
            None,
            24000,
            1,
            20,
            5,
            None,
        ),
        (
            48000,
            2,
            OPUS_APPLICATION_VOIP,
            None,
            None,
            32000,
            1,
            20,
            5,
            Some(OPUS_SIGNAL_VOICE),
        ),
        // 48kHz CELT 10ms (exercises short frame paths)
        (
            48000,
            1,
            OPUS_APPLICATION_RESTRICTED_LOWDELAY,
            Some(MODE_CELT_ONLY),
            None,
            48000,
            1,
            10,
            5,
            None,
        ),
        // Restricted low delay 5ms (smallest CELT frame)
        (
            48000,
            1,
            OPUS_APPLICATION_RESTRICTED_LOWDELAY,
            Some(MODE_CELT_ONLY),
            None,
            64000,
            1,
            5,
            5,
            None,
        ),
    ];
    for (idx, &(rate, ch, app, mode, bw, bitrate, vbr, frame_ms, complexity, signal)) in
        configs.iter().enumerate()
    {
        let mut enc = OpusEncoder::new(rate, ch, app).unwrap();
        enc.set_bitrate(bitrate);
        enc.set_vbr(vbr);
        enc.set_complexity(complexity);
        if let Some(m) = mode {
            enc.set_force_mode(m);
        }
        if let Some(b) = bw {
            enc.set_max_bandwidth(b);
        }
        if let Some(s) = signal {
            enc.set_signal(s);
        }
        let frame_size = rate * frame_ms / 1000;
        let mut dec = OpusDecoder::new(rate, ch).unwrap();
        for f in 0..8 {
            let pcm = patterned_pcm_i16(frame_size as usize, ch as usize, (idx * 100 + f) as i32);
            let mut pkt = vec![0u8; 1500];
            let len = enc.encode(&pcm, frame_size, &mut pkt, 1500).unwrap();
            assert!(len > 0, "config {idx} frame {f}: encode returned 0 bytes");
            let mut out = vec![0i16; frame_size as usize * ch as usize];
            dec.decode(Some(&pkt[..len as usize]), &mut out, frame_size, false)
                .unwrap();
        }
    }
}

/// Exercise the encoder's mode transition with redundancy by alternating
/// between SILK and CELT modes many times.
#[test]
fn coverage_rapid_mode_alternation() {
    let mut enc = OpusEncoder::new(48000, 1, OPUS_APPLICATION_AUDIO).unwrap();
    enc.set_bitrate(32000);
    enc.set_vbr(1);
    let mut dec = OpusDecoder::new(48000, 1).unwrap();
    let modes = [
        MODE_SILK_ONLY,
        MODE_CELT_ONLY,
        MODE_SILK_ONLY,
        MODE_CELT_ONLY,
        MODE_HYBRID,
        MODE_CELT_ONLY,
        MODE_SILK_ONLY,
        MODE_HYBRID,
        MODE_CELT_ONLY,
        MODE_SILK_ONLY,
    ];
    for (i, &mode) in modes.iter().enumerate() {
        enc.set_force_mode(mode);
        let pcm = patterned_pcm_i16(960, 1, 7000 + i as i32 * 17);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 960, &mut pkt, 1500).unwrap();
        let mut out = vec![0i16; 960];
        dec.decode(Some(&pkt[..len as usize]), &mut out, 960, false)
            .unwrap();
    }
}

/// Exercise the decoder's FEC path by dropping packets and using FEC recovery.
#[test]
fn coverage_fec_recovery_silk_multiple_drops() {
    let mut enc = OpusEncoder::new(16000, 1, OPUS_APPLICATION_VOIP).unwrap();
    enc.set_force_mode(MODE_SILK_ONLY);
    enc.set_bitrate(24000);
    enc.set_inband_fec(1);
    enc.set_packet_loss_perc(30);
    let mut dec = OpusDecoder::new(16000, 1).unwrap();
    let mut packets: Vec<Vec<u8>> = Vec::new();
    // Encode 10 frames
    for i in 0..10 {
        let pcm = patterned_pcm_i16(320, 1, 8000 + i * 13);
        let mut pkt = vec![0u8; 1500];
        let len = enc.encode(&pcm, 320, &mut pkt, 1500).unwrap();
        packets.push(pkt[..len as usize].to_vec());
    }
    // Decode with some drops: frames 3, 5, 7 are "lost"
    for i in 0..10 {
        let mut out = vec![0i16; 320];
        if i == 3 || i == 5 || i == 7 {
            // Lost frame — use FEC from next packet if available
            if i + 1 < packets.len() {
                dec.decode(Some(&packets[i + 1]), &mut out, 320, true)
                    .unwrap();
            } else {
                dec.decode(None, &mut out, 320, false).unwrap();
            }
        } else {
            dec.decode(Some(&packets[i]), &mut out, 320, false).unwrap();
        }
    }
}
