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

// Browser launch lines: "Using Chromium 120.0.0.0"
static BROWSER_INFO_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^(Using |Running \d+ test)[^\n]+\n?").unwrap());
// Passing test lines: "  ✓  tests/foo.spec.ts:12:3 › my test (234ms)"
static PASS_LINE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?m)^\s+✓\s+[^\n]+\n?").unwrap());
// Verbose retry lines
static RETRY_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^\s+(Retrying|retry \d+)[^\n]*\n?").unwrap());

pub fn compress_playwright(raw: &str, exit_code: i32) -> String {
    let cleaned = compactor::normalise(raw);
    let s = BROWSER_INFO_RE.replace_all(&cleaned, "");
    let s = RETRY_RE.replace_all(&s, "");

    if exit_code == 0 {
        // On success: keep summary lines only (passed/failed/skipped counts + timing)
        let kept: Vec<&str> = s
            .lines()
            .filter(|l| {
                let t = l.trim();
                t.contains("passed")
                    || t.contains("failed")
                    || t.contains("skipped")
                    || t.contains("Finished in")
                    || t.is_empty()
            })
            .collect();
        if !kept.is_empty() {
            return kept.join("\n");
        }
    }

    // On failure: strip passing tests, keep failures + tracebacks
    let s = PASS_LINE_RE.replace_all(&s, "");
    compactor::collapse_blanks(&s)
}

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

    #[test]
    fn success_strips_passing_tests() {
        let raw = "Running 3 tests using 1 worker\n  ✓  tests/a.spec.ts:1 › works (100ms)\n  ✓  tests/b.spec.ts:1 › also works (200ms)\n\n  3 passed (500ms)\n";
        let out = compress_playwright(raw, 0);
        assert!(out.contains("passed"), "{out}");
        assert!(!out.contains("✓  tests/a"), "{out}");
    }

    #[test]
    fn failure_keeps_error_output() {
        let raw = "  ✓  tests/a.spec.ts › passes\n  ✗  tests/b.spec.ts › fails\n    Error: expect(received).toBe(expected)\n  1 failed\n";
        let out = compress_playwright(raw, 1);
        assert!(out.contains("fails") || out.contains("Error"), "{out}");
        assert!(!out.contains("✓  tests/a"), "{out}");
    }
}
