use loco_rs::prelude::*;
use sea_orm::entity::prelude::*;
use sea_orm::QueryOrder;

pub use crate::models::_entities::product_images::{ActiveModel, Column, Entity, Model};
pub type ProductImages = 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 = sea_orm::ActiveValue::Set(chrono::Utc::now().into());
            Ok(this)
        } else {
            Ok(self)
        }
    }
}

// implement your write-oriented logic here
impl ActiveModel {}

// implement your custom finders, selectors oriented logic here
impl Entity {}

/// Filename of a product's primary (lowest-position) image, if any.
pub async fn first_for(ctx: &AppContext, product_id: i32) -> Result<Option<String>> {
    Ok(Entity::find()
        .filter(Column::ProductId.eq(product_id))
        .order_by_asc(Column::Position)
        .one(&ctx.db)
        .await?
        .map(|image| image.image_id))
}

/// All of a product's images in display order (lowest position first). Takes a
/// connection so it can run inside the update transaction.
pub async fn for_product<C: ConnectionTrait>(
    db: &C,
    product_id: i32,
) -> Result<Vec<Model>> {
    Ok(Entity::find()
        .filter(Column::ProductId.eq(product_id))
        .order_by_asc(Column::Position)
        .all(db)
        .await?)
}
