//! Admin management for checkout payment methods and bank-transfer details.

use axum_extra::extract::cookie::CookieJar;
use loco_rs::prelude::*;
use sea_orm::{ActiveModelTrait, EntityTrait, QueryOrder, Set};
use serde::Deserialize;
use serde_json::json;

use crate::{
    controllers::i18n::current_lang,
    models::{payment_methods, shop_settings},
    shared::guard,
};

#[derive(Debug, Deserialize)]
struct PaymentMethodForm {
    enabled: Option<String>,
}

#[derive(Debug, Deserialize)]
struct BankSettingsForm {
    bank_account_name: String,
    bank_iban: String,
}

fn is_checked(value: &Option<String>) -> bool {
    matches!(value.as_deref(), Some("on" | "true" | "1"))
}

fn trimmed(value: &str) -> Option<String> {
    let value = value.trim();
    (!value.is_empty()).then(|| value.to_string())
}

#[debug_handler]
async fn index(
    auth: auth::JWT,
    jar: CookieJar,
    ViewEngine(v): ViewEngine<TeraView>,
    State(ctx): State<AppContext>,
) -> Result<Response> {
    guard::current_admin(auth, &ctx).await?;
    let methods = payment_methods::Entity::find()
        .order_by_asc(payment_methods::Column::Position)
        .all(&ctx.db)
        .await?;
    let rows: Vec<serde_json::Value> = methods
        .iter()
        .map(|m| {
            json!({
                "id": m.id,
                "code": m.code,
                "label_key": m.label_key(),
                "enabled": m.enabled,
            })
        })
        .collect();
    let bank_account_name = shop_settings::Entity::get(&ctx.db, "bank_account_name")
        .await?
        .unwrap_or_default();
    let bank_iban = shop_settings::Entity::get(&ctx.db, "bank_iban")
        .await?
        .unwrap_or_default();

    format::view(
        &v,
        "admin/payments/index.html",
        json!({
            "methods": rows,
            "bank_account_name": bank_account_name,
            "bank_iban": bank_iban,
            "lang": current_lang(&jar),
        }),
    )
}

#[debug_handler]
async fn update_method(
    auth: auth::JWT,
    Path(id): Path<i32>,
    State(ctx): State<AppContext>,
    Form(form): Form<PaymentMethodForm>,
) -> Result<Response> {
    guard::current_admin(auth, &ctx).await?;
    let method = payment_methods::Entity::find_by_id(id)
        .one(&ctx.db)
        .await?
        .ok_or_else(|| Error::NotFound)?;
    let mut active = method.into_active_model();
    active.enabled = Set(is_checked(&form.enabled));
    active.update(&ctx.db).await?;
    format::redirect("/admin/payments")
}

#[debug_handler]
async fn update_bank(
    auth: auth::JWT,
    State(ctx): State<AppContext>,
    Form(form): Form<BankSettingsForm>,
) -> Result<Response> {
    guard::current_admin(auth, &ctx).await?;
    shop_settings::Entity::set(&ctx.db, "bank_account_name", trimmed(&form.bank_account_name)).await?;
    shop_settings::Entity::set(&ctx.db, "bank_iban", trimmed(&form.bank_iban)).await?;
    format::redirect("/admin/payments")
}

pub fn routes() -> Routes {
    Routes::new()
        .add("/admin/payments", get(index))
        .add("/admin/payments/methods/{id}", post(update_method))
        .add("/admin/payments/bank", post(update_bank))
}
