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

static DOWNLOAD_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^Download https?://[^\n]+\n?").unwrap());
static CHECK_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^Check (file|https?):[^\n]+\n?").unwrap());

pub fn compress_cache(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = DOWNLOAD_RE.replace_all(&cleaned, "");
    let s = CHECK_RE.replace_all(&s, "");
    compactor::collapse_blanks(&s)
}

pub fn compress_test(raw: &str, exit_code: i32) -> String {
    let cleaned = compactor::normalise(raw);
    let s = DOWNLOAD_RE.replace_all(&cleaned, "");
    let s = CHECK_RE.replace_all(&s, "");
    if exit_code == 0 {
        // Keep "ok | N passed (N steps)"
        let kept: Vec<&str> = s
            .lines()
            .filter(|l| l.contains("passed") || l.contains("failed") || l.contains("ok |"))
            .collect();
        if !kept.is_empty() {
            return kept.join("\n");
        }
    }
    // Keep failures
    s.lines()
        .filter(|l| !l.trim().starts_with("ok"))
        .collect::<Vec<_>>()
        .join("\n")
}

pub fn compress_deno(subcmd: &str, raw: &str, exit_code: i32) -> String {
    let sub = subcmd.trim();
    match sub {
        "cache" | "install" => compress_cache(raw),
        "test" => compress_test(raw, exit_code),
        "compile" | "bundle" => {
            let cleaned = compactor::normalise(raw);
            let s = DOWNLOAD_RE.replace_all(&cleaned, "");
            compactor::collapse_blanks(&s)
        }
        _ => compactor::normalise(raw),
    }
}

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

    #[test]
    fn cache_strips_downloads() {
        let raw = "Download https://deno.land/x/oak@v12.0.0/mod.ts\nDownload https://deno.land/std@0.200.0/http/server.ts\n";
        let out = compress_cache(raw);
        assert!(!out.contains("Download https://"), "{out}");
    }

    #[test]
    fn test_success_keeps_summary() {
        let raw = "Check file:///project/test.ts\nrunning 3 tests from ./test.ts\nok | 3 passed (5 steps)\n";
        let out = compress_test(raw, 0);
        assert!(out.contains("passed"), "{out}");
        assert!(!out.contains("Check file://"), "{out}");
    }
}
