use rocket::form::Form;
use rocket::fs::TempFile;
use rocket::response::{Flash, Redirect};
use rocket::{get, request::FlashMessage, routes, Route, State};
use rocket::{post, FromForm};
use rocket_dyn_templates::{tera::Context, Template};
use sqlx::SqlitePool;

use crate::model::log::Log;
use crate::model::mail::Mail;
use crate::model::role::Role;
use crate::model::user::AdminUser;
use crate::model::user::UserWithRoles;
use crate::tera::Config;

#[get("/mail")]
async fn index(
    db: &State<SqlitePool>,
    admin: AdminUser,
    flash: Option<FlashMessage<'_>>,
) -> Template {
    let mut context = Context::new();
    if let Some(msg) = flash {
        context.insert("flash", &msg.into_inner());
    }
    let roles = Role::all(db).await;

    context.insert(
        "loggedin_user",
        &UserWithRoles::from_user(admin.user, db).await,
    );
    context.insert("roles", &roles);

    Template::render("admin/mail", context.into_json())
}

#[get("/mail/fee")]
async fn fee(db: &State<SqlitePool>, admin: AdminUser, config: &State<Config>) -> &'static str {
    Log::create(db, format!("{admin:?} trying to send fee")).await;
    Mail::fees(db, config.smtp_pw.clone()).await;
    "SUCC"
}

#[get("/mail/fee-final")]
async fn fee_final(
    db: &State<SqlitePool>,
    admin: AdminUser,
    config: &State<Config>,
) -> &'static str {
    Log::create(db, format!("{admin:?} trying to send fee_final")).await;
    Mail::fees_final(db, config.smtp_pw.clone()).await;
    "SUCC"
}

#[derive(FromForm, Debug)]
pub struct MailToSend<'a> {
    pub(crate) role_id: i32,
    pub(crate) subject: String,
    pub(crate) body: String,
    pub(crate) files: Vec<TempFile<'a>>,
}

#[post("/mail", data = "<data>")]
async fn update(
    db: &State<SqlitePool>,
    data: Form<MailToSend<'_>>,
    config: &State<Config>,
    admin: AdminUser,
) -> Flash<Redirect> {
    let d = data.into_inner();
    Log::create(db, format!("{admin:?} trying to send this mail: {d:?}")).await;
    if Mail::send(db, d, config.smtp_pw.clone()).await {
        Log::create(db, "Mail successfully sent".into()).await;
        Flash::success(Redirect::to("/admin/mail"), "Mail versendet")
    } else {
        Log::create(db, "Error sending the mail".into()).await;
        Flash::error(Redirect::to("/admin/mail"), "Fehler")
    }
}

pub fn routes() -> Vec<Route> {
    routes![index, update, fee, fee_final]
}

#[cfg(test)]
mod test {}
