///|
/// Maintenance operations for ANN indices
/// - HNSW compaction: Remove deleted entries and rebuild the graph
/// - IVF retraining: Recompute centroids and reassign vectors

///|
/// Compact HNSW index by removing tombstoned entries and rebuilding
/// Returns the number of removed entries
pub fn hnsw_compact_and_rebuild(
  state : HNSWState,
  store : @store.CoreStore,
) -> (HNSWState, Int) {
  let n = store.size()
  if n == 0 {
    return (state, 0)
  }
  // Count alive vectors
  let mut alive = 0
  for i in 0..= state.tombstone.length() || !state.tombstone[i] {
      alive = alive + 1
    }
  }
  if alive == n {
    return (state, 0)
  }
  // Create new HNSW state (use default seed 42 for rebuild)
  let new_state = HNSWState::new(
    @types.HNSWParams::{
      m: state.m,
      ef_construction: state.ef_construction,
      ef_search: state.ef_search,
      level_mult: state.level_mult,
      seed: 42UL,
      allow_replace_deleted: state.allow_replace_deleted,
    },
    state.metric,
    if alive > 0 {
      alive
    } else {
      1
    },
  )
  // Re-add non-tombstoned vectors, mark skipped as tombstoned
  for i in 0.. Int {
  if store.size() == 0 {
    return 0
  }
  // Train new centroids
  ivf_train(state, store, iterations~)
  // Clear existing lists
  for list in state.lists {
    list.clear()
  }
  state.id_to_list.clear()
  // Reassign all vectors to new centroids using ivf_assign (no bootstrap)
  let mut reassigned = 0
  for i in 0.. IVFState {
  let state = IVFState::new(params, metric, store.dim)
  if store.size() > 0 {
    ivf_train(state, store, iterations~)
    // Use ivf_assign to assign vectors to trained centroids (no bootstrap)
    for i in 0.. HNSWState {
  let cap = if store.size() > 0 { store.size() } else { 1 }
  let state = HNSWState::new(params, metric, cap)
  for i in 0.. (Int, Int) {
  let n = store.size()
  let mut dead = 0
  for i in 0..