use std::collections::HashMap;

use config::Value;
use serde_json::Value as JsonValue;

pub(crate) fn json_to_config_value(v: &JsonValue) -> Value {
    match v {
        JsonValue::Null => Value::from(None::<String>),
        JsonValue::Bool(b) => Value::from(*b),
        JsonValue::Number(n) => {
            if let Some(i) = n.as_i64() {
                Value::from(i)
            } else if let Some(f) = n.as_f64() {
                Value::from(f)
            } else {
                Value::from(n.to_string())
            }
        }
        JsonValue::String(s) => Value::from(s.clone()),
        JsonValue::Array(_) | JsonValue::Object(_) => {
            panic!("json_to_config_value called on complex type")
        }
    }
}

pub(crate) fn flatten_json(prefix: &str, value: &JsonValue, out: &mut HashMap<String, Value>) {
    match value {
        JsonValue::Object(map) => {
            for (k, v) in map {
                let new_key = if prefix.is_empty() {
                    k.clone()
                } else {
                    format!("{}.{}", prefix, k)
                };
                flatten_json(&new_key, v, out);
            }
        }
        JsonValue::Array(arr) => {
            for (i, v) in arr.iter().enumerate() {
                let new_key = if prefix.is_empty() {
                    i.to_string()
                } else {
                    format!("{}.{}", prefix, i)
                };
                flatten_json(&new_key, v, out);
            }
        }
        _ => {
            out.insert(prefix.to_string(), json_to_config_value(value));
        }
    }
}
