use crate::connections::db_connection::db;
use crate::models::users::{NewUser, User, UserID};
use crate::schema::users;
use crate::utils::time_utils::time;
use diesel::prelude::*;

/// Create or update a user's information
pub async fn create_or_update_user(mail: &str, name: &str) -> anyhow::Result<User> {
    let mut user = match get_user_by_email(mail) {
        Ok(u) => u,
        Err(e) => {
            log::info!("Failed to fetch user info, attempting to create a new user... {e}");

            diesel::insert_into(users::table)
                .values(&NewUser {
                    time_create: time() as i64,
                    time_update: time() as i64,
                    name,
                    mail,
                })
                .get_result(&mut db()?)?
        }
    };

    if user.name != name {
        log::info!("Name needs to be updated for user {:?}", user.id());
        user.name = name.to_string();
        update(&user)?;
    }

    Ok(user)
}

/// Get user information by its ID
pub fn get_user_by_id(id: UserID) -> anyhow::Result<User> {
    Ok(users::table
        .filter(users::dsl::id.eq(id.0))
        .first(&mut db()?)?)
}

/// Get user information by its email
pub fn get_user_by_email(mail: &str) -> anyhow::Result<User> {
    Ok(users::table
        .filter(users::dsl::mail.eq(mail))
        .first(&mut db()?)?)
}

/// Update user information
pub fn update(user: &User) -> anyhow::Result<()> {
    diesel::update(users::dsl::users.filter(users::dsl::id.eq(user.id().0)))
        .set((
            users::dsl::time_update.eq(time() as i64),
            users::dsl::name.eq(user.name.to_string()),
            users::dsl::mail.eq(user.mail.to_string()),
        ))
        .execute(&mut db()?)?;

    Ok(())
}
