<?php
/**
 * This file implement method for advanced conditions logic
 *
 * @package  YITH\DynamicPricing\And\Discounts\Traits
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 *  The trait implement logic font the advanced conditions field
 *
 * @since 4.0.0
 */
trait  YWDPD_Advanced_Conditions_Trait {


	/**
	 * Get all rule conditions
	 *
	 * @return array
	 * @since  4.0.0
	 * @author YITH <plugins@yithemes.com>
	 */
	abstract public function get_conditions();

	/**
	 * Get the name of current condition
	 *
	 * @param array $condition The condition.
	 *
	 * @return string
	 * @since  4.0.0
	 */
	public function get_condition_name( $condition ) {

		return $condition['cart_condition_name'] ?? '';
	}

	/**
	 * Get the type of current condition
	 *
	 * @param array $condition The condition.
	 *
	 * @return string
	 * @since  4.0.0
	 */
	public function get_condition_type( $condition ) {

		return $condition['condition_for'];

	}

	/** ==== User condition methods ==== */

	/**
	 * Return how the condition is applied for users ( All | Specific users )
	 *
	 * @param array $condition The single condition.
	 *
	 * @return string
	 * @since  4.0.0
	 */
	public function get_condition_user_type( $condition ) {
		return $condition['user_discount_to'] ?? 'all';
	}

	/** ===== User exclusion condition ====== */

	/**
	 * Check if the condition is enabled the users exclusion
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_enabled_user_exclusion( $condition ) {
		$is_enabled = $condition['enable_exclude_users'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the list of customers excluded
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_customer_list_excluded( $condition ) {
		return ! empty( $condition['customers_list_excluded'] ) ? $condition['customers_list_excluded'] : array();
	}

	/**
	 * Get the list of user role excluded
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_user_role_list_excluded( $condition ) {
		return ! empty( $condition['customers_role_list_excluded'] ) ? $condition['customers_role_list_excluded'] : array();
	}

	/** ===== END: User exclusion condition ====== */

	/** ===== User included condition ===== */

	/**
	 * Get the list of customers included
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_customer_list_included( $condition ) {
		return ! empty( $condition['customers_list'] ) ? $condition['customers_list'] : array();
	}

	/**
	 * Get the list of user roles included
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_user_role_list_included( $condition ) {
		return ! empty( $condition['customers_role_list'] ) ? $condition['customers_role_list'] : array();
	}
	/** ===== END:User included condition ===== */
	/** ==== END:User condition methods ==== */
	/** ==== Number of orders methods. ==== */

	/**
	 * Get the minimum number of orders
	 *
	 * @param array $condition The single condition.
	 *
	 * @return int
	 * @since  4.0.0
	 */
	public function get_condition_minimum_orders( $condition ) {
		return $condition['min_max_order']['min_order'] ?? 1;
	}

	/**
	 * Get the maximum number of orders
	 *
	 * @param array $condition The single condition.
	 *
	 * @return int
	 * @since  4.0.0
	 */
	public function get_condition_maximum_orders( $condition ) {
		return ! empty( $condition['min_max_order']['max_order'] ) ? $condition['min_max_order']['max_order'] : '';
	}

	/** ==== END:Number of orders methods. ==== */
	/** ====  Total past expense methods. ==== */

	/**
	 * Get the minimum past expense required
	 *
	 * @param array $condition The single condition.
	 *
	 * @return float
	 * @since  4.0.0
	 */
	public function get_condition_minimum_past_expense( $condition ) {
		return isset( $condition['min_max_expense']['min_expense'] ) ? wc_format_decimal( $condition['min_max_expense']['min_expense'], wc_get_price_decimals() ) : 1;
	}

	/**
	 * Get the maximum past expense allowed
	 *
	 * @param array $condition The single condition.
	 *
	 * @return float
	 * @since  4.0.0
	 */
	public function get_condition_maximum_past_expense( $condition ) {
		return ! empty( $condition['min_max_expense']['max_expense'] ) ? wc_format_decimal( $condition['min_max_expense']['max_expense'], wc_get_price_decimals() ) : '';
	}

	/** ==== END: Total past expense methods. ==== */
	/** ==== Product methods ==== */

	/**
	 * Get the product type condition ( Require, Exclude, Disable )
	 *
	 * @param array $condition The single condition.
	 *
	 * @return string
	 * @since  4.0.0
	 */
	public function get_condition_product_type( $condition ) {
		return $condition['product_type'] ?? 'require_product';
	}

	/**
	 * Check if specific product are required in cart
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_required_specific_product( $condition ) {
		$is_enabled = $condition['enable_require_product'] ?? 'yes';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the required product list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_required_product_list( $condition ) {
		$list = ! empty( $condition['require_product_list'] ) ? $condition['require_product_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_required_product_list
		 *
		 * Change the required product ids.
		 *
		 * @param array                            $list The product ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_required_product_list', $list, $this );
	}

	/**
	 * Get how manage the required list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return string
	 * @since  4.0.0
	 */
	public function get_condition_required_product_list_mode( $condition ) {
		return $condition['require_product_list_mode'] ?? 'at_least';
	}

	/**
	 * Check if specific product categories are required in cart
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_required_specific_product_categories( $condition ) {
		$is_enabled = $condition['enable_require_product_categories'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the required category product list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_required_product_category_list( $condition ) {
		$list = ! empty( $condition['require_product_category_list'] ) ? $condition['require_product_category_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_required_product_category_list
		 *
		 * Change the required product category ids.
		 *
		 * @param array                            $list The product category ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_required_product_category_list', $list, $this );
	}

	/**
	 * Get how manage the required list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return string
	 * @since  4.0.0
	 */
	public function get_condition_required_product_category_list_mode( $condition ) {
		return $condition['require_product_cat_list_mode'] ?? 'at_least';
	}

	/**
	 * Check if specific product tag are required in cart
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_required_specific_product_tag( $condition ) {
		$is_enabled = $condition['enable_require_product_tag'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the required tag product list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_required_product_tag_list( $condition ) {
		$list = ! empty( $condition['require_product_tag_list'] ) ? $condition['require_product_tag_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_required_product_tag_list
		 *
		 * Change the required product tag ids.
		 *
		 * @param array                            $list The product tag ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_required_product_tag_list', $list, $this );
	}

	/**
	 * Get how manage the required list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return string
	 * @since  4.0.0
	 */
	public function get_condition_required_product_tag_list_mode( $condition ) {
		return $condition['require_product_tag_list_mode'] ?? 'at_least';
	}

	/**
	 * Check if products are excluded form rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_excluded_product_enabled( $condition ) {
		$is_enabled = $condition['enable_exclude_require_product'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the excluded product list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_excluded_product_list( $condition ) {
		$list = ! empty( $condition['exclude_product_list'] ) ? $condition['exclude_product_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_excluded_product_list
		 *
		 * Change the excluded product tag ids.
		 *
		 * @param array                            $list The product ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_excluded_product_list', $list, $this );
	}

	/**
	 * Check if on-sale products are excluded form rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_onsale_product_excluded( $condition ) {
		$is_enabled = $condition['enable_exclude_on_sale_product'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Check if product categories are excluded form rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_excluded_product_categories_enabled( $condition ) {
		$is_enabled = $condition['enable_exclude_product_categories'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the excluded product list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_excluded_product_categories_list( $condition ) {
		$list = ! empty( $condition['exclude_product_category_list'] ) ? $condition['exclude_product_category_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_excluded_product_categories_list
		 *
		 * Change the excluded product category ids.
		 *
		 * @param array                            $list The product category ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_excluded_product_categories_list', $list, $this );
	}

	/**
	 * Check if product tag are excluded form rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_excluded_product_tag_enabled( $condition ) {
		$is_enabled = $condition['enable_exclude_product_tag'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the excluded product tag list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_excluded_product_tag_list( $condition ) {
		$list = ! empty( $condition['exclude_product_tag_list'] ) ? $condition['exclude_product_tag_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_excluded_product_tag_list
		 *
		 * Change the excluded product tag ids.
		 *
		 * @param array                            $list The product tag ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_excluded_product_tag_list', $list, $this );
	}

	/**
	 * Check if products are excluded form rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_disable_product_enabled( $condition ) {
		$is_enabled = $condition['enable_disable_require_product'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the product list that disable the rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_disable_product_list( $condition ) {
		$list = ! empty( $condition['disable_product_list'] ) ? $condition['disable_product_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_disable_product_list
		 *
		 * Change the disabled product ids.
		 *
		 * @param array                            $list The product ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_disable_product_list', $list, $this );
	}

	/**
	 * Check if product categories are disabled form rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_disable_product_categories_enabled( $condition ) {
		$is_enabled = $condition['enable_disable_product_categories'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the excluded product list
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_disable_product_categories_list( $condition ) {
		$list = ! empty( $condition['disable_product_category_list'] ) ? $condition['disable_product_category_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_disable_product_categories_list
		 *
		 * Change the disabled product category ids.
		 *
		 * @param array                            $list The product category ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_disable_product_categories_list', $list, $this );
	}

	/**
	 * Check if product tag are disable form rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_condition_disable_product_tag_enabled( $condition ) {
		$is_enabled = $condition['disable_exclude_product_tag'] ?? 'no';

		return yith_plugin_fw_is_true( $is_enabled );
	}

	/**
	 * Get the product tag list that disable this rule
	 *
	 * @param array $condition The single condition.
	 *
	 * @return array
	 * @since  4.0.0
	 */
	public function get_condition_disable_product_tag_list( $condition ) {
		$list = ! empty( $condition['disable_product_tag_list'] ) ? $condition['disable_product_tag_list'] : array();

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_disable_product_tag_list
		 *
		 * Change the disabled product tag ids.
		 *
		 * @param array                            $list The product tag ids.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule The rule.
		 *
		 * @return array
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_disable_product_tag_list', $list, $this );
	}

	/** ==== END: Product methods ==== */

	/** ==== Cart item methods. ==== */

	/**
	 * Get cart item condition type ( Product items or Cart item )
	 *
	 * @param array $condition The single condition.
	 *
	 * @return string
	 * @since  4.0.0
	 */
	public function get_condition_cart_item_mode( $condition ) {
		return $condition['cart_item_qty_type'] ?? 'count_product_items';
	}

	/**
	 * Get the minimum item in cart
	 *
	 * @param array $condition The single condition.
	 *
	 * @return int
	 * @since  4.0.0
	 */
	public function get_condition_minimum_product_item( $condition ) {
		return isset( $condition['min_max_product_item']['min_product_item'] ) ? intval( $condition['min_max_product_item']['min_product_item'] ) : 1;
	}

	/**
	 * Get the maximum item in cart allowed
	 *
	 * @param array $condition The single condition.
	 *
	 * @return int
	 * @since  4.0.0
	 */
	public function get_condition_maximum_product_item( $condition ) {
		return ! empty( $condition['min_max_product_item']['max_product_item'] ) ? intval( $condition['min_max_product_item']['max_product_item'] ) : '';
	}

	/**
	 * Get the minimum cart element in cart
	 *
	 * @param array $condition The single condition.
	 *
	 * @return int
	 * @since  4.0.0
	 */
	public function get_condition_minimum_cart_item( $condition ) {
		return isset( $condition['min_max_cart_item']['min_cart_item'] ) ? intval( $condition['min_max_cart_item']['min_cart_item'] ) : 1;
	}

	/**
	 * Get the maximum cart item allowed
	 *
	 * @param array $condition The single condition.
	 *
	 * @return int
	 * @since  4.0.0
	 */
	public function get_condition_maximum_cart_item( $condition ) {
		return ! empty( $condition['min_max_cart_item']['max_cart_item'] ) ? intval( $condition['min_max_cart_item']['max_cart_item'] ) : '';
	}

	/** ==== END:Cart item methods. ==== */

	/** ==== SUBTOTAL methods. ==== */

	/**
	 * Get the minimum subtotal required
	 *
	 * @param array $condition The single condition.
	 *
	 * @return float
	 * @since  4.0.0
	 */
	public function get_condition_minimum_subtotal( $condition ) {
		$value = isset( $condition['min_max_subtotal']['min_subtotal'] ) ? wc_format_decimal( $condition['min_max_subtotal']['min_subtotal'], wc_get_price_decimals() ) : 1;

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_minimum_subtotal
		 *
		 * Change the minimum subtotal.
		 *
		 * @param float                            $value The minimum subtotal.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule  The rule.
		 *
		 * @return float
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_minimum_subtotal', $value, $this );
	}

	/**
	 * Get the maximum subtotal required
	 *
	 * @param array $condition The single condition.
	 *
	 * @return float
	 * @since  4.0.0
	 */
	public function get_condition_maximum_subtotal( $condition ) {
		$value = ! empty( $condition['min_max_subtotal']['max_subtotal'] ) ? wc_format_decimal( $condition['min_max_subtotal']['max_subtotal'], wc_get_price_decimals() ) : '';

		/**
		 * APPLY_FILTERS: ywdpd_advanced_conditions_get_maximum_subtotal
		 *
		 * Change the maximum subtotal.
		 *
		 * @param float                            $value The maximum subtotal.
		 * @param YWDPD_Cart_Rule|YWDPD_Last_Deals $rule  The rule.
		 *
		 * @return float
		 */
		return apply_filters( 'ywdpd_advanced_conditions_get_maximum_subtotal', $value, $this );
	}

	/** ==== END:SUBTOTAL methods. ==== */

	/** ==== Validation methods ==== */

	/**
	 * Check if the current user is valid
	 *
	 * @param array $condition The single conditions.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_valid_customers_condition( $condition ) {
		$is_valid       = true;
		$user_logged_in = is_user_logged_in();
		$user           = $user_logged_in ? wp_get_current_user() : false;
		$user_roles     = $user ? $user->roles : array( 'guest' );
		$user_mode      = $this->get_condition_user_type( $condition );

		if ( 'all' === $user_mode ) {
			$is_customers_excluded = $this->is_condition_enabled_user_exclusion( $condition );
			if ( $is_customers_excluded ) {
				$customers_excluded = $this->get_condition_customer_list_excluded( $condition );
				$roles_excluded     = $this->get_condition_user_role_list_excluded( $condition );
				if ( $user_logged_in ) {
					if ( ! empty( $customers_excluded ) ) {
						if ( in_array( $user->ID, $customers_excluded ) ) { //phpcs:ignore
							$is_valid = false;
						}
					}
				}

				if ( ! empty( $roles_excluded ) && is_array( $roles_excluded ) ) {
					$intersect = array_intersect( $user_roles, $roles_excluded );
					if ( ! empty( $roles_excluded ) && 0 < count( $intersect ) ) {
						$is_valid = false;
					}
				}
			}
		} else {
			$customers_list = $this->get_condition_customer_list_included( $condition );
			$role_list      = $this->get_condition_user_role_list_included( $condition );

			if ( $user_logged_in ) {
				if ( ! empty( $customers_list ) ) {
					if ( ! in_array( $user->ID, $customers_list ) ) { // phpcs:ignore
						$is_valid = false;
					}
				}
			} else {
				$is_valid = false;
			}

			if ( ! empty( $role_list ) && is_array( $role_list ) ) {
				$intersect = array_intersect( $user_roles, $role_list );

				if ( 0 === count( $intersect ) ) {
					$is_valid = false;
				}
			}
		}

		/**
		 * APPLY_FILTERS: ywdpd_customers_condition_is_valid
		 *
		 * Set if customer condition is valid or not.
		 *
		 * @param bool            $is_valid   Is valid.
		 * @param array           $condition  The condition.
		 * @param array           $conditions All conditions.
		 * @param YWDPD_Cart_Rule $rule       The cart rule.
		 *
		 * @return bool
		 */
		return apply_filters( 'ywdpd_customers_condition_is_valid', $is_valid, $condition, $this->get_conditions(), $this );
	}

	/**
	 * Check if customer has the right amount of orders
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_valid_num_of_orders_condition( $condition ) {
		$is_valid = true;

		if ( is_user_logged_in() ) {

			$user_id      = get_current_user_id();
			$num_of_order = wc_get_customer_order_count( $user_id );
			$min_order    = $this->get_condition_minimum_orders( $condition );
			$max_order    = $this->get_condition_maximum_orders( $condition );

			if ( ( $num_of_order < $min_order ) || ( ! empty( $max_order ) && $num_of_order >= $max_order ) ) {

				$is_valid = false;
			}
		}

		return $is_valid;
	}

	/**
	 * Check if the customer is valid for past expense
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_valid_past_expense_condition( $condition ) {
		$is_valid = true;

		if ( is_user_logged_in() ) {

			$user_id      = get_current_user_id();
			$past_expense = wc_get_customer_total_spent( $user_id );
			$min_expense  = $this->get_condition_minimum_past_expense( $condition );
			$max_expense  = $this->get_condition_maximum_past_expense( $condition );

			if ( ( $past_expense < $min_expense ) || ( ! empty( $max_expense ) && $past_expense > $max_expense ) ) {
				$is_valid = false;
			}
		}

		return $is_valid;
	}

	/**
	 * Check if the product condition is valid
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  3.0.0
	 */
	public function is_valid_product_condition( $condition ) {

		$is_valid = true;

		$type_check = $this->get_condition_product_type( $condition );
		if ( 'require_product' === $type_check ) {
			$require_product     = $this->is_condition_required_specific_product( $condition );
			$require_product_cat = $this->is_condition_required_specific_product_categories( $condition );
			$require_product_tag = $this->is_condition_required_specific_product_tag( $condition );
			if ( $require_product ) {
				$product_list = $this->get_condition_required_product_list( $condition );
				$check_mode   = $this->get_condition_required_product_list_mode( $condition );

				if ( count( $product_list ) > 0 ) {
					$is_valid = YWDPD_Counter::check_taxonomy_in_cart( $product_list, 'product', $check_mode );
				}
			}
			if ( $is_valid && $require_product_cat ) {
				$cat_list   = $this->get_condition_required_product_category_list( $condition );
				$check_mode = $this->get_condition_required_product_category_list_mode( $condition );

				$is_valid = YWDPD_Counter::check_taxonomy_in_cart( $cat_list, 'product_cat', $check_mode );

			}

			if ( $is_valid && $require_product_tag ) {
				$tag_list   = $this->get_condition_required_product_tag_list( $condition );
				$check_mode = $this->get_condition_required_product_tag_list_mode( $condition );
				$is_valid   = YWDPD_Counter::check_taxonomy_in_cart( $tag_list, 'product_tag', $check_mode );
			}
		} elseif ( 'disable_product' === $type_check ) {
			$disable_product     = $this->is_condition_disable_product_enabled( $condition );
			$disable_product_cat = $this->is_condition_disable_product_categories_enabled( $condition );
			$disable_product_tag = $this->is_condition_disable_product_tag_enabled( $condition );
			$is_disable          = false;
			if ( $disable_product ) {
				$disable_product_list = $this->get_condition_disable_product_list( $condition );
				$is_disable           = YWDPD_Counter::check_taxonomy_in_cart( $disable_product_list, 'product', 'at_least' );

			}

			if ( ! $is_disable && $disable_product_cat ) {
				$disable_product_cat_list = $this->get_condition_disable_product_categories_list( $condition );
				$is_disable               = YWDPD_Counter::check_taxonomy_in_cart( $disable_product_cat_list, 'product_cat', 'at_least' );
			}
			if ( ! $is_disable && $disable_product_tag ) {
				$disable_product_tag_list = $this->get_condition_disable_product_tag_list( $condition );
				$is_disable               = YWDPD_Counter::check_taxonomy_in_cart( $disable_product_tag_list, 'product_tag', 'at_least' );
			}

			$is_valid = ! $is_disable;
		}

		/**
		 * APPLY_FILTERS: ywdpd_valid_product_cart_condition
		 *
		 * Set if the product condition is valid or not.
		 *
		 * @param bool            $is_valid   Is valid.
		 * @param array           $condition  The condition.
		 * @param array           $conditions All conditions.
		 * @param YWDPD_Cart_Rule $rule       The cart rule.
		 *
		 * @return bool
		 */
		return apply_filters( 'ywdpd_valid_product_cart_condition', $is_valid, $condition, $this->get_conditions(), $this );

	}

	/**
	 * Check if the product is in a exclusion condition
	 *
	 * @param array $cart_item The product.
	 *
	 * @return bool
	 * @since  3.0.0
	 */
	public function is_product_excluded_from_conditions( $cart_item ) {
		$is_excluded = false;
		$conditions  = $this->get_conditions();
		$product     = $cart_item['data'];
		foreach ( $conditions as $condition ) {
			$type = $this->get_condition_type( $condition );
			if ( 'product' === $type ) {
				$type_check = $this->get_condition_product_type( $condition );

				if ( 'exclude_product' === $type_check ) {
					$exclude_product     = $this->is_condition_excluded_product_enabled( $condition );
					$exclude_onsale      = $this->is_condition_onsale_product_excluded( $condition );
					$exclude_product_cat = $this->is_condition_excluded_product_categories_enabled( $condition );
					$exclude_product_tag = $this->is_condition_excluded_product_tag_enabled( $condition );

					if ( $exclude_product ) {
						$product_list = $this->get_condition_excluded_product_list( $condition );

						$is_excluded = in_array( $product->get_id(), $product_list ); //phpcs:ignore
					}
					if ( ! $is_excluded && $exclude_onsale && $product->is_on_sale() ) {
						$is_excluded = true;
					}
					if ( ! $is_excluded && $exclude_product_cat ) {
						$exclude_product_cat_list = $this->get_condition_excluded_product_categories_list( $condition );
						$product_terms            = YWDPD_Taxonomy::get_product_category_ids( $product );
						$is_excluded              = count( array_intersect( $product_terms, $exclude_product_cat_list ) ) > 0;
					}

					if ( ! $is_excluded && $exclude_product_tag ) {
						$exclude_product_tag_list = $this->get_condition_excluded_product_tag_list( $condition );
						$product_terms            = YWDPD_Taxonomy::get_product_tag_ids( $product );
						$is_excluded              = count( array_intersect( $product_terms, $exclude_product_tag_list ) ) > 0;
					}
					/**
					 * APPLY_FILTERS: ywpd_is_excluded_product_cart_condition
					 *
					 * Set if the product is excluded or not.
					 *
					 * @param bool            $is_excluded Is valid.
					 * @param array           $condition   The condition.
					 * @param WC_Product      $product     The product.
					 * @param YWDPD_Cart_Rule $rule        The cart rule.
					 *
					 * @return bool
					 */
					$is_excluded = apply_filters( 'ywpd_is_excluded_product_cart_condition', $is_excluded, $condition, $product, $this );

					if ( $is_excluded ) {
						break;
					}
				}
			}
		}

		/**
		 * APPLY_FILTERS: ywdpd_valid_product_exclude_cart_condition
		 *
		 * Set if the product condition is valid or not.
		 *
		 * @param bool            $is_excluded Is valid.
		 * @param array           $condition   The condition.
		 * @param array           $conditions  All conditions.
		 * @param WC_Product      $product     The  product.
		 * @param YWDPD_Cart_Rule $rule        The cart rule.
		 *
		 * @return bool
		 */
		return apply_filters( 'ywdpd_valid_product_exclude_cart_condition', $is_excluded, $conditions, $product, $this );
	}

	/**
	 * Check if the cart item
	 *
	 * @param array $condition The condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_valid_cart_items_condition( $condition ) {
		$quantity_check = $this->get_condition_cart_item_mode( $condition );
		if ( 'count_product_items' === $quantity_check ) {
			$min_items = $this->get_condition_minimum_product_item( $condition );
			$max_items = $this->get_condition_maximum_product_item( $condition );
			$is_valid  = $this->check_cart_item_quantity( $min_items, $max_items );
		} else {
			$min_items = $this->get_condition_minimum_cart_item( $condition );
			$max_items = $this->get_condition_maximum_cart_item( $condition );
			$is_valid  = $this->check_comulative_quantity( $min_items, $max_items );
		}

		return $is_valid;
	}

	/**
	 * Check if the subtotal condition is valid
	 *
	 * @param array $condition The single condition.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function is_valid_cart_subtotal_condition( $condition ) {
		$is_valid = true;

		$min_subtotal = $this->get_condition_minimum_subtotal( $condition );
		$max_subtotal = $this->get_condition_maximum_subtotal( $condition );
		$subtotal     = $this->get_cart_subtotal();
		if ( $subtotal < $min_subtotal || ( ! empty( $max_subtotal ) && $subtotal > $max_subtotal ) ) {
			$is_valid = false;
		}

		/**
		* APPLY_FILTERS: is_valid_cart_subtotal_condition
		*
		* filter the cart subtotal condition
		* 
		* @param boolean $is_valid
		* @param array   $condition The single condition.
		* @param YWDPD_Cart_Rule|YWDPD_Last_Deals $this Rule Object.
		*
		* @return array
		* 
		*/
		return apply_filters( 'is_valid_cart_subtotal_condition', $is_valid, $condition, $this );
	}

	/**
	 * Check if the country condition is valid
	 *
	 * @param array $condition The condition.
	 *
	 * @return bool
	 * @since 4.0.0
	 */
	public function is_valid_country_condition( $condition ) {

		$customer = WC()->customer->get_billing_country();

		$is_valid = false;
		if ( yith_plugin_fw_is_true( $condition['enable_include_require_country'] ) ) {
			$list = $condition['include_require_country_list'];

			$is_valid = in_array( $customer, $list, true );
		} elseif ( yith_plugin_fw_is_true( $condition['enable_exclude_require_country'] ) ) {
			$list     = $condition['exclude_require_country_list'];
			$is_valid = ! in_array( $customer, $list, true );
		}

		return $is_valid;
	}

	/**
	 * Check if the condition for the payment method is valid
	 *
	 * @param array $condition The condition.
	 *
	 * @return bool
	 */
	public function is_valid_payment_method_condition( $condition ) {
		$selected_method = WC()->session->get( 'chosen_payment_method' );

		$is_valid        = false;
		if ( yith_plugin_fw_is_true( $condition['enable_include_require_payment_method'] ) ) {
			$list = $condition['include_require_payment_method_list'];

			$is_valid = in_array( $selected_method, $list, true );
		} elseif ( yith_plugin_fw_is_true( $condition['enable_exclude_require_payment_method'] ) ) {
			$list     = $condition['exclude_require_payment_method_list'];
			$is_valid = ! in_array( $selected_method, $list, true );
		}

		return $is_valid;
	}

	/**
	 * Check if each cart item quantity is valid
	 *
	 * @param int $min_qty The min qty to check.
	 * @param int $max_qty The max qty to check.
	 *
	 * @return bool
	 * @since  3.0
	 */
	public function check_cart_item_quantity( $min_qty, $max_qty ) {
		if ( ! is_null( WC()->cart ) && ! WC()->cart->is_empty() ) {

			foreach ( WC()->cart->get_cart_contents() as $cart_item_key => $cart_item ) {

				$qty = $cart_item['quantity'];
				/**
				 * APPLY_FILTERS: ywdpd_product_can_be_counted_in_condition
				 *
				 * Set if the product can be counted or not.
				 *
				 * @param bool       $can_count True or false.
				 * @param WC_Product $product   The  product.
				 *
				 * @return bool
				 */
				if ( apply_filters( 'ywdpd_product_can_be_counted_in_condition', ! $this->is_product_excluded_from_conditions( $cart_item ), $cart_item ) ) {
					if ( ( $qty < $min_qty ) || ( ! empty( $max_qty ) && $qty > $max_qty ) ) {
						return false;
					}
				}
			}
		}

		return true;
	}

	/**
	 * Check if the total of items in the cart are between min and max
	 *
	 * @param int $min_items The minimum amount of items in the cart.
	 * @param int $max_items The maximum amount of items in the cart.
	 *
	 * @return bool
	 * @since  4.0.0
	 */
	public function check_comulative_quantity( $min_items, $max_items ) {

		$num_items = 0;

		if ( ! is_null( WC()->cart ) && ! WC()->cart->is_empty() ) {

			foreach ( WC()->cart->get_cart_contents() as $cart_item_key => $cart_item ) {
				/**
				 * APPLY_FILTERS: ywdpd_product_can_be_counted_in_condition
				 *
				 * Set if the product can be counted or not.
				 *
				 * @param bool       $can_count True or false.
				 * @param WC_Product $product   The  product.
				 *
				 * @return bool
				 */
				if ( apply_filters( 'ywdpd_product_can_be_counted_in_condition', ! $this->is_product_excluded_from_conditions( $cart_item ), $cart_item ) ) {
					$num_items += $cart_item['quantity'];
				}
			}
		}
		/**
		 * APPLY_FILTERS: ywdpd_get_cart_item_quantities
		 *
		 * Set the cart item quantities.
		 *
		 * @param int $num_items The quantity.
		 *
		 * @return int
		 */
		$num_items = apply_filters( 'ywdpd_get_cart_item_quantities', $num_items );

		return ( ( $num_items >= $min_items ) && ( ( empty( $max_items ) || ( ! empty( $max_items ) && $num_items <= $max_items ) ) ) );
	}

	/**
	 * Return the right cart subtotal
	 *
	 * @return float
	 * @since  4.0.0
	 */
	public function get_cart_subtotal() {

		$subtotal = 0;
		if ( ! is_null( WC()->cart ) && ! WC()->cart->is_empty() ) {
			$tax_excluded = 'tax_excluded' === YITH_WC_Dynamic_Options::how_calculate_discounts();
			foreach ( WC()->cart->get_cart_contents() as $cart_item_key => $cart_item ) {
				if ( isset( $cart_item['data'], $cart_item['line_subtotal'], $cart_item['line_subtotal_tax'] ) ) {
					/**
					 * APPLY_FILTERS: ywdpd_product_can_be_counted_in_condition
					 *
					 * Set if the product can be counted or not.
					 *
					 * @param bool       $can_count True or false.
					 * @param WC_Product $product   The  product.
					 *
					 * @return bool
					 */
					if ( apply_filters( 'ywdpd_product_can_be_counted_in_condition', ! $this->is_product_excluded_from_conditions( $cart_item ), $cart_item ) ) {
						$subtotal += $tax_excluded ? $cart_item['line_subtotal'] : $cart_item['line_subtotal'] + $cart_item['line_subtotal_tax'];
					}
				}
			}
		}

		return $subtotal;
	}

}
