#![allow(clippy::doc_markdown)]
//! Regression test for the pass-2 review finding:
//! "storage-indexes — total_count() and selectivity() recompute a full bitmap
//! union on every call."
//!
//! `BitmapIndex::total_count()` is now memoized (the union over every value
//! bitmap is computed at most once per mutation). This test pins the
//! correctness side of that optimization: the memoized count must always agree
//! with the freshly-recomputed union across a full insert / delete /
//! delete_entity cycle, including a cloned handle that shares the memo.

use tidaldb::storage::indexes::BitmapIndex;

#[test]
fn total_count_cache_tracks_mutations() {
    let index = BitmapIndex::new("category");
    // Primed-empty cache returns 0 without a recompute.
    assert_eq!(index.total_count(), 0);

    index.insert(1, "jazz");
    index.insert(2, "blues");
    index.insert(3, "jazz");
    // Invalidated by each insert, recomputed once, then memoized.
    assert_eq!(index.total_count(), 3);
    assert_eq!(index.total_count(), 3); // fast path agrees with slow path

    // Adding entity 1 to a SECOND value bitmap does not change the distinct
    // count: it is still three distinct entities in the union.
    index.insert(1, "blues");
    assert_eq!(index.total_count(), 3);

    // Removing entity 1 from only one of its two value bitmaps keeps it in the
    // union (still present under "jazz"), so the distinct count is unchanged.
    assert!(index.delete(1, "blues"));
    assert_eq!(index.total_count(), 3);

    // delete_entity scrubs every value bitmap, so the count finally drops.
    assert!(index.delete_entity(1) > 0);
    assert_eq!(index.total_count(), 2);
}

#[test]
fn cloned_handle_shares_total_count_memo() {
    // BitmapIndex::clone shares the underlying values Arc AND the memo Arc, so a
    // mutation through one handle must invalidate the other handle's cache.
    let a = BitmapIndex::new("format");
    a.insert(10, "video");
    assert_eq!(a.total_count(), 1);

    let b = a.clone();
    assert_eq!(b.total_count(), 1);

    // Mutate through `a`; `b` must observe the change, not a stale memo.
    a.insert(20, "audio");
    assert_eq!(b.total_count(), 2, "clone must see the shared invalidation");
}
