use serde_json::{Map, Value};
use super::format;
use super::sections::{ContentsSection, Section};
const COL_NAME: &str = "Name";
#[must_use]
pub fn sheet_stats_to_section(section_key: &str, obj: &Map<String, Value>) -> Section {
let data_keys: Vec<String> = obj
.values()
.find_map(|v| v.as_object())
.map(|o| o.keys().cloned().collect())
.unwrap_or_default();
let column_keys: Vec<String> = std::iter::once(COL_NAME.to_string())
.chain(data_keys.clone())
.collect();
let columns: Vec<String> = column_keys.iter().map(|k| format::format_key(k)).collect();
let mut entries: Vec<Value> = Vec::new();
for (name, v) in obj {
let Some(sub) = v.as_object() else {
continue;
};
let mut row = serde_json::Map::new();
row.insert(COL_NAME.to_string(), Value::String(name.clone()));
for key in &data_keys {
let val = sub.get(key).cloned().unwrap_or(Value::Null);
row.insert(key.clone(), val);
}
entries.push(Value::Object(row));
}
Section::Contents(ContentsSection {
title: format::format_key(section_key),
columns,
column_keys,
entries,
sub_title: false,
})
}
#[must_use]
pub fn is_sheet_stats(obj: &Map<String, Value>) -> bool {
let mut it = obj.values();
let Some(first) = it.next() else {
return false;
};
let Some(sub) = first.as_object() else {
return false;
};
sub.contains_key("rows") && sub.contains_key("columns")
}