use mysql_async::{params, Pool};
use mysql_async::prelude::Queryable;
use mysql_async::error::Error;
use crate::UBigInt;

async fn update_jwt(p: &Pool, id: UBigInt, token: &str) -> Result<(), Error> {
    let conn = p.get_conn().await?;
    let _ = conn.drop_exec("UPDATE jwt SET token = :tk WHERE id = :id", 
        params!{"tk" => token, "id" => id}).await?;
    Ok(())
}

pub async fn add_jwt(p: &Pool, id: UBigInt, token: &str) -> Result<(), Error> {
    let conn = p.get_conn().await?;
    let q = "INSERT INTO jwt (id, token) VALUES (:id, :tk)";
    return match conn.prep_exec(q, params!{"tk" => token, "id" => id}).await {
        Ok(_) => Ok(()),
        Err(_) => update_jwt(p, id, token).await // attempt to refresh token
    };
}

pub async fn listed_jwt(p: &Pool, id: UBigInt, token_given: &str) -> Result<bool, Error> {
    // only checks if the given token is listed somewhere in the db
    let conn = p.get_conn().await?;
    let q = "SELECT token FROM jwt WHERE id = :id";
    // if id.token == return true
    let (_, db_t): (_, Option<String>) =
        conn.first_exec(q, params!{"id" => id}).await?;
    
    
    return match db_t {
        Some(token_db) => Ok(token_db == token_given),  // probably pointless check but its not that expensive so its stays as a sanity check
        None => Ok(false)
    };
}