/// Valence Normalization Boundary
///
/// Clean JSON-LD from Fluree before it enters components.
/// Components work with native MoonBit types only.

/// Convert Fluree URI to DOM-safe key (for element IDs, CSS classes)
///
/// Example:
///   "http://helios.local/schema/Heartbeat" → "Heartbeat"
///   "ex:ev-001" → "ev-001"
pub fn uri_to_key(uri: String) -> String {
  uri
    .replace(old="http://helios.local/schema/", new="")
    .replace(old="http://helios.local/", new="")
    .replace(old="https://helios.local/", new="")
    .replace(old="ex:", new="")
    .replace(old="/", new="-")
    .replace(old=":", new="-")
    .replace(old="#", new="-")
    .replace(old=".", new="-")
}

/// Normalize instance name for use in CSS classes and IDs
///
/// Example: "Claude Code Opus" → "claude-code-opus"
pub fn normalize_instance_name(name: String) -> String {
  name
    .to_lower()
    .replace(old=" ", new="-")
    .replace(old="_", new="-")
    .replace(old=".", new="-")
}

/// Truncate message to max length with ellipsis
pub fn truncate_string(s: String, max_len: Int) -> String {
  if s.length() > max_len {
    s[0:max_len - 3].to_owned() + "..."
  } else {
    s
  }
}

/// Format relative time from ISO timestamp
/// Example: "2026-05-24 14:30:00" with load_time "2026-05-24 14:35:00" → "5 min ago"
pub fn format_relative_time(timestamp: String, load_time: String) -> String {
  // Simplified: just return timestamp for now
  // Full implementation: parse ISO, compute delta, format as "X min/hour/day ago"
  timestamp
}