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

static DOWNLOAD_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^Downloading (chart|repository)[^\n]+\n?").unwrap());
#[allow(dead_code)]
static MANIFEST_VERBOSE_RE: Lazy<Regex> = Lazy::new(||
    // Strip long verbose manifest blocks: "---\n# Source: chart/templates/..."
    Regex::new(r"(?ms)^---\n# Source: [^\n]+\n").unwrap());
static STATUS_DETAIL_RE: Lazy<Regex> = Lazy::new(||
    // Strips verbose Notes: section boilerplate (up to next blank line or end)
    Regex::new(r"(?m)^NOTES:\n(?:[^\n]+\n)*").unwrap());

// ── helm install / upgrade ────────────────────────────────────────────────────

pub fn compress_install(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = DOWNLOAD_RE.replace_all(&cleaned, "");
    // Keep: NAME/LAST DEPLOYED/STATUS/REVISION lines + errors
    let kept: Vec<&str> = s
        .lines()
        .filter(|l| {
            let t = l.trim();
            t.is_empty()
                || t.starts_with("NAME:")
                || t.starts_with("LAST DEPLOYED:")
                || t.starts_with("NAMESPACE:")
                || t.starts_with("STATUS:")
                || t.starts_with("REVISION:")
                || t.starts_with("DESCRIPTION:")
                || t.contains("Error")
                || t.contains("error")
                || t.contains("FAILED")
                || t.starts_with("Release") // "Release 'name' has been upgraded"
        })
        .collect();
    if kept.is_empty() {
        return compactor::collapse_blanks(&s);
    }
    kept.join("\n")
}

// ── helm list ─────────────────────────────────────────────────────────────────

pub fn compress_list(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    // Keep table as-is but truncate at 30 rows
    let lines: Vec<&str> = cleaned.lines().filter(|l| !l.trim().is_empty()).collect();
    if lines.len() > 31 {
        return format!(
            "{}\n... [{} more releases] ...",
            lines[..31].join("\n"),
            lines.len() - 31
        );
    }
    cleaned
}

// ── helm status ───────────────────────────────────────────────────────────────

pub fn compress_status(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    // Strip the NOTES: boilerplate that echoes chart instructions
    let s = STATUS_DETAIL_RE.replace_all(&cleaned, "");
    compactor::collapse_blanks(&s)
}

// ── helm diff (plugin) ────────────────────────────────────────────────────────

pub fn compress_diff(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    // Keep only changed lines (+/-), strip context lines
    let diffs: Vec<&str> = cleaned
        .lines()
        .filter(|l| {
            l.starts_with('+') || l.starts_with('-') || l.starts_with("---") || l.starts_with("+++")
        })
        .take(100)
        .collect();
    if diffs.is_empty() {
        return cleaned;
    }
    diffs.join("\n")
}

// ── top-level dispatcher ──────────────────────────────────────────────────────

pub fn compress_helm(subcmd: &str, raw: &str) -> String {
    let sub = subcmd.trim();
    if sub.starts_with("install") || sub.starts_with("upgrade") || sub.starts_with("rollback") {
        return compress_install(raw);
    }
    if sub.starts_with("list") || sub.starts_with("ls") {
        return compress_list(raw);
    }
    if sub.starts_with("status") {
        return compress_status(raw);
    }
    if sub.starts_with("diff") {
        return compress_diff(raw);
    }
    // repo add/update, get, show — truncate if large
    let cleaned = compactor::normalise(raw);
    let lines: Vec<&str> = cleaned.lines().collect();
    if lines.len() > 40 {
        return format!(
            "{}\n... [{} more lines] ...",
            lines[..40].join("\n"),
            lines.len() - 40
        );
    }
    cleaned
}

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

    #[test]
    fn install_keeps_status_lines() {
        let raw = "NAME: my-release\nLAST DEPLOYED: Mon Jan 1 00:00:00 2024\nNAMESPACE: default\nSTATUS: deployed\nREVISION: 1\n";
        let out = compress_install(raw);
        assert!(out.contains("STATUS:"), "{out}");
        assert!(out.contains("REVISION:"), "{out}");
    }

    #[test]
    fn list_truncates_many_releases() {
        let header = "NAME\tNAMESPACE\tREVISION\tSTATUS\n";
        let rows: String = (0..35)
            .map(|i| format!("rel-{i}\tdefault\t1\tdeployed\n"))
            .collect();
        let out = compress_list(&format!("{header}{rows}"));
        assert!(out.contains("more releases"), "{out}");
    }

    #[test]
    fn install_strips_download_lines() {
        let raw = "Downloading chart from https://charts.example.com/chart-1.0.0.tgz\nNAME: app\nSTATUS: deployed\n";
        let out = compress_install(raw);
        assert!(!out.contains("Downloading chart"), "{out}");
        assert!(out.contains("deployed"), "{out}");
    }
}
