tod 0.12.0

An unofficial Todoist command-line client
use std::fmt::Display;

use crate::{config::Config, errors::Error, todoist};
use serde::Deserialize;

#[derive(Deserialize, Debug, PartialEq, Eq)]
pub struct Label {
    pub id: String,
    pub name: String,
    pub color: String,
    pub order: Option<u32>,
    pub is_favorite: bool,
}

#[allow(dead_code)]
#[derive(Deserialize)]
pub struct LabelResponse {
    pub results: Vec<Label>,
    pub next_cursor: Option<String>,
}

impl Display for Label {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let name = self.name.clone();
        write!(f, "{name}")
    }
}
pub async fn get_labels(config: &Config, spinner: bool) -> Result<Vec<Label>, Error> {
    todoist::all_labels(config, spinner, None).await
}

pub fn json_to_labels_response(json: &str) -> Result<LabelResponse, Error> {
    let response: LabelResponse = serde_json::from_str(json)?;
    Ok(response)
}

#[cfg(test)]
mod tests {
    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn test_label_fmt() {
        let label = Label {
            id: "1".to_string(),
            name: "work".to_string(),
            color: "red".to_string(),
            order: Some(1),
            is_favorite: false,
        };
        assert_eq!(label.to_string(), "work");
    }

    #[test]
    fn test_json_to_labels_response_valid() {
        let json = r#"{"results":[{"id":"1","name":"work","color":"red","order":1,"is_favorite":false}],"next_cursor":null}"#;
        let response = json_to_labels_response(json).expect("should parse labels response");
        assert_eq!(response.results.len(), 1);
        assert_eq!(response.results[0].name, "work");
        assert_eq!(response.results[0].color, "red");
        assert!(response.next_cursor.is_none());
    }

    #[test]
    fn test_json_to_labels_response_with_cursor() {
        let json = r#"{"results":[],"next_cursor":"abc123"}"#;
        let response =
            json_to_labels_response(json).expect("should parse labels response with cursor");
        assert!(response.results.is_empty());
        assert_eq!(response.next_cursor, Some("abc123".to_string()));
    }

    #[test]
    fn test_json_to_labels_response_invalid() {
        let result = json_to_labels_response("not json");
        assert!(result.is_err());
    }
}