use btree_store::{BTree, Result};
use std::sync::Arc;
use std::thread;
use tempfile::TempDir;

#[test]
#[cfg(not(windows))]
fn reproduce_btree_corruption() -> Result<()> {
    let temp_dir = TempDir::new().unwrap();
    let path = temp_dir.path().join("reproduce_manifest.db");

    let btree = Arc::new(BTree::open(path)?);

    // Initialize multiple buckets
    let buckets = ["bucket_1", "bucket_2", "bucket_3", "bucket_4", "bucket_5"];
    for b in buckets {
        btree.exec(b, |_| Ok(()))?;
    }

    let mut handles = vec![];

    // Simulate mace's concurrent scenario: Flusher and GC update different metadata buckets at the same time
    for t in 0..4 {
        let btree_clone = btree.clone();
        let handle = thread::spawn(move || {
            for i in 0..10000 {
                let bucket = buckets[i % buckets.len()];
                let key = format!("thread_{}_key_{}", t, i);
                let val = vec![t as u8; 3840];

                // Simulate mace's internal_commit behavior:
                // each exec is an independent disk commit
                if let Err(e) = btree_clone.exec(bucket, |txn| txn.put(key.as_bytes(), &val)) {
                    // If reproduction succeeds, this should trigger Corruption or Panic
                    eprintln!("Thread {} failed at iteration {}: {:?}", t, i, e);
                    if e.to_string().contains("Corruption") {
                        panic!("REPRODUCED: BTree Corruption detected!");
                    }
                }
            }
        });
        handles.push(handle);
    }

    for h in handles {
        h.join().unwrap();
    }

    Ok(())
}
