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

// Flyway ASCII banner lines (start with a box-drawing char or "Flyway")
static BANNER_RE: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"(?m)^(?:Flyway(?:\s+Community)?[^\n]*\n|[+\-|]+\n|_{10,}\n)").unwrap()
});
// "Database: jdbc:postgresql://localhost:5432/mydb (PostgreSQL 14.5)"
static DB_CONN_RE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"(?m)^Database: jdbc:[^\n]+\n?").unwrap());
// "Successfully validated N migrations" / "Schema version: X"
// These are signal — kept intentionally.

// ── flyway migrate ────────────────────────────────────────────────────────────

pub fn compress_migrate(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = BANNER_RE.replace_all(&cleaned, "");
    let s = DB_CONN_RE.replace_all(&s, "");
    let useful: Vec<&str> = s
        .lines()
        .filter(|l| {
            let t = l.trim();
            !t.is_empty()
                && (t.contains("Migrating schema")
                    || t.contains("Successfully applied")
                    || t.contains("Successfully validated")
                    || t.contains("Schema version")
                    || t.contains("No migration")
                    || t.contains("ERROR")
                    || t.contains("error")
                    || t.contains("FAILED")
                    || t.contains("V") && t.contains("__"))
        })
        .collect();
    if useful.is_empty() {
        return compactor::collapse_blanks(&s);
    }
    useful.join("\n")
}

// ── flyway info ───────────────────────────────────────────────────────────────

pub fn compress_info(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = BANNER_RE.replace_all(&cleaned, "");
    let s = DB_CONN_RE.replace_all(&s, "");
    // Keep table rows (version, description, type, state)
    let lines: Vec<&str> = s.lines().filter(|l| !l.trim().is_empty()).collect();
    if lines.len() > 30 {
        return format!(
            "{}\n… [{} more migrations]",
            lines[..30].join("\n"),
            lines.len() - 30
        );
    }
    lines.join("\n")
}

// ── flyway validate / repair ──────────────────────────────────────────────────

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

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

pub fn compress_flyway(subcmd: &str, raw: &str) -> String {
    let sub = subcmd.trim();
    if sub.starts_with("migrate") {
        return compress_migrate(raw);
    }
    if sub.starts_with("info") {
        return compress_info(raw);
    }
    if sub.starts_with("validate") || sub.starts_with("repair") {
        return compress_validate(raw);
    }
    // baseline / clean / undo
    let cleaned = compactor::normalise(raw);
    let s = BANNER_RE.replace_all(&cleaned, "");
    let s = DB_CONN_RE.replace_all(&s, "");
    compactor::collapse_blanks(&s)
}

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

    #[test]
    fn migrate_strips_banner_and_keeps_migrations() {
        let raw = "Flyway Community Edition 9.22.3 by Redgate\n____________________________\nDatabase: jdbc:postgresql://localhost:5432/mydb (PostgreSQL 14.5)\nSuccessfully validated 3 migrations (execution time 00:00.025s)\nCurrent version of schema \"public\": 2\nMigrating schema \"public\" to version \"3 - add orders table\" [V3__add_orders_table.sql]\nSuccessfully applied 1 migration to schema \"public\", now at version v3 (execution time 00:00.123s)\n";
        let out = compress_flyway("migrate", raw);
        assert!(!out.contains("Flyway Community"), "{out}");
        assert!(!out.contains("jdbc:postgresql"), "{out}");
        assert!(
            out.contains("Successfully applied") || out.contains("Migrating schema"),
            "{out}"
        );
    }

    #[test]
    fn info_truncates_long_history() {
        let mut lines = vec![
            "+-----------+---------+---------------------+------+---------------------+---------+"
                .to_string(),
        ];
        for i in 0..35 {
            lines.push(format!("| {i:<9} | migrate | V{i}__migration.sql  | SQL  | 2024-01-{i:02} 00:00:00 | Success |"));
        }
        let out = compress_info(&lines.join("\n"));
        assert!(out.contains("more migrations"), "{out}");
    }
}
