use serde_json::Value;
use std::collections::BTreeSet;

/// Formats a JSON Value into a Markdown string with intelligent rendering strategies.
pub fn format_data(data: &Value) -> String {
    match data {
        Value::Object(map) => {
            // Heuristic: If it looks like a "summary" object with a "records" array, 
            // likely the "records" are the main content.
            if map.len() <= 3 && map.contains_key("records") && map["records"].is_array() {
                let mut md = String::new();
                // Render non-records fields first
                for (k, v) in map {
                    if k != "records" {
                        md.push_str(&format!("**{}:** {}\n\n", k, format_primitive(v)));
                    }
                }
                md.push_str(&format_table(&map["records"]));
                return md;
            }

            // Default Object rendering
            let mut md = String::new();
            for (k, v) in map {
                md.push_str(&format!("### {}\n\n", k));
                md.push_str(&format_data(v));
                md.push_str("\n\n");
            }
            md
        },
        Value::Array(arr) => {
            if arr.is_empty() {
                return "_No Data_".to_string();
            }
            // Check if array of objects (Table candidate)
            if arr.iter().all(|v| v.is_object()) {
                return format_table(data);
            }
            // Simple list
            let mut md = String::new();
            for item in arr {
                md.push_str(&format!("- {}\n", format_primitive(item)));
            }
            md
        },
        _ => format_primitive(data),
    }
}

fn format_primitive(v: &Value) -> String {
    match v {
        Value::String(s) => s.clone(),
        Value::Number(n) => n.to_string(),
        Value::Bool(b) => b.to_string(),
        Value::Null => "null".to_string(),
        _ => format!("`{}`", v),
    }
}

fn format_table(data: &Value) -> String {
    let arr = data.as_array().unwrap();
    if arr.is_empty() {
        return "".to_string();
    }

    // Collect all unique keys for headers
    let mut keys: BTreeSet<String> = BTreeSet::new();
    for item in arr {
        if let Value::Object(map) = item {
            for k in map.keys() {
                keys.insert(k.clone());
            }
        }
    }

    if keys.is_empty() {
        return "".to_string();
    }

    let header_list: Vec<String> = keys.into_iter().collect();
    
    let mut md = String::new();
    
    // Header Row
    md.push_str("| ");
    md.push_str(&header_list.join(" | "));
    md.push_str(" |\n");

    // Separator Row
    md.push_str("|");
    for _ in 0..header_list.len() {
        md.push_str(" --- |");
    }
    md.push_str("\n");

    // Data Rows
    for item in arr {
        let map = item.as_object().unwrap();
        md.push_str("|");
        for key in &header_list {
            let val = map.get(key).unwrap_or(&Value::Null);
            // Truncate long values for table
            let mut val_str = format_primitive(val);
            val_str = val_str.replace('\n', " "); // No newlines in table cells
            if val_str.len() > 50 {
                val_str = format!("{}...", &val_str[0..47]);
            }
            md.push_str(&format!(" {} |", val_str));
        }
        md.push_str("\n");
    }

    md
}

