// Copyright 2026 TiKV Project Authors. Licensed under Apache-2.0.

use std::path::PathBuf;

use legacy_sst::{ChecksumType, Reader};

const CASES: &[(&str, u32, ChecksumType)] = &[
    ("format-0.sst", 0, ChecksumType::Crc32c),
    ("format-1.sst", 1, ChecksumType::Crc32c),
    ("format-2.sst", 2, ChecksumType::Crc32c),
    ("format-3.sst", 3, ChecksumType::Crc32c),
    ("format-4.sst", 4, ChecksumType::Crc32c),
    ("format-5.sst", 5, ChecksumType::Crc32c),
    ("checksum-none.sst", 5, ChecksumType::None),
    ("checksum-xxhash32.sst", 5, ChecksumType::XxHash),
    ("checksum-xxhash64.sst", 5, ChecksumType::XxHash64),
    ("checksum-xxh3.sst", 5, ChecksumType::Xxh3),
    ("compression-none.sst", 5, ChecksumType::Crc32c),
    ("compression-snappy.sst", 5, ChecksumType::Crc32c),
    ("compression-lz4.sst", 5, ChecksumType::Crc32c),
    ("compression-zstd.sst", 5, ChecksumType::Crc32c),
    ("filter-full-bloom.sst", 5, ChecksumType::Crc32c),
];

#[test]
fn reads_files_produced_by_rocksdb_8_10_2() {
    for &(name, expected_format, expected_checksum) in CASES {
        verify_fixture(name, expected_format, expected_checksum);
    }
}

fn verify_fixture(name: &str, expected_format: u32, expected_checksum: ChecksumType) {
    let path = fixture_path(name);
    let reader = Reader::open(&path).unwrap_or_else(|error| panic!("{name}: {error}"));
    assert_eq!(reader.format_version(), expected_format, "{name}");
    assert_eq!(reader.checksum_type(), expected_checksum, "{name}");
    reader
        .verify_checksum()
        .unwrap_or_else(|error| panic!("{name}: {error}"));

    let mut iter = reader.iter();
    assert!(iter.seek_to_first().unwrap(), "{name}");
    for index in 0..100 {
        assert_eq!(iter.key(), format!("key-{index:04}").as_bytes(), "{name}");
        assert_eq!(
            iter.value(),
            format!("value-{index:04}-{}", "abcdefgh".repeat(32)).as_bytes(),
            "{name}"
        );
        if index != 99 {
            assert!(iter.next().unwrap(), "{name}");
        }
    }
    assert!(!iter.next().unwrap(), "{name}");

    assert!(iter.seek_to_last().unwrap(), "{name}");
    assert_eq!(iter.key(), b"key-0099", "{name}");
    assert!(iter.seek(b"key-0042").unwrap(), "{name}");
    assert_eq!(iter.key(), b"key-0042", "{name}");
}

fn fixture_path(name: &str) -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("tests/fixtures")
        .join(name)
}
