///|
/// A compact export row for event catalog interchange.
pub struct CatalogExportRow {
  id : Int
  origin_time : Double
  latitude : Double
  longitude : Double
  depth_km : Double
  magnitude : Double
  station_count : Int
  confidence : Double
  quality : String
}

///|
/// Return a quality label from catalog completeness and station support.
pub fn catalog_entry_quality(entry : CatalogEntry) -> String {
  if entry.confidence >= 0.8 && entry.station_count >= 4 {
    "high"
  } else if entry.confidence >= 0.5 && entry.station_count >= 2 {
    "medium"
  } else {
    "low"
  }
}

///|
/// Convert catalog entries into stable export rows.
pub fn catalog_export_rows(catalog : EventCatalog) -> Array[CatalogExportRow] {
  catalog.entries.map(entry => {
    id: entry.id,
    origin_time: entry.origin_time,
    latitude: entry.latitude,
    longitude: entry.longitude,
    depth_km: entry.depth_km,
    magnitude: entry.magnitude,
    station_count: entry.station_count,
    confidence: entry.confidence,
    quality: catalog_entry_quality(entry),
  })
}

///|
/// Serialize catalog rows as an extended CSV table.
pub fn catalog_export_csv(rows : Array[CatalogExportRow]) -> String {
  let mut output = "id,origin_time,latitude,longitude,depth_km,magnitude,station_count,confidence,quality\n"
  for row in rows {
    output = output +
      row.id.to_string() +
      "," +
      row.origin_time.to_string() +
      "," +
      row.latitude.to_string() +
      "," +
      row.longitude.to_string() +
      "," +
      row.depth_km.to_string() +
      "," +
      row.magnitude.to_string() +
      "," +
      row.station_count.to_string() +
      "," +
      row.confidence.to_string() +
      "," +
      row.quality +
      "\n"
  }
  output
}

///|
/// Export catalog rows as a GeoJSON-like FeatureCollection string.
pub fn catalog_export_geojson(rows : Array[CatalogExportRow]) -> String {
  let mut output = "{\"type\":\"FeatureCollection\",\"features\":["
  for index = 0; index < rows.length(); index = index + 1 {
    let row = rows[index]
    if index > 0 {
      output += ","
    }
    output += "{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[" +
      row.longitude.to_string() +
      "," +
      row.latitude.to_string() +
      "]},\"properties\":{"
    output += "\"id\":" +
      row.id.to_string() +
      ",\"origin_time\":" +
      row.origin_time.to_string() +
      ",\"depth_km\":" +
      row.depth_km.to_string() +
      ",\"magnitude\":" +
      row.magnitude.to_string() +
      ",\"confidence\":" +
      row.confidence.to_string() +
      ",\"quality\":\"" +
      row.quality +
      "\"}}"
  }
  output + "]}"
}

///|
/// Return rows sorted by descending magnitude.
pub fn sort_catalog_rows_by_magnitude(
  rows : Array[CatalogExportRow],
) -> Array[CatalogExportRow] {
  let result = rows.copy()
  result.sort_by((left, right) => {
    if left.magnitude > right.magnitude {
      -1
    } else if left.magnitude < right.magnitude {
      1
    } else {
      left.id - right.id
    }
  })
  result
}

///|
/// Return rows selected for a review queue.
pub fn catalog_review_queue(
  rows : Array[CatalogExportRow],
  minimum_magnitude : Double,
) -> Array[CatalogExportRow] {
  sort_catalog_rows_by_magnitude(
    rows.filter(row => {
      row.magnitude >= minimum_magnitude || row.quality == "low"
    }),
  )
}

///|
/// Count events in quality bands.
pub fn catalog_quality_counts(rows : Array[CatalogExportRow]) -> Array[Int] {
  [
    rows.filter(row => row.quality == "high").length(),
    rows.filter(row => row.quality == "medium").length(),
    rows.filter(row => row.quality == "low").length(),
  ]
}

///|
/// Format catalog export statistics.
pub fn catalog_export_summary(rows : Array[CatalogExportRow]) -> String {
  let counts = catalog_quality_counts(rows)
  "rows=" +
  rows.length().to_string() +
  " high=" +
  counts[0].to_string() +
  " medium=" +
  counts[1].to_string() +
  " low=" +
  counts[2].to_string()
}