///|
/// Retains one accepted numeral with stable document and parse evidence.
pub(all) struct RomanIndexEntry {
  document_id : String
  source_span : SourceSpan
  source_text : String
  value : Int
  canonical : String
  normalized_text : String
  mode : RomanMode
  used_unicode_compatibility : Bool
  normalized_input : Bool
  trimmed_outer_whitespace : Bool
  token_count : Int
  ordinal : Int
} derive(Eq, Debug)

///|
/// Summarizes one Int-bounded scan report without discarding input position.
pub(all) struct RomanIndexDocumentMetadata {
  id : String
  source_length : Int
  parse_mode : RomanMode
  candidates_examined : Int
  accepted_count : Int
  rejected_count : Int
  first_ordinal : Int?
} derive(Eq, Debug)

///|
/// Retains one rejected candidate in document and source order.
pub(all) struct RomanIndexRejectionSummary {
  document_id : String
  source_span : SourceSpan
  source_text : String
  reason : ScanRejectionReason
} derive(Eq, Debug)

///|
/// Provides deterministic totals derived from retained index evidence.
pub(all) struct RomanIndexStatistics {
  total_documents : Int64
  candidates_examined : Int64
  accepted_entries : Int64
  rejected_candidates : Int64
  used_unicode_compatibility : Int64
  normalized_inputs : Int64
} derive(Eq, Debug)

///|
/// Stores source-ordered document entries, rejections, and aggregate evidence.
pub(all) struct RomanDocumentIndex {
  entries : Array[RomanIndexEntry]
  documents : Array[RomanIndexDocumentMetadata]
  rejections : Array[RomanIndexRejectionSummary]
  statistics : RomanIndexStatistics
} derive(Eq, Debug)

///|
/// Identifies the report array containing invalid retained evidence.
pub(all) enum RomanIndexEvidenceKind {
  IndexMatchEvidence
  IndexRejectionEvidence
} derive(Eq, Debug)

///|
/// Reports invalid identities, scan failures, and mutable report mismatches.
pub(all) enum RomanIndexConstructionError {
  EmptyIndexDocumentId(Int)
  DuplicateIndexDocumentId(String)
  IndexDocumentScanFailed(String, ConfigError)
  IndexReportDocumentCountMismatch(Int, Int)
  IndexReportDocumentIdMismatch(Int, String, String)
  IndexReportDocumentTextMismatch(Int, String, String)
  IndexReportUnexpectedScanFailure(String, ConfigError)
  IndexReportUnexpectedScanSuccess(String, ConfigError)
  IndexReportScanFailureMismatch(String, ConfigError, ConfigError)
  IndexScanReportMismatch(String)
  IndexCorpusStatisticsMismatch(RomanCorpusStatistics, RomanCorpusStatistics)
  IndexReportInvalidSpan(String, RomanIndexEvidenceKind, Int, SourceSpan, Int)
  IndexReportSourceMismatch(String, RomanIndexEvidenceKind, Int, String, String)
  IndexReportOutOfOrder(String, RomanIndexEvidenceKind, Int)
  IndexReportOverlappingEvidence(
    String,
    RomanIndexEvidenceKind,
    Int,
    RomanIndexEvidenceKind,
    Int
  )
  IndexReportCandidateCountTooSmall(String, Int, Int)
  IndexReportMatchParseFailed(String, Int, RomanReportError)
  IndexReportMatchEvidenceMismatch(String, Int)
  IndexReportMatchPolicyMismatch(String, Int)
  IndexReportUnexpectedRejectionDetails(String)
  IndexReportRejectionReasonMismatch(String, Int)
} derive(Eq, Debug)