/// Phase 11.2: Compatibility tests — verify we can parse openjpeg-generated headers.
///
/// Full bitstream decode of openjpeg files requires standard T2 packet parsing,
/// which is not yet implemented (our TCD uses a simplified internal format).
/// These tests verify header parsing and structural correctness.

/// Load a fixture file from tests/fixtures/
fn load_fixture(name: &str) -> Vec<u8> {
    let path = format!("{}/tests/fixtures/{}", env!("CARGO_MANIFEST_DIR"), name);
    std::fs::read(&path).unwrap_or_else(|e| panic!("failed to load fixture {}: {}", name, e))
}

#[test]
fn compat_decode_gray_lossless() {
    // Parse header of a lossless grayscale J2K file generated by openjpeg
    let data = load_fixture("gray_lossless.j2k");
    let header = justjp2::j2k::j2k_read_header(&data).unwrap();
    assert_eq!(header.siz.num_comps, 1);
    assert_eq!(header.siz.width, 8);
    assert_eq!(header.siz.height, 8);
    assert_eq!(header.siz.tile_width, 8);
    assert_eq!(header.siz.tile_height, 8);

    // Component info
    assert_eq!(header.siz.comps.len(), 1);
    assert_eq!(header.siz.comps[0].precision & 0x7F, 7); // 8-bit = precision-1 = 7
    assert_eq!(header.siz.comps[0].dx, 1);
    assert_eq!(header.siz.comps[0].dy, 1);

    // COD: should be reversible (5/3 wavelet)
    assert_eq!(header.cod.transform, 1); // 1 = 5/3 reversible
}

#[test]
fn compat_decode_rgb_lossless() {
    // Parse header of a lossless RGB J2K file generated by openjpeg
    let data = load_fixture("rgb_lossless.j2k");
    let header = justjp2::j2k::j2k_read_header(&data).unwrap();
    assert_eq!(header.siz.num_comps, 3);
    assert_eq!(header.siz.width, 8);
    assert_eq!(header.siz.height, 8);

    for comp in &header.siz.comps {
        assert_eq!(comp.precision & 0x7F, 7); // 8-bit
        assert_eq!(comp.dx, 1);
        assert_eq!(comp.dy, 1);
    }

    // Should use reversible transform
    assert_eq!(header.cod.transform, 1);
}

#[test]
fn compat_decode_lossy() {
    // Parse header of a lossy-compressed J2K file generated by openjpeg
    let data = load_fixture("gray_lossy.j2k");
    let header = justjp2::j2k::j2k_read_header(&data).unwrap();
    assert_eq!(header.siz.num_comps, 1);
    assert_eq!(header.siz.width, 8);
    assert_eq!(header.siz.height, 8);

    // openjpeg with -r 10 may still use 5/3 reversible depending on settings.
    // Just verify the transform field is valid (0 or 1).
    assert!(
        header.cod.transform <= 1,
        "transform should be 0 (9/7) or 1 (5/3), got {}",
        header.cod.transform
    );
}

#[test]
fn compat_multi_tile() {
    // Parse header of a multi-tile J2K file (16x16 image, 8x8 tiles)
    let data = load_fixture("multi_tile.j2k");
    let header = justjp2::j2k::j2k_read_header(&data).unwrap();
    assert_eq!(header.siz.width, 16);
    assert_eq!(header.siz.height, 16);
    assert_eq!(header.siz.tile_width, 8);
    assert_eq!(header.siz.tile_height, 8);
    assert_eq!(header.siz.num_comps, 1);

    // 16x16 with 8x8 tiles = 4 tiles
    let ntx = (header.siz.width + header.siz.tile_width - 1) / header.siz.tile_width;
    let nty = (header.siz.height + header.siz.tile_height - 1) / header.siz.tile_height;
    assert_eq!(ntx * nty, 4);
}

#[test]
fn compat_multi_resolution() {
    // Parse header of a multi-resolution J2K file (4 resolution levels)
    let data = load_fixture("multi_res.j2k");
    let header = justjp2::j2k::j2k_read_header(&data).unwrap();
    assert_eq!(header.siz.width, 16);
    assert_eq!(header.siz.height, 16);
    // COD should have num_decomp >= 3 for 4 resolution levels
    assert!(
        header.cod.num_decomp >= 3,
        "expected >= 3 decomp levels, got {}",
        header.cod.num_decomp
    );
}
