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

static PASS_LINE_RE: Lazy<Regex> = Lazy::new(||
    // pytest: "PASSED src/test_foo.py::test_bar" — strip on success
    Regex::new(r"(?m)^PASSED [^\n]+\n?").unwrap());
static DOTS_RE: Lazy<Regex> = Lazy::new(||
    // pytest -v dots: "....F...."
    Regex::new(r"(?m)^[\.FEsxX]{4,}\n?").unwrap());
static COLLECTED_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^collected \d+ items?[^\n]*\n?").unwrap());

pub fn compress_pytest(raw: &str, exit_code: i32) -> String {
    let cleaned = compactor::normalise(raw);
    let s = COLLECTED_RE.replace_all(&cleaned, "");
    if exit_code == 0 {
        // Keep only summary line
        let out: Vec<&str> = s
            .lines()
            .filter(|l| l.starts_with("=") || l.contains(" passed"))
            .collect();
        return if out.is_empty() {
            s.into_owned()
        } else {
            out.join("\n")
        };
    }
    // Failure: strip PASSED lines, keep FAILED + tracebacks + summary
    let s = PASS_LINE_RE.replace_all(&s, "");
    let s = DOTS_RE.replace_all(&s, "");
    compactor::collapse_blanks(&s)
}

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

    #[test]
    fn pytest_success_keeps_summary() {
        let raw = "collected 5 items\nPASSED test_foo.py::test_a\nPASSED test_foo.py::test_b\n===== 5 passed in 0.12s =====\n";
        let out = compress_pytest(raw, 0);
        assert!(!out.contains("PASSED test_foo"), "{out}");
        assert!(out.contains("5 passed"), "{out}");
    }

    #[test]
    fn pytest_failure_strips_passing_keeps_failed() {
        let raw = "PASSED test_foo.py::test_a\nFAILED test_foo.py::test_b - AssertionError\n===== 1 failed, 1 passed =====\n";
        let out = compress_pytest(raw, 1);
        assert!(!out.contains("PASSED test_foo"), "{out}");
        assert!(out.contains("FAILED"), "{out}");
    }
}
