///|
/// Provenance link from an event result to its source trace.
pub struct EventProvenanceLink {
  event_id : String
  station : String
  channel : String
  start_time : Double
  end_time : Double
  sample_count : Int
  processing_plan : String
  checksum : String
}

///|
/// Create a provenance link from a processed trace.
pub fn make_event_provenance(
  event_id : String,
  trace : Trace,
  processing_plan : String,
) -> EventProvenanceLink {
  {
    event_id,
    station: trace.station,
    channel: trace.channel,
    start_time: trace.start_time,
    end_time: trace.start_time + trace.duration(),
    sample_count: trace.npts(),
    processing_plan,
    checksum: waveform_checksum(trace.data),
  }
}

///|
/// Validate a provenance link against a trace.
pub fn validate_event_provenance(
  link : EventProvenanceLink,
  trace : Trace,
) -> Result[Unit, String] {
  if link.station != trace.station || link.channel != trace.channel {
    return Err("provenance station or channel does not match trace")
  }
  if link.sample_count != trace.npts() {
    return Err("provenance sample count does not match trace")
  }
  if link.checksum != waveform_checksum(trace.data) {
    return Err("provenance checksum does not match trace")
  }
  Ok(())
}

///|
/// Export provenance links for audit storage.
pub fn event_provenance_to_csv(links : Array[EventProvenanceLink]) -> String {
  let mut output = "event_id,station,channel,start_time,end_time,sample_count,processing_plan,checksum\n"
  for link in links {
    output = output +
      link.event_id +
      "," +
      link.station +
      "," +
      link.channel +
      "," +
      link.start_time.to_string() +
      "," +
      link.end_time.to_string() +
      "," +
      link.sample_count.to_string() +
      "," +
      link.processing_plan +
      "," +
      link.checksum +
      "\n"
  }
  output
}

///|
/// Format a provenance link for logs.
pub fn event_provenance_text(link : EventProvenanceLink) -> String {
  "event=" +
  link.event_id +
  " station=" +
  link.station +
  " channel=" +
  link.channel +
  " samples=" +
  link.sample_count.to_string() +
  " checksum=" +
  link.checksum +
  " plan=" +
  link.processing_plan
}