//! JSON wrapper around `car-health` for CLI/bindings/server.
//!
//! Error codes: `unavailable`, `backend`, `not_implemented`, `parse`.

use chrono::{DateTime, NaiveDate, Utc};
use serde_json::{json, Value};

fn err_json(e: car_health::HealthError) -> String {
    use car_health::HealthError::*;
    let code = match &e {
        Unavailable(_) => "unavailable",
        Backend(_) => "backend",
        NotImplemented(_) => "not_implemented",
    };
    json!({"code": code, "message": e.to_string()}).to_string()
}

fn val_err(e: impl std::fmt::Display) -> String {
    json!({"code": "backend", "message": e.to_string()}).to_string()
}

pub fn status() -> Result<Value, String> {
    let r = car_health::status().map_err(err_json)?;
    serde_json::to_value(&r).map_err(val_err)
}

pub fn sleep_windows(start: DateTime<Utc>, end: DateTime<Utc>) -> Result<Value, String> {
    let r = car_health::sleep_windows(start, end).map_err(err_json)?;
    serde_json::to_value(&r).map_err(val_err)
}

pub fn workouts(start: DateTime<Utc>, end: DateTime<Utc>) -> Result<Value, String> {
    let r = car_health::workouts(start, end).map_err(err_json)?;
    serde_json::to_value(&r).map_err(val_err)
}

pub fn activity(start: NaiveDate, end: NaiveDate) -> Result<Value, String> {
    let r = car_health::activity(start, end).map_err(err_json)?;
    serde_json::to_value(&r).map_err(val_err)
}
