use anyhow::Result;
use chrono::NaiveDate;
use colored::Colorize;
use crate::config::Config;
use crate::elements::{Element, ElementKind};
use crate::store::Store;
pub fn run(
config: &Config,
dates: Vec<NaiveDate>,
all: bool,
) -> Result<()> {
let store = Store::new(&config.storage_dir);
let effective_dates: Vec<NaiveDate> = if all {
store.all_file_dates()?
} else {
dates
};
let multi = effective_dates.len() > 1;
let mut grand_tasks = 0usize;
let mut grand_notes = 0usize;
let mut grand_reminders = 0usize;
let mut grand_logs = 0usize;
let mut grand_log_mins = 0i64;
let mut grand_characters = 0usize;
let mut any = false;
for d in &effective_dates {
let elements: Vec<Element> = store.parse_date(*d)?
.into_values()
.filter(|e| !e.is_mps_group() && !e.is_unknown())
.collect();
if elements.is_empty() { continue; }
any = true;
let tasks: Vec<&Element> = elements.iter().filter(|e| e.kind() == ElementKind::Task).collect();
let notes: usize = elements.iter().filter(|e| e.kind() == ElementKind::Note).count();
let reminders: usize = elements.iter().filter(|e| e.kind() == ElementKind::Reminder).count();
let logs: Vec<&Element> = elements.iter().filter(|e| e.kind() == ElementKind::Log).collect();
let characters: usize = elements.iter().filter(|e| e.kind() == ElementKind::Character).count();
let open_n = tasks.iter().filter(|e| {
if let Element::Task { data, .. } = e { data.is_open() } else { false }
}).count();
let done_n = tasks.len() - open_n;
let log_mins: i64 = logs.iter().map(|e| {
if let Element::Log { data, .. } = e { data.duration_minutes().unwrap_or(0) } else { 0 }
}).sum();
grand_tasks += tasks.len();
grand_notes += notes;
grand_reminders += reminders;
grand_logs += logs.len();
grand_log_mins += log_mins;
grand_characters += characters;
let mut parts: Vec<String> = Vec::new();
if !tasks.is_empty() {
let n = tasks.len();
parts.push(format!(
"{} task{} ({}, {})",
n,
if n != 1 { "s" } else { "" },
format!("{} open", open_n).yellow(),
format!("{} done", done_n).green()
));
}
if notes > 0 {
parts.push(format!("{} note{}", notes, if notes != 1 { "s" } else { "" }));
}
if reminders > 0 {
parts.push(format!("{} reminder{}", reminders, if reminders != 1 { "s" } else { "" }));
}
if !logs.is_empty() {
let n = logs.len();
let dur = format_duration(log_mins);
let dur_suffix = if dur.is_empty() { String::new() } else { format!(" ({})", dur) };
parts.push(format!("{} log{}{}", n, if n != 1 { "s" } else { "" }, dur_suffix));
}
if characters > 0 {
parts.push(format!("{} character{}", characters, if characters != 1 { "s" } else { "" }));
}
println!("{} — {}", d.format("%Y-%m-%d").to_string().white(), parts.join(", "));
}
if !any {
println!("{}", "(no data found)".yellow());
return Ok(());
}
if multi && any {
println!("{}", "─".repeat(44).white());
let mut tparts: Vec<String> = Vec::new();
if grand_tasks > 0 { tparts.push(format!("{} tasks", grand_tasks)); }
if grand_notes > 0 { tparts.push(format!("{} notes", grand_notes)); }
if grand_reminders > 0 { tparts.push(format!("{} reminders", grand_reminders)); }
if grand_logs > 0 {
let dur = format_duration(grand_log_mins);
let dur_suffix = if dur.is_empty() { String::new() } else { format!(" ({} total)", dur) };
tparts.push(format!("{} logs{}", grand_logs, dur_suffix));
}
if grand_characters > 0 { tparts.push(format!("{} characters", grand_characters)); }
println!("Total: {}", tparts.join(", "));
}
Ok(())
}
fn format_duration(mins: i64) -> String {
if mins <= 0 { return String::new(); }
let h = mins / 60;
let m = mins % 60;
if m > 0 { format!("{}h{}m", h, m) } else { format!("{}h", h) }
}