use super::type_badge;
use crate::config::Config;
use crate::elements::ElementKind;
use crate::store::Store;
use anyhow::{bail, Result};
use chrono::NaiveDate;
use colored::Colorize;

const VALID_TYPES: &[&str] = &["task", "note", "log", "reminder", "character"];

#[allow(clippy::too_many_arguments)]
pub fn run(
    config: &Config,
    kind: &str,
    body: &str,
    tags: Vec<String>,
    status: Option<String>,
    at: Option<String>,
    start_time: Option<String>,
    end_time: Option<String>,
    name: Option<String>,
    date: NaiveDate,
) -> Result<()> {
    let kind = kind.to_lowercase();
    if !VALID_TYPES.contains(&kind.as_str()) {
        bail!("Unknown type '{}'. Valid: {}", kind, VALID_TYPES.join(", "));
    }

    let mut attrs: Vec<(&str, String)> = Vec::new();
    if let Some(ref s) = status {
        attrs.push(("status", s.clone()));
    }
    if let Some(ref a) = at {
        attrs.push(("at", a.clone()));
    }
    if let Some(ref s) = start_time {
        attrs.push(("start", s.clone()));
    }
    if let Some(ref e) = end_time {
        attrs.push(("end", e.clone()));
    }
    if let Some(ref n) = name {
        attrs.push(("name", n.clone()));
    }

    let attrs_ref: Vec<(&str, &str)> = attrs.iter().map(|(k, v)| (*k, v.as_str())).collect();

    let store = Store::new(&config.storage_dir);
    store.append(&kind, body, &tags, &attrs_ref, date)?;

    let ek = ElementKind::from_sign(&kind);
    println!("  {} {} {}", "appended".green(), type_badge(&ek), body);
    Ok(())
}
