///|
/// Bruteforce ANN strategy implementation.
/// Simple linear scan over all vectors - best for small datasets.
pub struct BruteforceState {
  metric : @types.Metric
}

///|
/// Create bruteforce state
pub fn BruteforceState::new(metric : @types.Metric) -> BruteforceState {
  { metric, }
}

///|
/// Bruteforce search - linear scan over all vectors.
/// Returns top-k results sorted by score (highest first).
/// Query is normalized for cosine metric.
pub fn bf_search(
  state : BruteforceState,
  store : @store.CoreStore,
  q : Array[Double],
  k : Int,
  filter : ((@types.VectorId, @types.Attrs) -> Bool)?,
) -> Array[@types.SearchHit] {
  guard q.length() == store.dim else {
    abort(
      "dim mismatch: got " +
      q.length().to_string() +
      ", want " +
      store.dim.to_string(),
    )
  }
  // Normalize query for cosine
  let query = store.normalize_query(q)
  let out : Array[@types.SearchHit] = []
  let score_fn = @vecmath.get_score_fn(state.metric)
  for i in 0.. if !f(id, attrs) { continue }
      None => ()
    }
    let base = i * store.dim
    let s = score_fn(store.data, base, query, store.dim)
    push_search_hit_top_k(out, @types.SearchHit::{ id, score: s, attrs }, k)
  }
  out
}

///|
/// Bruteforce find one - returns the best match
pub fn bf_find(
  state : BruteforceState,
  store : @store.CoreStore,
  q : Array[Double],
  filter : ((@types.VectorId, @types.Attrs) -> Bool)?,
) -> @types.SearchHit? {
  let results = bf_search(state, store, q, 1, filter)
  first_search_hit(results)
}

///|
/// Bruteforce add - no-op for bruteforce (no index structure)
pub fn bf_add(
  _state : BruteforceState,
  _store : @store.CoreStore,
  _id : @types.VectorId,
) -> Unit {
  // No-op: bruteforce doesn't maintain an index
}

///|
/// Bruteforce remove - no-op for bruteforce (no index structure)
pub fn bf_remove(
  _state : BruteforceState,
  _store : @store.CoreStore,
  _id : @types.VectorId,
) -> Unit {
  // No-op: bruteforce doesn't maintain an index
}

///|
/// Serialize bruteforce state (empty for bruteforce)
pub fn bf_serialize(_state : BruteforceState) -> Bytes {
  Bytes::new(0)
}

///|
/// Deserialize bruteforce state (no-op)
pub fn bf_deserialize(_state : BruteforceState, _data : Bytes) -> Unit {
  // No-op: bruteforce has no serialized state
}