use crate::models::{
    _entities::{audio_albums, audio_tracks, audit_logs, blog_articles, users},
    users as users_model,
};
use loco_rs::prelude::*;
use sea_orm::{EntityTrait, PaginatorTrait};
use serde::Serialize;

#[derive(Debug, Serialize)]
struct DashboardResponse {
    users: u64,
    blog_articles: u64,
    audio_albums: u64,
    audio_tracks: u64,
    audit_logs: u64,
}

pub(crate) fn admin_email(ctx: &AppContext) -> Option<&str> {
    ctx.config
        .settings
        .as_ref()
        .and_then(|settings| settings.get("admin_email"))
        .and_then(|email| email.as_str())
}

pub(crate) fn is_admin(ctx: &AppContext, user: &users::Model) -> bool {
    admin_email(ctx).is_some_and(|email| user.email.eq_ignore_ascii_case(email))
}

pub(crate) async fn current_admin(auth: auth::JWT, ctx: &AppContext) -> Result<users::Model> {
    let user = users_model::Model::find_by_pid(&ctx.db, &auth.claims.pid).await?;

    if !is_admin(ctx, &user) {
        return unauthorized("admin only");
    }

    Ok(user)
}

#[debug_handler]
async fn dashboard(auth: auth::JWT, State(ctx): State<AppContext>) -> Result<Response> {
    current_admin(auth, &ctx).await?;

    format::json(DashboardResponse {
        users: users::Entity::find().count(&ctx.db).await?,
        blog_articles: blog_articles::Entity::find().count(&ctx.db).await?,
        audio_albums: audio_albums::Entity::find().count(&ctx.db).await?,
        audio_tracks: audio_tracks::Entity::find().count(&ctx.db).await?,
        audit_logs: audit_logs::Entity::find().count(&ctx.db).await?,
    })
}

pub fn routes() -> Routes {
    Routes::new()
        .prefix("/api/admin")
        .add("/dashboard", get(dashboard))
}
