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

// Certificate chain noise: long base64 blocks
static CERT_BLOCK_RE: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"(?m)-----BEGIN CERTIFICATE-----[^-]*-----END CERTIFICATE-----\n?").unwrap()
});
// "Verification for <image>:" preamble
static VERIFY_PREAMBLE_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^Verification for [^\n]+:\n?").unwrap());

// ── compress cosign output ────────────────────────────────────────────────────

pub fn compress_cosign(subcmd: &str, raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = CERT_BLOCK_RE.replace_all(&cleaned, "[certificate redacted]\n");

    if subcmd.trim().starts_with("verify") {
        let s = VERIFY_PREAMBLE_RE.replace_all(&s, "");
        // Keep: verified OK / not signed / subject / issuer / identity / error
        let useful: Vec<&str> = s
            .lines()
            .filter(|l| {
                let t = l.trim();
                !t.is_empty()
                    && (t.contains("VERIFIED OK")
                        || t.contains("not signed")
                        || t.contains("no matching signatures")
                        || t.contains("subject")
                        || t.contains("issuer")
                        || t.contains("Issuer")
                        || t.contains("identity")
                        || t.contains("Error")
                        || t.contains("WARNING")
                        || t.starts_with('{')
                        || t.starts_with('['))
            })
            .collect();
        if useful.is_empty() {
            return compactor::collapse_blanks(&s);
        }
        return useful.join("\n");
    }

    // sign / attest / upload — keep errors + success confirmation
    let useful: Vec<&str> = s
        .lines()
        .filter(|l| {
            let t = l.trim();
            !t.is_empty()
                && (t.contains("pushed")
                    || t.contains("signed")
                    || t.contains("uploaded")
                    || t.contains("Error")
                    || t.contains("WARNING")
                    || t.contains("tlog entry"))
        })
        .collect();
    if useful.is_empty() {
        return compactor::collapse_blanks(&s);
    }
    useful.join("\n")
}

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

    #[test]
    fn verify_strips_cert_and_keeps_result() {
        let raw = "Verification for gcr.io/my-project/my-image:latest:\nThe following checks were performed on each of these signatures:\n  - The cosign claims were validated\n  - Existence of the claims in the transparency log was verified\n-----BEGIN CERTIFICATE-----\nMIIBvzCCAWagAwIBAgIUYkXr\n-----END CERTIFICATE-----\n[certificate redacted]\nSubject: https://github.com/my-org/my-repo/.github/workflows/release.yml@refs/tags/v1.0\nIssuer: https://token.actions.githubusercontent.com\n";
        let out = compress_cosign("verify", raw);
        assert!(!out.contains("BEGIN CERTIFICATE"), "{out}");
        assert!(out.contains("Subject") || out.contains("Issuer"), "{out}");
    }

    #[test]
    fn verify_not_signed_kept() {
        let raw = "Error: no matching signatures:\nimage not signed\n";
        let out = compress_cosign("verify", raw);
        assert!(out.contains("Error") || out.contains("not signed"), "{out}");
    }

    #[test]
    fn sign_keeps_tlog_entry() {
        let raw = "Pushing signature to: gcr.io/my-project/my-image\ntlog entry created with index: 12345678\n";
        let out = compress_cosign("sign", raw);
        assert!(
            out.contains("tlog entry") || out.contains("signed") || out.contains("Pushing"),
            "{out}"
        );
    }
}
