///|
/// CSS Diagnostics Collector
/// Collects and aggregates CSS parsing diagnostics

///|
/// A single diagnostic entry
pub(all) struct Diagnostic {
  property : String
  value : String
  level : SupportLevel
  severity : Severity
  selector : String // selector context where this appeared
}

///|
pub impl Show for Diagnostic with output(self, logger) {
  logger.write_string("[")
  self.severity.output(logger)
  logger.write_string("] ")
  logger.write_string(self.property)
  logger.write_string(": ")
  logger.write_string(self.value)
  logger.write_string(" (")
  self.level.output(logger)
  logger.write_string(")")
}

///|
/// Summary statistics for diagnostics
pub(all) struct DiagnosticSummary {
  total_properties : Int
  supported : Int
  partial : Int
  unsupported_layout : Int
  unsupported_visual : Int
  deprecated : Int
  unknown : Int
}

///|
pub impl Show for DiagnosticSummary with output(self, logger) {
  logger.write_string("CSS Diagnostics Summary:\n")
  logger.write_string("  Total: ")
  self.total_properties.output(logger)
  logger.write_string("\n  Supported: ")
  self.supported.output(logger)
  logger.write_string("\n  Partial: ")
  self.partial.output(logger)
  logger.write_string("\n  Unsupported (layout): ")
  self.unsupported_layout.output(logger)
  logger.write_string("\n  Unsupported (visual): ")
  self.unsupported_visual.output(logger)
  logger.write_string("\n  Deprecated: ")
  self.deprecated.output(logger)
  logger.write_string("\n  Unknown: ")
  self.unknown.output(logger)
}

///|
/// Collector for CSS diagnostics
pub struct DiagnosticsCollector {
  diagnostics : Array[Diagnostic]
  // Track unique property+value combinations to avoid duplicates
  seen : Map[String, Bool]
  // Count by support level
  mut supported_count : Int
  mut partial_count : Int
  mut unsupported_layout_count : Int
  mut unsupported_visual_count : Int
  mut deprecated_count : Int
  mut unknown_count : Int
}

///|
/// Create a new diagnostics collector
pub fn DiagnosticsCollector::new() -> DiagnosticsCollector {
  {
    diagnostics: [],
    seen: {},
    supported_count: 0,
    partial_count: 0,
    unsupported_layout_count: 0,
    unsupported_visual_count: 0,
    deprecated_count: 0,
    unknown_count: 0,
  }
}

///|
/// Add a property to the collector
pub fn DiagnosticsCollector::add_property(
  self : DiagnosticsCollector,
  property : String,
  value : String,
  selector : String,
) -> Unit {
  let level = get_support_level(property)
  let severity = support_to_severity(level)
  // Update counts
  match level {
    Supported => self.supported_count += 1
    Partial(_) => self.partial_count += 1
    UnsupportedLayout => self.unsupported_layout_count += 1
    UnsupportedVisual => self.unsupported_visual_count += 1
    Deprecated(_) => self.deprecated_count += 1
    Unknown => self.unknown_count += 1
  }
  // Only store non-supported properties to save memory
  if should_warn(level) {
    let key = property + ":" + value
    // Deduplicate
    if !self.seen.contains(key) {
      self.seen.set(key, true)
      self.diagnostics.push({ property, value, level, severity, selector })
    }
  }
}

///|
/// Get summary statistics
pub fn DiagnosticsCollector::get_summary(
  self : DiagnosticsCollector,
) -> DiagnosticSummary {
  {
    total_properties: self.supported_count +
    self.partial_count +
    self.unsupported_layout_count +
    self.unsupported_visual_count +
    self.deprecated_count +
    self.unknown_count,
    supported: self.supported_count,
    partial: self.partial_count,
    unsupported_layout: self.unsupported_layout_count,
    unsupported_visual: self.unsupported_visual_count,
    deprecated: self.deprecated_count,
    unknown: self.unknown_count,
  }
}

///|
/// Get all diagnostics
pub fn DiagnosticsCollector::get_diagnostics(
  self : DiagnosticsCollector,
) -> Array[Diagnostic] {
  self.diagnostics
}

///|
/// Get diagnostics filtered by severity
pub fn DiagnosticsCollector::get_by_severity(
  self : DiagnosticsCollector,
  severity : Severity,
) -> Array[Diagnostic] {
  let result : Array[Diagnostic] = []
  for diag in self.diagnostics {
    let matches = match (diag.severity, severity) {
      (Info, Info) => true
      (Warning, Warning) => true
      (Error, Error) => true
      _ => false
    }
    if matches {
      result.push(diag)
    }
  }
  result
}

///|
/// Get diagnostics that affect layout
pub fn DiagnosticsCollector::get_layout_affecting(
  self : DiagnosticsCollector,
) -> Array[Diagnostic] {
  let result : Array[Diagnostic] = []
  for diag in self.diagnostics {
    if affects_layout(diag.level) {
      result.push(diag)
    }
  }
  result
}

///|
/// Format diagnostics as a string report
pub fn DiagnosticsCollector::format_report(
  self : DiagnosticsCollector,
  max_entries : Int,
) -> String {
  let buf = StringBuilder::new()
  let summary = self.get_summary()
  // Header
  buf.write_string("=== CSS Support Report ===\n")
  buf.write_string("Total properties: ")
  buf.write_string(summary.total_properties.to_string())
  buf.write_string("\n")
  // Summary
  buf.write_string("  Supported: ")
  buf.write_string(summary.supported.to_string())
  buf.write_string("\n")
  if summary.partial > 0 {
    buf.write_string("  Partial: ")
    buf.write_string(summary.partial.to_string())
    buf.write_string("\n")
  }
  if summary.unsupported_visual > 0 {
    buf.write_string("  Unsupported (visual): ")
    buf.write_string(summary.unsupported_visual.to_string())
    buf.write_string("\n")
  }
  if summary.unsupported_layout > 0 {
    buf.write_string("  Unsupported (layout): ")
    buf.write_string(summary.unsupported_layout.to_string())
    buf.write_string(" [WARNING]\n")
  }
  if summary.deprecated > 0 {
    buf.write_string("  Deprecated: ")
    buf.write_string(summary.deprecated.to_string())
    buf.write_string("\n")
  }
  if summary.unknown > 0 {
    buf.write_string("  Unknown: ")
    buf.write_string(summary.unknown.to_string())
    buf.write_string(" [ERROR]\n")
  }
  // Layout-affecting issues (most important)
  let layout_issues = self.get_layout_affecting()
  if layout_issues.length() > 0 {
    buf.write_string("\n--- Layout-affecting issues ---\n")
    let count = if layout_issues.length() > max_entries {
      max_entries
    } else {
      layout_issues.length()
    }
    for i = 0; i < count; i = i + 1 {
      let diag = layout_issues[i]
      buf.write_string("  ")
      buf.write_string(diag.property)
      buf.write_string(": ")
      buf.write_string(diag.value)
      buf.write_string("\n")
    }
    if layout_issues.length() > max_entries {
      buf.write_string("  ... and ")
      buf.write_string((layout_issues.length() - max_entries).to_string())
      buf.write_string(" more\n")
    }
  }
  // Unknown properties (errors)
  let errors = self.get_by_severity(Error)
  if errors.length() > 0 {
    buf.write_string("\n--- Unknown properties ---\n")
    let count = if errors.length() > max_entries {
      max_entries
    } else {
      errors.length()
    }
    for i = 0; i < count; i = i + 1 {
      let diag = errors[i]
      buf.write_string("  ")
      buf.write_string(diag.property)
      buf.write_string(": ")
      buf.write_string(diag.value)
      buf.write_string("\n")
    }
    if errors.length() > max_entries {
      buf.write_string("  ... and ")
      buf.write_string((errors.length() - max_entries).to_string())
      buf.write_string(" more\n")
    }
  }
  buf.to_string()
}

///|
/// Format a compact one-line summary
pub fn DiagnosticsCollector::format_compact(
  self : DiagnosticsCollector,
) -> String {
  let summary = self.get_summary()
  let buf = StringBuilder::new()
  buf.write_string("CSS: ")
  buf.write_string(summary.supported.to_string())
  buf.write_string(" ok")
  if summary.partial > 0 {
    buf.write_string(", ")
    buf.write_string(summary.partial.to_string())
    buf.write_string(" partial")
  }
  if summary.unsupported_visual > 0 {
    buf.write_string(", ")
    buf.write_string(summary.unsupported_visual.to_string())
    buf.write_string(" visual-only")
  }
  if summary.unsupported_layout > 0 {
    buf.write_string(", ")
    buf.write_string(summary.unsupported_layout.to_string())
    buf.write_string(" layout!")
  }
  if summary.unknown > 0 {
    buf.write_string(", ")
    buf.write_string(summary.unknown.to_string())
    buf.write_string(" unknown!")
  }
  buf.to_string()
}