///|
/// Stores the caller's stable identifier and original name.
pub(all) struct NameRecord {
  id : String
  name : String
} derive(Eq, Debug)

///|
/// Reports invalid index setup, records, or normalized data.
pub(all) enum IndexError {
  InvalidIndexMatchConfig(MatchError)
  NoBlockingAlgorithms
  DuplicateBlockingAlgorithm(Algorithm)
  EmptyRecordId
  DuplicateRecord(String)
  MissingRecord(String)
  IndexNormalizationFailed(NormalizationError)
  NoBlockingKeys(String)
  InvalidQueryLimit(Int)
  InvalidMinimumScore(Double)
  IndexMatchFailed(MatchError)
  UnsupportedSnapshotVersion(Int)
  DuplicateSnapshotRecord(String)
  InconsistentSnapshotRecord(String)
} derive(Eq, Debug)

///|
/// Stores original and recomputable derived fields for one record.
pub(all) struct IndexSnapshotRecord {
  record : NameRecord
  normalized : String
  bucket_keys : Array[String]
} derive(Eq, Debug)

///|
/// Represents a versioned, structured index export without file I/O claims.
pub(all) struct IndexSnapshot {
  version : Int
  config : MatchConfig
  blocking_algorithms : Array[Algorithm]
  records : Array[IndexSnapshotRecord]
} derive(Eq, Debug)

///|
/// Associates one indexed record with its complete matching evidence.
pub(all) struct IndexMatch {
  record : NameRecord
  normalized_name : String
  evidence : MatchEvidence
} derive(Eq, Debug)

///|
/// Counts the candidate, scoring, and result stages of an index query.
pub(all) struct IndexQuerySummary {
  candidate_count : Int
  scored_count : Int
  returned_count : Int
} derive(Eq, Debug)

///|
/// Contains ranked query matches and auditable stage counts.
pub(all) struct IndexQueryResult {
  query : String
  normalized_query : String
  matches : Array[IndexMatch]
  summary : IndexQuerySummary
} derive(Eq, Debug)

///|
/// Explains which blocking keys admitted one candidate.
pub(all) struct IndexCandidateRecord {
  record : NameRecord
  normalized_name : String
  shared_bucket_keys : Array[String]
} derive(Eq, Debug)

///|
/// Exposes a deterministic candidate set before similarity scoring.
pub(all) struct IndexCandidateSet {
  query : String
  normalized_query : String
  query_bucket_keys : Array[String]
  records : Array[IndexCandidateRecord]
} derive(Eq, Debug)

///|
/// Summarizes current inverted-index occupancy.
pub(all) struct IndexStatistics {
  record_count : Int
  bucket_count : Int
  key_assignment_count : Int
  largest_bucket_size : Int
  average_bucket_size : Double
} derive(Eq, Debug)

///|
/// Maintains records and an in-memory inverted index of phonetic keys.
pub struct NameIndex {
  config : MatchConfig
  blocking_algorithms : Array[Algorithm]
  records : Map[String, NameRecord]
  normalized : Map[String, String]
  record_bucket_keys : Map[String, Array[String]]
  buckets : Map[String, Array[String]]
}