use crate::models::accounts::AccountID;
use crate::models::files::FileID;
use crate::schema::*;
use diesel::{Insertable, Queryable, QueryableByName};

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

/// Single movement information
#[derive(Queryable, QueryableByName, Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Movement {
    /// The ID of the movement
    id: i32,
    /// The ID of the account this movement is attached to
    account_id: i32,
    /// The time this movement happened
    pub time: i64,
    /// The label associated to this movement
    pub label: String,
    /// ID of the file attached to this movement (if any)
    file_id: Option<i32>,
    /// The amount of the movement
    pub amount: f32,
    /// Checkbox presented to the user (no impact on code logic)
    pub checked: bool,
    /// The time this movement was created in the database
    pub time_create: i64,
    /// The time this movement was last updated in the database
    pub time_update: i64,
}

impl Movement {
    /// Get the ID of the movement
    pub fn id(&self) -> MovementID {
        MovementID(self.id)
    }

    /// The ID of the account attached to the movement
    pub fn account_id(&self) -> AccountID {
        AccountID(self.account_id)
    }

    /// The ID of the file attached to the movement, if any
    pub fn file_id(&self) -> Option<FileID> {
        self.file_id.map(FileID)
    }
}

#[derive(Insertable, Debug)]
#[diesel(table_name = movements)]
pub struct NewMovement<'a> {
    pub account_id: i32,
    pub time: i64,
    pub label: &'a str,
    pub file_id: Option<i32>,
    pub amount: f32,
    pub checked: bool,
    pub time_create: i64,
    pub time_update: i64,
}
