use sea_orm::entity::prelude::*;
use sea_orm::{ActiveValue, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, TryIntoModel};

pub use crate::models::_entities::shop_settings::{ActiveModel, Column, Entity, Model};
pub type ShopSettings = Entity;

#[async_trait::async_trait]
impl ActiveModelBehavior for ActiveModel {
    async fn before_save<C>(self, _db: &C, insert: bool) -> std::result::Result<Self, DbErr>
    where
        C: ConnectionTrait,
    {
        if !insert && self.updated_at.is_unchanged() {
            let mut this = self;
            this.updated_at = ActiveValue::set(chrono::Utc::now().into());
            Ok(this)
        } else {
            Ok(self)
        }
    }
}

impl Entity {
    pub async fn get<C: ConnectionTrait>(db: &C, key: &str) -> Result<Option<String>, DbErr> {
        Ok(Entity::find()
            .filter(Column::Key.eq(key))
            .one(db)
            .await?
            .and_then(|setting| setting.value))
    }

    pub async fn set<C: ConnectionTrait>(db: &C, key: &str, value: Option<String>) -> Result<Model, DbErr> {
        let mut active = match Entity::find()
            .filter(Column::Key.eq(key))
            .one(db)
            .await?
        {
            Some(existing) => existing.into_active_model(),
            None => ActiveModel {
                key: ActiveValue::set(key.to_string()),
                ..Default::default()
            },
        };
        active.value = ActiveValue::set(value);
        active.save(db).await?.try_into_model()
    }
}
