use crate::models::users::UserID;
use crate::schema::*;
use diesel::prelude::*;
use std::fmt::{Display, Formatter};

#[derive(
    Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord,
)]
pub struct AccountID(pub i32);

#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
pub enum AccountType {
    #[serde(rename = "C")]
    Cash,
    #[serde(rename = "B")]
    Bank,
    #[serde(rename = "S")]
    Saving,
}

impl Display for AccountType {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            serde_json::to_string(self).unwrap().replace('"', "")
        )
    }
}

#[derive(Queryable, Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Account {
    id: i32,
    pub name: String,
    user_id: i32,
    pub time_create: i64,
    pub time_update: i64,
    r#type: String,
    pub default_account: bool,
}

impl Account {
    pub fn id(&self) -> AccountID {
        AccountID(self.id)
    }

    pub fn user_id(&self) -> UserID {
        UserID(self.user_id)
    }

    pub fn account_type(&self) -> AccountType {
        serde_json::from_str(format!("\"{}\"", self.r#type).as_str()).unwrap()
    }

    pub fn set_account_type(&mut self, t: AccountType) {
        self.r#type = t.to_string();
    }
}

#[derive(Insertable, Debug)]
#[diesel(table_name = accounts)]
pub struct NewAccount<'a> {
    pub name: &'a str,
    pub user_id: i32,
    pub time_create: i64,
    pub time_update: i64,
    pub type_: String,
}
