use super::{Category, CategoryKind};

#[derive(Debug, Clone, PartialEq)]
pub struct CategoryValue {
    pub category_id: i64,
    pub category_name: String,
    pub kind: CategoryKind,
    pub numeric_value: Option<f64>,
    pub date_value: Option<String>,
    pub assignment: String,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Item {
    pub id: i64,
    pub text: String,
    pub note: String,
    pub priority: i64,
    pub when_at: Option<String>,
    pub done_at: Option<String>,
    pub alarm_at: Option<String>,
    pub numeric_value: Option<f64>,
    pub recurrence: String,
    pub created_at: String,
    pub updated_at: String,
    pub discarded: bool,
    pub categories: Vec<Category>,
    pub values: Vec<CategoryValue>,
}

impl Item {
    pub fn category_names(&self) -> String {
        self.categories
            .iter()
            .map(|category| category.name.as_str())
            .collect::<Vec<_>>()
            .join(", ")
    }

    pub fn numeric_value_for(&self, category: &str) -> Option<f64> {
        self.values
            .iter()
            .find(|value| {
                value.kind == CategoryKind::Numeric
                    && value.category_name.eq_ignore_ascii_case(category)
                    && self
                        .categories
                        .iter()
                        .any(|assigned| assigned.id == value.category_id)
            })
            .and_then(|value| value.numeric_value)
    }

    pub fn date_value_for(&self, category: &str) -> Option<&str> {
        self.values
            .iter()
            .find(|value| {
                value.kind == CategoryKind::Date
                    && value.category_name.eq_ignore_ascii_case(category)
                    && self
                        .categories
                        .iter()
                        .any(|assigned| assigned.id == value.category_id)
            })
            .and_then(|value| value.date_value.as_deref())
    }
}

#[derive(Debug, Clone, Default)]
pub struct ItemChanges {
    pub text: Option<String>,
    pub note: Option<String>,
    pub priority: Option<i64>,
    pub when_at: Option<Option<String>>,
    pub alarm_at: Option<Option<String>>,
    pub numeric_value: Option<Option<f64>>,
    pub recurrence: Option<String>,
}
