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

// "  - Downloading vendor/package (1.2.3)"
static DOWNLOAD_RE: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"(?m)^\s+- (Downloading|Installing|Upgrading|Removing) [^\n]+\n?").unwrap()
});
static LOCK_WRITING_RE: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"(?m)^(Writing lock file|Generating optimized autoload files|Generated optimized autoload files)[^\n]*\n?").unwrap()
});

// ── composer install / update ─────────────────────────────────────────────────

pub fn compress_install(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = DOWNLOAD_RE.replace_all(&cleaned, "");
    let s = LOCK_WRITING_RE.replace_all(&s, "");
    // Keep: "Package operations:", errors, security warnings
    let kept: Vec<&str> = s
        .lines()
        .filter(|l| {
            let t = l.trim();
            t.is_empty()
                || t.starts_with("Package operations:")
                || t.contains("packages")
                || t.contains("Nothing to install")
                || t.contains("error")
                || t.starts_with("Warning")
                || t.contains("security")
        })
        .collect();
    if kept.is_empty() {
        return compactor::collapse_blanks(&s);
    }
    kept.join("\n")
}

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

// ── artisan (Laravel) ─────────────────────────────────────────────────────────

pub fn compress_artisan(subcmd: &str, raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let sub = subcmd.trim();
    if sub.starts_with("migrate") {
        // Keep table of applied migrations, strip banner
        let lines: Vec<&str> = cleaned
            .lines()
            .filter(|l| !l.contains("migrations table") && !l.trim().is_empty())
            .collect();
        return lines.join("\n");
    }
    // Generic: truncate if large
    let lines: Vec<&str> = cleaned.lines().collect();
    if lines.len() > 40 {
        return format!(
            "{}\n... [{} more lines] ...",
            lines[..40].join("\n"),
            lines.len() - 40
        );
    }
    cleaned
}

pub fn compress_composer(subcmd: &str, raw: &str) -> String {
    let sub = subcmd.trim();
    match sub {
        "install" | "update" | "i" | "u" => compress_install(raw),
        "require" | "remove" => compress_require(raw),
        _ => compactor::normalise(raw),
    }
}

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

    #[test]
    fn install_strips_download_lines() {
        let raw = "  - Downloading vendor/foo (1.2.3)\n  - Installing vendor/foo (1.2.3): OK\nPackage operations: 1 install, 0 updates, 0 removals\n";
        let out = compress_install(raw);
        assert!(!out.contains("Downloading vendor/foo"), "{out}");
        assert!(out.contains("Package operations"), "{out}");
    }

    #[test]
    fn install_strips_lock_writing() {
        let raw = "Writing lock file\nGenerating optimized autoload files\nPackage operations: 0 installs, 0 updates, 0 removals\n";
        let out = compress_install(raw);
        assert!(!out.contains("Writing lock file"), "{out}");
    }
}
