//! Ensures built-in payment methods and editable bank-transfer settings exist.
//!
//! Payment method enabled flags and bank account details are admin-managed in the
//! database. We seed missing rows only, so admin changes persist across restarts.

use async_trait::async_trait;
use loco_rs::prelude::*;
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set};

use crate::{
    models::{payment_methods, shop_settings},
    shared::settings,
};

/// `(code, name, enabled, position)`
const METHODS: [(&str, &str, bool, i32); 2] = [
    (payment_methods::COD, "Cash on delivery", true, 0),
    (payment_methods::BANK_TRANSFER, "Bank transfer", true, 1),
];

pub struct PaymentSeeder;

#[async_trait]
impl Initializer for PaymentSeeder {
    fn name(&self) -> String {
        "payment-seeder".to_string()
    }

    async fn before_run(&self, ctx: &AppContext) -> Result<()> {
        for (code, name, enabled, position) in METHODS {
            let exists = payment_methods::Entity::find()
                .filter(payment_methods::Column::Code.eq(code))
                .count(&ctx.db)
                .await?
                > 0;
            if exists {
                continue;
            }
            payment_methods::ActiveModel {
                code: Set(code.to_string()),
                name: Set(name.to_string()),
                enabled: Set(enabled),
                position: Set(position),
                ..Default::default()
            }
            .insert(&ctx.db)
            .await?;
            tracing::info!(payment = code, "seeded built-in payment method");
        }

        seed_setting(ctx, "bank_iban").await?;
        seed_setting(ctx, "bank_account_name").await
    }
}

async fn seed_setting(ctx: &AppContext, key: &str) -> Result<()> {
    let exists = shop_settings::Entity::find()
        .filter(shop_settings::Column::Key.eq(key))
        .count(&ctx.db)
        .await?
        > 0;
    if exists {
        return Ok(());
    }
    shop_settings::ActiveModel {
        key: Set(key.to_string()),
        value: Set(settings::get(ctx, key).map(str::to_string)),
        ..Default::default()
    }
    .insert(&ctx.db)
    .await?;
    Ok(())
}
