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

static PASS_SUITE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?m)^  ✓ [^\n]+\n?").unwrap());
static CONSOLE_LOG_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^\s+console\.(log|warn|info|debug)[^\n]+\n?").unwrap());
#[allow(dead_code)]
static TIMING_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^\s+at [^\n]+ \(\d+ms\)\n?").unwrap());

pub fn compress_jest(raw: &str, exit_code: i32) -> String {
    let cleaned = compactor::normalise(raw);
    let s = CONSOLE_LOG_RE.replace_all(&cleaned, "");
    if exit_code == 0 {
        // Keep only PASS/FAIL suite lines and summary
        let out: Vec<&str> = s
            .lines()
            .filter(|l| {
                l.starts_with("PASS ")
                    || l.starts_with("FAIL ")
                    || l.starts_with("Tests:")
                    || l.starts_with("Test Suites:")
                    || l.starts_with("Snapshots:")
                    || l.starts_with("Time:")
            })
            .collect();
        return if out.is_empty() {
            s.into_owned()
        } else {
            out.join("\n")
        };
    }
    // Failure: strip passing individual test lines, keep failures + summary
    let s = PASS_SUITE_RE.replace_all(&s, "");
    compactor::collapse_blanks(&s)
}

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

    #[test]
    fn jest_success_keeps_suite_summary() {
        let raw = "PASS src/__tests__/foo.test.ts\n  ✓ test one (5ms)\n  ✓ test two (3ms)\nTests: 2 passed, 2 total\nTest Suites: 1 passed, 1 total\n";
        let out = compress_jest(raw, 0);
        assert!(!out.contains("✓ test one"), "{out}");
        assert!(out.contains("Tests: 2 passed"), "{out}");
    }

    #[test]
    fn jest_failure_strips_console_noise() {
        let raw = "FAIL src/__tests__/bar.test.ts\n  console.log debug stuff\n  ✕ failing test\nTests: 1 failed, 1 total\n";
        let out = compress_jest(raw, 1);
        assert!(!out.contains("console.log"), "{out}");
        assert!(out.contains("1 failed"), "{out}");
    }
}
