///|
/// Bitmap Attribute Index - Simplified index for low-cardinality fields
/// Supports equality and existence queries only, no range queries.
pub struct BitmapAttrIndex {
  data : Map[@types.VectorId, @types.Attrs] // id -> attrs
  eq_map : Map[String, Map[String, Array[@types.VectorId]]] // key -> value -> ids
  exists_map : Map[String, Array[@types.VectorId]] // key -> ids with that key
}

///|
/// Create a new empty BitmapAttrIndex
pub fn BitmapAttrIndex::new() -> BitmapAttrIndex {
  { data: {}, eq_map: {}, exists_map: {} }
}

///|
/// Set attributes for an ID (replaces existing)
pub fn BitmapAttrIndex::set_attrs(
  self : BitmapAttrIndex,
  id : @types.VectorId,
  attrs : @types.Attrs,
) -> Unit {
  // Remove old attrs from indexes if present
  match self.data.get(id) {
    None => ()
    Some(old_attrs) =>
      for_each_attr(old_attrs, fn(key, value) {
        remove_from_eq_index(self.eq_map, key, value, id)
        remove_from_exists_index(self.exists_map, key, id)
      })
  }
  // Add new attrs to indexes
  for_each_attr(attrs, fn(key, value) {
    add_to_eq_index(self.eq_map, key, value, id)
    if attr_value_counts_as_exists(value) {
      add_to_exists_index(self.exists_map, key, id)
    }
  })
  // Store attrs (defensive copy to prevent external mutation)
  self.data.set(id, attrs.copy())
}

///|
/// Get attributes for an ID
pub fn BitmapAttrIndex::get_attrs(
  self : BitmapAttrIndex,
  id : @types.VectorId,
) -> @types.Attrs? {
  self.data.get(id)
}

///|
/// Remove an ID from the index
pub fn BitmapAttrIndex::remove_id(
  self : BitmapAttrIndex,
  id : @types.VectorId,
) -> Unit {
  match self.data.get(id) {
    None => ()
    Some(old_attrs) => {
      for_each_attr(old_attrs, fn(key, value) {
        remove_from_eq_index(self.eq_map, key, value, id)
        remove_from_exists_index(self.exists_map, key, id)
      })
      self.data.remove(id)
    }
  }
}

///|
/// Find IDs where key equals value
pub fn BitmapAttrIndex::eq(
  self : BitmapAttrIndex,
  key : String,
  value : @types.AttrValue,
) -> Array[@types.VectorId] {
  let value_key = attr_value_to_key(value)
  match self.eq_map.get(key) {
    None => []
    Some(value_map) =>
      match value_map.get(value_key) {
        None => []
        Some(ids) => ids.copy()
      }
  }
}

///|
/// Find IDs where key exists
pub fn BitmapAttrIndex::exists(
  self : BitmapAttrIndex,
  key : String,
) -> Array[@types.VectorId] {
  match self.exists_map.get(key) {
    None => []
    Some(ids) => ids.copy()
  }
}

///|
/// Range queries not supported for Bitmap index
pub fn BitmapAttrIndex::range(
  _self : BitmapAttrIndex,
  key : String,
  range : @types.NumericRange,
) -> Array[@types.VectorId]? {
  let _ = (key, range)
  None // Not supported
}

///|
/// Get the number of indexed IDs
pub fn BitmapAttrIndex::size(self : BitmapAttrIndex) -> Int {
  self.data.length()
}