///|
/// A constant collector that identifies the running application build.
///
/// The collector exposes one `moonbit_build_info` gauge with value `1` and
/// the constant labels `revision`, `target`, and `version`.
pub struct BuildInfoCollector {
  descriptor : @metric.Descriptor
  labels : Array[@metric.Label]
}

///|
/// Construct build information for one application binary.
///
/// `revision` and `target` default to `"unknown"` so callers can expose a
/// useful version metric even when their build pipeline does not inject Git
/// or backend metadata.
pub fn BuildInfoCollector::new(
  version : String,
  revision? : String = "unknown",
  target? : String = "unknown",
) -> BuildInfoCollector {
  let labels : Array[@metric.Label] = [
    { name: "revision", value: revision },
    { name: "target", value: target },
    { name: "version", value: version },
  ]
  let descriptor = try! @metric.Descriptor::new(
    "moonbit_build_info",
    GaugeKind,
    help="Build information about the MoonBit application",
    const_labels=labels,
  )
  { descriptor, labels }
}

///|
/// Return the immutable metric descriptor advertised by this collector.
pub fn BuildInfoCollector::descriptor(
  self : BuildInfoCollector,
) -> @metric.Descriptor {
  self.descriptor
}

///|
/// Return a detached copy of the build labels.
pub fn BuildInfoCollector::labels(
  self : BuildInfoCollector,
) -> Array[@metric.Label] {
  self.labels.copy()
}

///|
/// Adapt this build-information metric for registration in a `Registry`.
pub fn BuildInfoCollector::collector(
  self : BuildInfoCollector,
) -> @registry.CollectorAdapter {
  let descriptor = self.descriptor
  let labels = self.labels.copy()
  @registry.CollectorAdapter::new([descriptor], () => {
    Ok([
      @registry.FamilySnapshot::scalar(
        descriptor.name(),
        descriptor.help(),
        GaugeFamily,
        [@registry.scalar_sample(labels, 1.0)],
        descriptor.unit(),
      ),
    ])
  })
}