use forge::signal::compactor;
use once_cell::sync::Lazy;
use regex::Regex;

// Spinner/cataloging progress lines
static PROGRESS_RE: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"(?m)^\s*[✔✘⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]\s+(?:Loaded|Cataloged|Indexed|Parsed|Tagged)[^\n]*\n?")
        .unwrap()
});

// ── compress syft SBOM output ─────────────────────────────────────────────────

pub fn compress_syft(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = PROGRESS_RE.replace_all(&cleaned, "");

    // If JSON/SPDX/CycloneDX output — passthrough (it's structured, already compact)
    let trimmed = s.trim();
    if trimmed.starts_with('{') || trimmed.starts_with("SPDX") || trimmed.starts_with("<?xml") {
        return trimmed.to_string();
    }

    // Table output: NAME  VERSION  TYPE
    let lines: Vec<&str> = s.lines().filter(|l| !l.trim().is_empty()).collect();
    let total = lines
        .iter()
        .filter(|l| {
            let t = l.trim();
            !t.starts_with("NAME") && !t.is_empty()
        })
        .count();

    if lines.len() > 30 {
        let shown = &lines[..30];
        return format!(
            "{}\n… [{} total packages — {} more not shown]",
            shown.join("\n"),
            total,
            total.saturating_sub(30)
        );
    }
    lines.join("\n")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn strips_spinner_progress() {
        let raw = " ✔ Loaded image\n ✔ Cataloged packages\nNAME       VERSION  TYPE\nopenssl    3.0.2    deb\ncurl       7.81.0   deb\n";
        let out = compress_syft(raw);
        assert!(!out.contains("Loaded image"), "{out}");
        assert!(out.contains("openssl"), "{out}");
    }

    #[test]
    fn truncates_large_sbom() {
        let mut lines = vec!["NAME  VERSION  TYPE".to_string()];
        for i in 0..40 {
            lines.push(format!("pkg-{i}  1.{i}.0  deb"));
        }
        let out = compress_syft(&lines.join("\n"));
        assert!(out.contains("more not shown"), "{out}");
    }

    #[test]
    fn json_passthrough() {
        let raw = " ✔ Cataloged packages\n{\"schema\":\"https://cyclonedx.org\"}\n";
        let out = compress_syft(raw);
        assert!(out.starts_with('{'), "{out}");
    }
}
