mod guilds;
mod models;
mod reminders;

use std::env;

use chrono_tz::Tz;
pub use guilds::*;
pub use reminders::*;
use rocket::{
    get,
    http::CookieJar,
    patch,
    serde::json::{json, Json, Value as JsonValue},
    State,
};
use serde::{Deserialize, Serialize};
use serenity::{
    client::Context,
    model::id::{GuildId, RoleId},
};
use sqlx::{MySql, Pool};

#[derive(Serialize)]
struct UserInfo {
    name: String,
    patreon: bool,
    timezone: Option<String>,
}

#[derive(Deserialize)]
pub struct UpdateUser {
    timezone: String,
}

#[get("/api/user")]
pub async fn get_user_info(
    cookies: &CookieJar<'_>,
    ctx: &State<Context>,
    pool: &State<Pool<MySql>>,
) -> JsonValue {
    offline!(json!(UserInfo { name: "Discord".to_string(), patreon: true, timezone: None }));

    if let Some(user_id) =
        cookies.get_private("userid").map(|u| u.value().parse::<u64>().ok()).flatten()
    {
        let member_res = GuildId::new(env::var("PATREON_GUILD_ID").unwrap().parse().unwrap())
            .member(&ctx.inner(), user_id)
            .await;

        let timezone = sqlx::query!(
            "SELECT IFNULL(timezone, 'UTC') AS timezone FROM users WHERE user = ?",
            user_id
        )
        .fetch_one(pool.inner())
        .await
        .map_or(None, |q| Some(q.timezone));

        let user_info = UserInfo {
            name: cookies
                .get_private("username")
                .map_or("Discord User".to_string(), |c| c.value().to_string()),
            patreon: member_res.map_or(false, |member| {
                member
                    .roles
                    .contains(&RoleId::new(env::var("PATREON_ROLE_ID").unwrap().parse().unwrap()))
            }),
            timezone,
        };

        json!(user_info)
    } else {
        json!({"error": "Not authorized"})
    }
}

#[patch("/api/user", data = "<user>")]
pub async fn update_user_info(
    cookies: &CookieJar<'_>,
    user: Json<UpdateUser>,
    pool: &State<Pool<MySql>>,
) -> JsonValue {
    if let Some(user_id) =
        cookies.get_private("userid").map(|u| u.value().parse::<u64>().ok()).flatten()
    {
        if user.timezone.parse::<Tz>().is_ok() {
            let _ = sqlx::query!(
                "UPDATE users SET timezone = ? WHERE user = ?",
                user.timezone,
                user_id,
            )
            .execute(pool.inner())
            .await;

            json!({})
        } else {
            json!({"error": "Timezone not recognized"})
        }
    } else {
        json!({"error": "Not authorized"})
    }
}
