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

static SPINNER_RE: Lazy<Regex> = Lazy::new(||
    // Strip spinner frames and "Loading prisma client" lines
    Regex::new(r"(?m)^(⠋|⠙|⠹|⠸|⠼|⠴|⠦|⠧|⠇|⠏|Prisma schema loaded from|Environment variables loaded)[^\n]*\n?").unwrap());
static MIGRATION_PROGRESS_RE: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"(?m)^The following migration\(s\) have been applied:[^\n]*\n?").unwrap()
});

pub fn compress_migrate(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = SPINNER_RE.replace_all(&cleaned, "");
    // Keep: migration names, "Database is now in sync", errors, warnings
    let kept: Vec<&str> = s
        .lines()
        .filter(|l| {
            let t = l.trim();
            !t.is_empty()
                && (t.starts_with("migrations/")
                    || t.contains("applied")
                    || t.contains("in sync")
                    || t.contains("error")
                    || t.contains("Error")
                    || t.contains("warn")
                    || t.contains("Generated")
                    || t.starts_with("✔")
                    || t.starts_with("✗")
                    || t.starts_with("➜"))
        })
        .collect();
    if kept.is_empty() {
        return compactor::collapse_blanks(&s);
    }
    kept.join("\n")
}

pub fn compress_generate(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let s = SPINNER_RE.replace_all(&cleaned, "");
    // Keep "Generated Prisma Client" line and timing
    let kept: Vec<&str> = s
        .lines()
        .filter(|l| {
            let t = l.trim();
            !t.is_empty()
                && (t.contains("Generated Prisma Client")
                    || t.contains("Start by importing")
                    || t.contains("error")
                    || t.starts_with("✔"))
        })
        .collect();
    if kept.is_empty() {
        return compactor::collapse_blanks(&s);
    }
    kept.join("\n")
}

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

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

pub fn compress_prisma(subcmd: &str, raw: &str) -> String {
    let sub = subcmd.trim();
    if sub.starts_with("migrate") {
        return compress_migrate(raw);
    }
    if sub.starts_with("generate") {
        return compress_generate(raw);
    }
    if sub.starts_with("db push") {
        return compress_db_push(raw);
    }
    // studio / validate / format — normalise only
    compactor::normalise(raw)
}

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

    #[test]
    fn generate_keeps_generated_line() {
        let raw = "Prisma schema loaded from prisma/schema.prisma\n✔ Generated Prisma Client (5.0.0) to ./node_modules/@prisma/client in 234ms\n";
        let out = compress_generate(raw);
        assert!(out.contains("Generated Prisma Client"), "{out}");
        assert!(!out.contains("schema loaded"), "{out}");
    }

    #[test]
    fn migrate_keeps_migration_names() {
        let raw = "Prisma schema loaded from prisma/schema.prisma\n✔ migrations/20240101_init.sql\nYour database is now in sync with your schema.\n";
        let out = compress_migrate(raw);
        assert!(out.contains("in sync") || out.contains("20240101"), "{out}");
    }
}
