///|
/// Reports invalid batch inputs or a failed matching/indexing stage.
pub(all) enum DedupError {
  InvalidUnionFindSize(Int)
  UnionFindIndexOutOfBounds(Int, Int)
  DuplicateInputId(String)
  DedupIndexFailed(IndexError)
  DedupMatchFailed(MatchError)
} derive(Eq, Debug)

///|
/// Supplies one stable identifier and name to batch deduplication.
pub(all) struct DedupInput {
  id : String
  name : String
} derive(Eq, Debug)

///|
/// Retains the evidence for one accepted canonical record pair.
pub(all) struct DedupEdge {
  left_id : String
  right_id : String
  evidence : MatchEvidence
} derive(Eq, Debug)

///|
/// Contains one connected duplicate group and its stable representative.
pub(all) struct DedupGroup {
  representative : DedupInput
  members : Array[DedupInput]
} derive(Eq, Debug)

///|
/// Counts all observable stages of one deduplication run.
pub(all) struct DedupSummary {
  input_count : Int
  candidate_pair_count : Int
  comparison_count : Int
  accepted_edge_count : Int
  group_count : Int
  ungrouped_count : Int
} derive(Eq, Debug)

///|
/// Returns canonical groups, optional singletons, accepted evidence, and counts.
pub(all) struct DedupReport {
  groups : Array[DedupGroup]
  singletons : Array[DedupInput]
  accepted_edges : Array[DedupEdge]
  summary : DedupSummary
} derive(Eq, Debug)