use colored::Colorize;
use serde_json::{Map, Value};
use std::path::Path;

/// Compare old and new configs, print a change summary, return whether anything changed.
pub fn print_diff(client: &str, old: &Map<String, Value>, new: &Map<String, Value>) -> bool {
    let mut added: Vec<&str> = Vec::new();
    let mut updated: Vec<&str> = Vec::new();
    let mut unchanged: Vec<&str> = Vec::new();

    // Find added and updated entries.
    for (name, new_val) in new {
        match old.get(name) {
            None => added.push(name),
            Some(old_val) if old_val != new_val => updated.push(name),
            _ => unchanged.push(name),
        }
    }
    // Find removed entries.
    let removed: Vec<&str> = old
        .keys()
        .filter(|k| !new.contains_key(*k))
        .map(|k| k.as_str())
        .collect();

    let has_changes = !added.is_empty() || !removed.is_empty() || !updated.is_empty();

    println!("Syncing to {}...", client.bold());
    for name in &added {
        println!("  {}", format!("[+] added:     {}", name).green());
    }
    for name in &removed {
        println!("  {}", format!("[-] removed:   {}", name).red());
    }
    for name in &updated {
        println!("  {}", format!("[~] updated:   {}", name).yellow());
    }

    if unchanged.is_empty() && !has_changes {
        println!("  {}", "[=] no changes".dimmed());
        return has_changes;
    }
    if !unchanged.is_empty() {
        // Show up to 3, fold the rest.
        let show_count = unchanged.len().min(3);
        let shown = unchanged[..show_count].join(", ");
        let rest = unchanged.len() - show_count;
        let line = if rest > 0 {
            format!("[=] unchanged: {} ({} more...)", shown, rest)
        } else {
            format!("[=] unchanged: {}", shown)
        };
        println!("  {}", line.dimmed());
    }

    has_changes
}

/// Print the global config file path of a client.
pub fn print_config_path(path: &Path) {
    println!("  {}", format!("→ {}", path.display()).cyan());
}
