use crate::model::{
    log::Log,
    notification::Notification,
    role::Role,
    user::{AdminUser, User, UserWithRoles},
};
use rocket::{
    form::Form,
    get, post,
    request::FlashMessage,
    response::{Flash, Redirect},
    routes, FromForm, Route, State,
};
use rocket_dyn_templates::{tera::Context, Template};
use sqlx::SqlitePool;

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

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

#[derive(FromForm, Debug)]
pub struct NotificationToSend {
    pub(crate) role_id: i32,
    pub(crate) category: String,
    pub(crate) message: String,
}

#[post("/notification", data = "<data>")]
async fn send(
    db: &State<SqlitePool>,
    data: Form<NotificationToSend>,
    admin: AdminUser,
) -> Flash<Redirect> {
    let d = data.into_inner();
    Log::create(
        db,
        format!("{admin:?} trying to send this notification: {d:?}"),
    )
    .await;

    let Some(role) = Role::find_by_id(db, d.role_id).await else {
        return Flash::error(Redirect::to("/admin/notification"), "Rolle gibt's ned");
    };

    for user in User::all_with_role(&db, &role).await {
        Notification::create(db, &user, &d.message, &d.category, None).await;
    }
    Log::create(db, "Notification successfully sent".into()).await;
    Flash::success(
        Redirect::to("/admin/notification"),
        "Nachricht ausgeschickt",
    )
}

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