//! Reusable discount profiles: a named percentage over a product scope, mixable
//! across business accounts.

pub use crate::models::_entities::discount_profiles::{ActiveModel, Column, Entity, Model};
use sea_orm::entity::prelude::*;

pub type DiscountProfiles = Entity;

/// Scope value: the profile covers exactly the listed products.
pub const SCOPE_INCLUDE: &str = "include";
/// Scope value: the profile covers every product except the listed ones.
pub const SCOPE_ALL_EXCEPT: &str = "all_except";

#[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)
        }
    }
}

impl Model {
    /// A profile covers `product_id` when its scope lists the product (include)
    /// or does not list it (all_except). `membership` is the profile's product
    /// id set.
    #[must_use]
    pub fn covers(&self, product_id: i32, membership: &std::collections::HashSet<i32>) -> bool {
        let listed = membership.contains(&product_id);
        match self.scope_type.as_str() {
            SCOPE_ALL_EXCEPT => !listed,
            _ => listed,
        }
    }
}
