git-intelligence-message 2.1.3

An advanced Git commit message generation utility with AI assistance
use std::{fmt::Display, str::FromStr};

use chrono::{Local, NaiveDate};
use gim_config::config::{get_config, update_config_value};
use serde::{Deserialize, Serialize};
use toml::Value;

const UPDATE_SECTION: &str = "update";

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UpdateReminder {
    last_update_check: NaiveDate,
    reminder_count: u32,
    max_try_count: u32,
    max_check_interval: u32,
}

impl Display for UpdateReminder {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "last_update_check: {}, reminder_count: {}/{}, check_interval: {} days",
            self.last_update_check,
            self.reminder_count,
            self.max_try_count,
            self.max_check_interval
        )
    }
}

impl Default for UpdateReminder {
    fn default() -> Self {
        let last_update_check = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap();
        Self {
            last_update_check,
            reminder_count: 0,
            max_try_count: 5,
            max_check_interval: 30,
        }
    }
}

impl UpdateReminder {
    pub fn load() -> Self {
        let config = get_config().unwrap();
        let mut remider = UpdateReminder::default();
        if let Some(update) = config.get(UPDATE_SECTION) {
            if let Some(tried) = update.get("tried") {
                remider.reminder_count = tried.as_integer().unwrap() as u32;
            }
            if let Some(max_try) = update.get("max_try") {
                remider.max_try_count = max_try.as_integer().unwrap() as u32;
            }
            if let Some(interval) = update.get("try_interval_days") {
                remider.max_check_interval = interval.as_integer().unwrap() as u32;
            }
            if let Some(last_check) = update.get("last_try_day") {
                remider.last_update_check =
                    NaiveDate::from_str(last_check.as_str().unwrap()).unwrap();
            }
        }
        remider
    }

    pub fn save(&self) -> std::io::Result<()> {
        update_config_value(
            UPDATE_SECTION,
            "tried",
            Value::Integer(self.reminder_count as i64),
        )?;
        update_config_value(
            UPDATE_SECTION,
            "last_try_day",
            Value::String(self.last_update_check.to_string()),
        )?;
        Ok(())
    }

    pub fn should_show_reminder(&self) -> bool {
        let today = Local::now().date_naive();
        let days_since_last_check = today
            .signed_duration_since(self.last_update_check)
            .num_days();

        days_since_last_check >= self.max_check_interval as i64
            && self.reminder_count < self.max_try_count
    }

    pub fn increment_reminder_count(&mut self) -> std::io::Result<()> {
        let should_reset = self.reminder_count >= self.max_try_count - 1;

        if should_reset {
            self.reset_reminder()
        } else {
            self.reminder_count += 1;
            self.save()
        }
    }

    pub fn reset_reminder(&mut self) -> std::io::Result<()> {
        self.last_update_check = Local::now().date_naive();
        self.reminder_count = 0;
        self.save()
    }
}