<?php
/**
 * Rule helper
 *
 * @package WooCommerce Points and Rewards
 * @version 1.0.0
 */

namespace DDWCPointsAndRewards\Helper\Rule;

use DDWCPointsAndRewards\Helper\Point\DDWCPR_Point_Helper;
use DDWCPointsAndRewards\Helper\Log\DDWCPR_Log_Helper;

defined( 'ABSPATH' ) || exit();

if ( ! class_exists( 'DDWCPR_Rule_Helper' ) ) {
	/**
	 * Rule helper class
	 */
	class DDWCPR_Rule_Helper {
		/**
		 * Database object
		 *
		 * @var object
		 */
		protected $wpdb;

		/**
		 * Configuration Variable
		 *
		 * @var array
		 */
		protected $ddwcpr_configuration;

		/**
		 * Point Helper Variable
		 *
		 * @var object
		 */
		protected $point_helper;

		/**
		 * Construct
		 */
		public function __construct( $ddwcpr_configuration ) {
			global $wpdb;
			$this->wpdb                 = $wpdb;
			$this->ddwcpr_configuration = $ddwcpr_configuration;
			$this->point_helper         = new DDWCPR_Point_Helper( $ddwcpr_configuration );
		}

		/**
		 * Save earning rule function
		 *
		 * @return int
		 */
		public function ddwcpr_save_earning_rule() {
			$name                     = ! empty( $_POST['_ddwcpr_rule_name'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_name'] ) ) : '';
			$description              = ! empty( $_POST['_ddwcpr_rule_description'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_description'] ) ) : '';
			$priority                 = ! empty( $_POST['_ddwcpr_rule_priority'] ) ? intval( $_POST['_ddwcpr_rule_priority'] ) : '';
			$type                     = ! empty( $_POST['_ddwcpr_rule_type'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_type'] ) ) : '';
			$points_type              = ! empty( $_POST['_ddwcpr_rule_points_type'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_points_type'] ) ) : '';
			$points_per_amount        = ! empty( $_POST['_ddwcpr_rule_points_per_amount'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_points_per_amount'] ) ) : '';
			$points_value             = ! empty( $_POST['_ddwcpr_rule_points_value'] ) ? intval( $_POST['_ddwcpr_rule_points_value'] ) : '';
			$applicable_to            = ! empty( $_POST['_ddwcpr_rule_applicable_to'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_applicable_to'] ) ) : '';
			$start_date               = ! empty( $_POST['_ddwcpr_rule_start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_start_date'] ) ) : NULL;
			$end_date                 = ! empty( $_POST['_ddwcpr_rule_end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_end_date'] ) ) : NULL;
			$icon                     = ! empty( $_POST['_ddwcpr_rule_icon'] ) ? intval( $_POST['_ddwcpr_rule_icon'] ) : NULL;
			$show                     = ! empty( $_POST['_ddwcpr_rule_show'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_show'] ) ) : '';
			$status                   = ! empty( $_POST['_ddwcpr_rule_status'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_status'] ) ) : '';

			if ( ! empty( $name ) && ! empty( $priority ) && ! empty( $type ) && ! empty( $show ) && ! empty( $status ) ) {
				$additional_data = compact( 'points_type', 'points_per_amount', 'points_value' );
				$data            = compact( 'name', 'description', 'priority', 'type', 'applicable_to', 'additional_data', 'start_date', 'end_date', 'icon', 'show', 'status' );

				$action = ! empty( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '';
				$id     = ! empty( $_GET['ddwcpr-id'] ) ? intval( sanitize_text_field( wp_unslash( $_GET['ddwcpr-id'] ) ) ) : 0;

				$default_data = [
					'name'            => '',
					'description'     => '',
					'priority'        => 1,
					'type'            => '',
					'applicable_to'   => '',
					'additional_data' => [],
					'start_date'      => NULL,
					'end_date'        => NULL,
					'icon'            => NULL,
					'show'            => 'show',
					'status'          => 'active',
				];

				$data = wp_parse_args( $data, $default_data );

				$data['additional_data'] = maybe_serialize( $data['additional_data'] );

				if ( 'edit' === $action && ! empty( $id ) ) {
					$this->wpdb->update(
						$this->wpdb->ddwcpr_earning_rules,
						$data,
						[ 'id' => $id ],
						[ '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s' ],
						[ '%d' ]
					);
				} else {
					$this->wpdb->insert(
						$this->wpdb->ddwcpr_earning_rules,
						$data,
						[ '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s' ]
					);
				}

				$page = ! empty( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
				$menu = ! empty( $_GET['menu'] ) ? sanitize_text_field( wp_unslash( $_GET['menu'] ) ) : '';

				if ( ! empty( $_GET['tab'] ) ) {
					$tab          = sanitize_text_field( wp_unslash( $_GET['tab'] ) );
					$redirect_url = admin_url( "admin.php?page={$page}&menu={$menu}&tab={$tab}&action=saved" );
				} else {
					$redirect_url = admin_url( "admin.php?page={$page}&menu={$menu}&action=saved" );
				}

				wp_safe_redirect( $redirect_url );
				exit();
			} else {
				ddfw_print_notification( esc_html__( 'Please fill all mandatory fields', 'loyaltyx-points-and-rewards-for-woocommerce' ), 'error' );
			}
		}

		/**
		 * Get earning rule by ID function
		 *
		 * @param string $id
		 * @return array
		 */
		public function ddwcpr_get_earning_rule_by_id( $id ) {
			$response   = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT DISTINCT * FROM {$this->wpdb->ddwcpr_earning_rules} WHERE id=%d", $id ), ARRAY_A );

			return apply_filters( 'ddwcpr_modify_earning_rule_data', $response, $id );
		}

		/**
		 * Prepare where conditions for earning rules function
		 *
		 * @param array $args
		 * @return string
		 */
		public function ddwcpr_prepare_where_conditions_for_earning_rules( $args ) {
			extract( $args );
			$conditions = '';

			if ( ! empty( $search ) ) {
				$conditions .= $this->wpdb->prepare( " AND name LIKE %s", '%' . $search . '%' );
			}

			if ( ! empty( $types ) ) {
				// Dynamically create placeholders for the IN clause
				$placeholders = implode( ', ', array_fill( 0, count( $types ), '%s' ) );

				$conditions .= $this->wpdb->prepare( " AND type IN ($placeholders)", $types );
			}

			if ( ! empty( $status ) ) {
				$conditions .= $this->wpdb->prepare( " AND status=%s", $status );
			}

			if ( ! empty( $current_date ) ) {
				$conditions .= $this->wpdb->prepare( " AND (start_date IS NULL OR start_date <= %s) AND (end_date IS NULL OR end_date >= %s)", $current_date, $current_date );
			}

			if ( ! empty( $status ) ) {
				$conditions .= $this->wpdb->prepare( " AND status=%s", $status );
			}

			return $conditions;
		}

		/**
		 * Get earning rules function
		 *
		 * @param array $args
		 * @return array
		 */
		public function ddwcpr_get_earning_rules( $args ) {
			$args['orderby'] = ! empty( $args['orderby'] ) ? $args['orderby'] : 'id';
			$args['order']   = ! empty( $args['order'] ) ? $args['order'] : 'DESC';

			extract( $args );

			$conditions = $this->ddwcpr_prepare_where_conditions_for_earning_rules( $args );
			$response   = $this->wpdb->get_results(
				$this->wpdb->prepare(
					"SELECT DISTINCT * FROM {$this->wpdb->ddwcpr_earning_rules} WHERE 1=1 $conditions ORDER BY %s %s LIMIT %d OFFSET %d",
					$orderby,
					$order,
					$per_page,
					$offset
				),
				ARRAY_A
			);

			return apply_filters( 'ddwcpr_modify_earning_rules_data', $response, $args );
		}

		/**
		 * Get earning rules count function
		 *
		 * @param array $args
		 * @return int
		 */
		public function ddwcpr_get_earning_rules_count( $args ) {
			$conditions = $this->ddwcpr_prepare_where_conditions_for_earning_rules( $args );
			$response   = intval( $this->wpdb->get_var( "SELECT count(DISTINCT id) FROM {$this->wpdb->ddwcpr_earning_rules} WHERE 1=1 $conditions" ) );

			return apply_filters( 'ddwcpr_modify_earning_rules_count', $response, $args );
		}

		/**
		 * Update earning rule function
		 *
		 * @param int $id
		 * @param string $status
		 * @return int|bool
		 */
		public function ddwcpr_update_earning_rule_status( $id, $status ) {
			return $this->wpdb->update(
				$this->wpdb->ddwcpr_earning_rules,
				[ 'status' => $status ],
				[ 'id' => $id ],
				[ '%s' ],
				[ '%d' ]
			);
		}

		/**
		 * Delete earning rule function
		 * 
		 * @param int $id
		 * @return int|bool
		 */
		public function ddwcpr_delete_earning_rule( $id ) {
			return $this->wpdb->delete(
				$this->wpdb->ddwcpr_earning_rules,
				[
					'id' => $id
				],
				[ '%d' ]
			);
		}

		/**
		 * Save redeeming rule function
		 *
		 * @return int
		 */
		public function ddwcpr_save_redeeming_rule() {
			$name                = ! empty( $_POST['_ddwcpr_rule_name'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_name'] ) ) : '';
			$description         = ! empty( $_POST['_ddwcpr_rule_description'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_description'] ) ) : '';
			$priority            = ! empty( $_POST['_ddwcpr_rule_priority'] ) ? intval( $_POST['_ddwcpr_rule_priority'] ) : '';
			$type                = ! empty( $_POST['_ddwcpr_rule_type'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_type'] ) ) : '';
			$discount_value      = ! empty( $_POST['_ddwcpr_rule_discount_value'] ) ? floatval( wp_unslash( $_POST['_ddwcpr_rule_discount_value'] ) ) : '';
			$points_value        = ! empty( $_POST['_ddwcpr_rule_points_value'] ) ? intval( wp_unslash( $_POST['_ddwcpr_rule_points_value'] ) ) : '';
			$coupon_label        = ! empty( $_POST['_ddwcpr_rule_coupon_label'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_coupon_label'] ) ) : '';
			$coupon_expiry       = ! empty( $_POST['_ddwcpr_rule_coupon_expiry'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_coupon_expiry'] ) ) : '';
			$applicable_to       = ! empty( $_POST['_ddwcpr_rule_applicable_to'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_applicable_to'] ) ) : '';
			$start_date          = ! empty( $_POST['_ddwcpr_rule_start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_start_date'] ) ) : NULL;
			$end_date            = ! empty( $_POST['_ddwcpr_rule_end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_end_date'] ) ) : NULL;
			$icon                = ! empty( $_POST['_ddwcpr_rule_icon'] ) ? intval( $_POST['_ddwcpr_rule_icon'] ) : NULL;
			$sharing             = ! empty( $_POST['_ddwcpr_rule_sharing'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_sharing'] ) ) : '';
			$show                = ! empty( $_POST['_ddwcpr_rule_show'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_show'] ) ) : '';
			$status              = ! empty( $_POST['_ddwcpr_rule_status'] ) ? sanitize_text_field( wp_unslash( $_POST['_ddwcpr_rule_status'] ) ) : '';

			if ( ! empty( $name ) && ! empty( $priority ) && ! empty( $type ) && ! empty( $coupon_label ) && ! empty( $sharing ) && ! empty( $show ) && ! empty( $status ) ) {
				$additional_data = compact( 'discount_value', 'points_value', 'coupon_label', 'coupon_expiry' );
				$data            = compact( 'name', 'description', 'priority', 'type', 'applicable_to', 'additional_data', 'start_date', 'end_date', 'icon', 'sharing', 'show', 'status' );

				$action = ! empty( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '';
				$id     = ! empty( $_GET['ddwcpr-id'] ) ? intval( sanitize_text_field( wp_unslash( $_GET['ddwcpr-id'] ) ) ) : 0;

				$default_data = [
					'name'            => '',
					'description'     => '',
					'priority'        => 1,
					'type'            => '',
					'applicable_to'   => 'all',
					'additional_data' => [],
					'start_date'      => NULL,
					'end_date'        => NULL,
					'icon'            => NULL,
					'sharing'         => 'yes',
					'show'            => 'show',
					'status'          => 'active',
				];

				$data = wp_parse_args( $data, $default_data );

				$data['additional_data'] = maybe_serialize( $data['additional_data'] );

				if ( 'edit' === $action && ! empty( $id ) ) {
					$this->wpdb->update(
						$this->wpdb->ddwcpr_redeeming_rules,
						$data,
						[ 'id' => $id ],
						[ '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s', '%s' ],
						[ '%d' ]
					);
				} else {
					$this->wpdb->insert(
						$this->wpdb->ddwcpr_redeeming_rules,
						$data,
						[ '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s', '%s' ]
					);
				}

				$page = ! empty( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
				$menu = ! empty( $_GET['menu'] ) ? sanitize_text_field( wp_unslash( $_GET['menu'] ) ) : '';

				if ( ! empty( $_GET['tab'] ) ) {
					$tab          = sanitize_text_field( wp_unslash( $_GET['tab'] ) );
					$redirect_url = admin_url( "admin.php?page={$page}&menu={$menu}&tab={$tab}&action=saved" );
				} else {
					$redirect_url = admin_url( "admin.php?page={$page}&menu={$menu}&action=saved" );
				}

				wp_safe_redirect( $redirect_url );
				exit();
			} else {
				ddfw_print_notification( esc_html__( 'Please fill all mandatory fields', 'loyaltyx-points-and-rewards-for-woocommerce' ), 'error' );
			}
		}

		/**
		 * Get redeeming rule by ID function
		 *
		 * @param string $id
		 * @return array
		 */
		public function ddwcpr_get_redeeming_rule_by_id( $id ) {
			$response   = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT DISTINCT * FROM {$this->wpdb->ddwcpr_redeeming_rules} WHERE id=%d", $id ), ARRAY_A );

			return apply_filters( 'ddwcpr_modify_redeeming_rule_data', $response, $id );
		}

		/**
		 * Prepare where conditions for redeeming rules function
		 *
		 * @param array $args
		 * @return string
		 */
		public function ddwcpr_prepare_where_conditions_for_redeeming_rules( $args ) {
			extract( $args );
			$conditions = '';

			if ( ! empty( $search ) ) {
				$conditions .= $this->wpdb->prepare( " AND name LIKE %s", '%' . $search . '%' );
			}

			if ( ! empty( $types ) ) {
				// Dynamically create placeholders for the IN clause
				$placeholders = implode( ', ', array_fill( 0, count( $types ), '%s' ) );

				$conditions .= $this->wpdb->prepare( " AND type IN ($placeholders)", $types );
			}

			if ( ! empty( $status ) ) {
				$conditions .= $this->wpdb->prepare( " AND status=%s", $status );
			}

			if ( ! empty( $current_date ) ) {
				$conditions .= $this->wpdb->prepare( " AND (start_date IS NULL OR start_date <= %s) AND (end_date IS NULL OR end_date >= %s)", $current_date, $current_date );
			}

			if ( ! empty( $status ) ) {
				$conditions .= $this->wpdb->prepare( " AND status=%s", $status );
			}

			return $conditions;
		}

		/**
		 * Get redeeming rules function
		 *
		 * @param array $args
		 * @return array
		 */
		public function ddwcpr_get_redeeming_rules( $args ) {
			$args['orderby'] = ! empty( $args['orderby'] ) ? $args['orderby'] : 'id';
			$args['order']   = ! empty( $args['order'] ) ? $args['order'] : 'DESC';

			extract( $args );

			$conditions = $this->ddwcpr_prepare_where_conditions_for_redeeming_rules( $args );
			$response   = $this->wpdb->get_results(
				$this->wpdb->prepare(
					"SELECT DISTINCT * FROM {$this->wpdb->ddwcpr_redeeming_rules} WHERE 1=1 $conditions ORDER BY %s %s LIMIT %d OFFSET %d",
					$orderby,
					$order,
					$per_page,
					$offset
				),
				ARRAY_A
			);

			return apply_filters( 'ddwcpr_modify_redeeming_rules_data', $response, $args );
		}

		/**
		 * Get redeeming rules count function
		 *
		 * @param array $args
		 * @return int
		 */
		public function ddwcpr_get_redeeming_rules_count( $args ) {
			$conditions = $this->ddwcpr_prepare_where_conditions_for_redeeming_rules( $args );
			$response   = intval( $this->wpdb->get_var( "SELECT count(DISTINCT id) FROM {$this->wpdb->ddwcpr_redeeming_rules} WHERE 1=1 $conditions" ) );

			return apply_filters( 'ddwcpr_modify_redeeming_rules_count', $response, $args );
		}

		/**
		 * Update redeeming rule function
		 *
		 * @param int $id
		 * @param string $status
		 * @return int|bool
		 */
		public function ddwcpr_update_redeeming_rule_status( $id, $status ) {
			return $this->wpdb->update(
				$this->wpdb->ddwcpr_redeeming_rules,
				[ 'status' => $status ],
				[ 'id' => $id ],
				[ '%s' ],
				[ '%d' ]
			);
		}

		/**
		 * Delete redeeming rule function
		 * 
		 * @param int $id
		 * @return int|bool
		 */
		public function ddwcpr_delete_redeeming_rule( $id ) {
			return $this->wpdb->delete(
				$this->wpdb->ddwcpr_redeeming_rules,
				[
					'id' => $id
				],
				[ '%d' ]
			);
		}

		/**
		 * Get display points earning message function
		 *
		 * @param int $points
		 * @param string $message
		 * @param string $layout
		 * @return string
		 */
		public function ddwcpr_get_display_points_earning_message( $points, $message, $layout = 'product' ) {
			$message = str_replace(
				[
					'{points_value}',
					'{points_label}',
				],
				[
					$points,
					ddwcpr_get_points_label( $points ),
				],
				$message
			);

			if ( 'shop' === $layout ) {
				?>
				<div class="ddwcpr-earning-points-message-shop-loop">
				<?php
			}
			?>
			<div
				class="ddwcpr-earning-points-message"
				style="
					background-color: <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['background_color'] ); ?>;
					color           : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['color'] ); ?>;
					border          : solid 1px <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['border_color'] ); ?>;
					font-size       : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['font_size'] ); ?>;
					padding         : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['padding'] ); ?>;
					margin          : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['margin'] ); ?>;
					border-radius   : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['border_radius'] ); ?>;
					"
				>
				<p><?php echo wp_kses( $message, array_merge( wp_kses_allowed_html( 'post' ), ddfw_kses_allowed_svg_tags() ) ); ?></p>
			</div>
			<?php
			if ( 'shop' === $layout ) {
				?>
				</div>
				<?php
			}
		}

		/**
		 * Get display points redeeming message function
		 *
		 * @param string $message
		 * @param string $layout
		 * @return string
		 */
		public function ddwcpr_get_display_points_redeeming_message( $message ) {
			$user_available_points =$this->point_helper->ddwcpr_get_user_available_points( get_current_user_id() );

			if ( $user_available_points <= 0 ) {
				return;
			}

			$message = str_replace(
				[
					'{user_available_points}',
					'{points_label}',
					'{choose_rewards_link}',
				],
				[
					$user_available_points,
					ddwcpr_get_points_label( $user_available_points ),
					'<a href="javascript:void(0);" id="ddwcpr-choose-rewards-link">' . esc_html__( 'Choose Rewards', 'loyaltyx-points-and-rewards-for-woocommerce' ) . '</a>',
				],
				$message
			);

			?>
			<div
				class="ddwcpr-earning-points-message"
				style="
					background-color: <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['background_color'] ); ?>;
					color           : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['color'] ); ?>;
					border          : solid 1px <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['border_color'] ); ?>;
					font-size       : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['font_size'] ); ?>;
					padding         : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['padding'] ); ?>;
					margin          : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['margin'] ); ?>;
					border-radius   : <?php echo esc_attr( $this->ddwcpr_configuration['points_message_styling']['border_radius'] ); ?>;
					"
				>
				<p><?php echo wp_kses( $message, array_merge( wp_kses_allowed_html( 'post' ), ddfw_kses_allowed_svg_tags() ) ); ?></p>
			</div>
			<div class="ddwcpr-popup-overlay" id="choose_rewards">
				<div class="ddwcpr-popup-content">
					<button class="ddwcpr-popup-close">×</button>
					<div class="ddwcpr-rewards-popup-container">
						<?php
						// Add current_tab="rewards" to the shortcode stored in the configuration variable.
						$shortcode = $this->ddwcpr_configuration['points_dashboard_shortcode'];
						// Remove the trailing ']' if present, then append the attribute and close the bracket.
						$shortcode = rtrim( $shortcode, ']' ) . ' current_tab="rewards"]';
						echo do_shortcode( $shortcode );
						?>
					</div>
				</div>
			</div>
			<?php
		}

		/**
		 * Calculate earning points by product ID function
		 *
		 * @param int $product_id
		 * @return int
		 */
		public function ddwcpr_calculate_earning_points_by_product_id( $product_id ) {
			$product = wc_get_product( $product_id );

			if ( ! $product ) {
				return 0;
			}

			if ( 'variable' === $product->get_type() ) {
				// Fetch min and max price for the variable product
				$min_price = $product->get_variation_price( 'min' ); // Minimum price
				$max_price = $product->get_variation_price( 'max' ); // Maximum price

				// Include/Exclude tax in points calculation
				if ( ! empty( $this->ddwcpr_configuration['points_earning_include_taxes_enabled'] ) ) {
					$min_amount = wc_get_price_including_tax( $product, [ 'price' => $min_price ] );
					$max_amount = wc_get_price_including_tax( $product, [ 'price' => $max_price ] );
				} else {
					$min_amount = wc_get_price_excluding_tax( $product, [ 'price' => $min_price ] );
					$max_amount = wc_get_price_excluding_tax( $product, [ 'price' => $max_price ] );
				}

				$min_points = $this->ddwcpr_calculate_earning_points_for_amount( $min_amount, $product_id, $product );
				$max_points = $this->ddwcpr_calculate_earning_points_for_amount( $max_amount, $product_id, $product );
			} elseif ( 'simple' === $product->get_type() || 'variation' === $product->get_type() ) {
				// Include/Exclude tax in points calculation
				if ( ! empty( $this->ddwcpr_configuration['points_earning_include_taxes_enabled'] ) ) {
					$amount = wc_get_price_including_tax( $product );
				} else {
					$amount = wc_get_price_excluding_tax( $product );
				}

				$points = $this->ddwcpr_calculate_earning_points_for_amount( $amount, $product_id, $product );
			}

			return ! empty( $points ) ? $points : ( ! empty( $max_points ) ? "$min_points-$max_points" : 0 );
		}

		/**
		 * Calculate points for amount function
		 *
		 * @param float $amount
		 * @param int|null $product_id
		 * @param object|null $product_id
		 * @return int
		 */
		public function ddwcpr_calculate_earning_points_for_amount( $amount, $product_id = null, $product = null ) {
			$points = 0;

			if ( $product_id ) {
				if ( ! $product ) {
					$product = wc_get_product( $product_id );

					if ( ! $product ) {
						return $points;
					}
				}

				$product_exclude_flag = (
					(
						! empty( $this->ddwcpr_configuration['points_earning_exclude_sale_products_enabled'] )
						&& $product->is_on_sale()
					)
					|| in_array( strval( $product_id ), $this->ddwcpr_configuration['points_earning_excluded_products'], true )
					|| ! empty( array_intersect( $this->ddwcpr_configuration['points_earning_excluded_categories'], wc_get_product_cat_ids( $product_id ) ) )
				);

				if ( $product_exclude_flag ) {
					return $points;
				}
			}

			$rules = $this->ddwcpr_get_earning_rules( [
				'per_page'     => 100,
				'offset'       => 0,
				'status'       => 'active',
				'current_date' => current_time( 'Y-m-d' ),
				'types'        => [ 'product_purchase', 'purchase_amount' ],
				'orderby'      => 'priority',
				'order'        => 'ASC', // Lower priority number = higher priority
			] );

			if ( ! empty( $rules ) ) {
				$user = wp_get_current_user();

				foreach ( $rules as $rule ) {
					$additional_data = maybe_unserialize( $rule['additional_data'] );

					if ( 'product_purchase' === $rule['type'] && $product_id ) {
						$product_flag = (
							'all_products' === $additional_data['apply_to_products']
							|| ( 
								'on_sale_products' === $additional_data['apply_to_products']
								&& $product->is_on_sale()
							)
							|| (
								'specific_products' === $additional_data['apply_to_products']
								&& in_array( $product_id, $additional_data['applied_products'], true )
							)
							|| (
								'specific_product_categories' === $additional_data['apply_to_products']
								&& ! empty( array_intersect( $additional_data['applied_categories'], wc_get_product_cat_ids( 'variation' === $product->get_type() ? $product->get_parent_id() : $product_id ) ) )
							)
						);

						if ( $product_flag ) {
							$points = $this->ddwcpr_calculate_points_for_rule( $amount, $additional_data, $rule );
							// Break after finding first matching product_purchase rule
							break;
						}
					} elseif ( 'purchase_amount' === $rule['type'] ) {
						// Check if amount meets the minimum order value requirement
						if ( ! empty( $additional_data['minimum_order_value'] ) && $amount < floatval( $additional_data['minimum_order_value'] ) ) {
							// Continue to next rule if minimum order value is not met
							continue;
						} else {
							$points = $this->ddwcpr_calculate_points_for_rule( $amount, $additional_data, $rule );
							// Break after finding first matching purchase_amount rule
							break;
						}
					}
				}
			}

			return $points;
		}

		/**
		 * Calculate points for rule function
		 *
		 * @param float $amount
		 * @param array $additional_data
		 * @param array $rule
		 * @return int
		 */
		public function ddwcpr_calculate_points_for_rule( $amount, $additional_data, $rule ) {
			$points = 0;

			if ( ! empty( $amount ) ) {
				if ( ! empty( $additional_data ) ) {
					if ( 'fixed_points_based_on_amount' === $additional_data['points_type'] ) {
						$points = $amount * $additional_data['points_value'] / $additional_data['points_per_amount'];
					} elseif ( 'fixed_points' === $additional_data['points_type'] ) {
						$points = $additional_data['points_value'];
					} elseif ( 'percentage_points' === $additional_data['points_type'] ) {
						$points = $additional_data['points_value'] * $amount / 100;
					}
				} else {
					$points = $amount * $this->ddwcpr_configuration['points_earning_value'] / $this->ddwcpr_configuration['points_earning_per_amount'];
				}

				if ( 'round_to_nearest' === $this->ddwcpr_configuration['points_earning_rounding'] ) {
					$points = round( $points );
				} elseif ( 'round_up' === $this->ddwcpr_configuration['points_earning_rounding'] ) {
					$points = ceil( $points );
				} elseif ( 'round_down' === $this->ddwcpr_configuration['points_earning_rounding'] ) {
					$points = floor( $points );
				}
			}

			return $points;
		}

		/**
		 * Calculate cart earning points function
		 *
		 * @return int
		 */
		public function ddwcpr_calculate_cart_earning_points() {
			$points = 0;

			foreach ( WC()->cart->get_cart() as $cart_item ) {
				$product_id = ! empty( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : $cart_item['product_id'];

				if ( ! empty( $this->ddwcpr_configuration['points_earning_exclude_coupon_enabled'] ) ) {
					$amount = ! empty( $this->ddwcpr_configuration['points_earning_include_taxes_enabled'] ) ? $cart_item['line_total'] + $cart_item['line_tax'] : $cart_item['line_total'];
				} else {
					$amount = ! empty( $this->ddwcpr_configuration['points_earning_include_taxes_enabled'] ) ? $cart_item['line_subtotal'] + $cart_item['line_subtotal_tax'] : $cart_item['line_subtotal'];
				}

				$points += $this->ddwcpr_calculate_earning_points_for_amount( $amount, $product_id );
			}

			if ( ! empty( $this->ddwcpr_configuration['points_earning_include_shipping_enabled'] ) ) {
				$shipping_total = WC()->cart->get_shipping_total();

				if ( ! empty( $this->ddwcpr_configuration['points_earning_include_taxes_enabled'] ) ) {
					$shipping_total += WC()->cart->get_shipping_tax();
				}

				if ( $shipping_total > 0 ) {
					$points += $this->ddwcpr_calculate_earning_points_for_amount( $shipping_total );
				}
			}

			return $points;
		}

		/**
		 * Calculate cart points function
		 *
		 * @param object $order
		 * @param boolean $add_item_meta
		 * @return int
		 */
		public function ddwcpr_calculate_order_earning_points( $order, $add_item_meta = false ) {
			$points = 0;

			foreach ( $order->get_items() as $item_id => $item ) {
				$variation_id = $item->get_variation_id();
				$product_id   = ! empty( $variation_id ) ? $variation_id : $item->get_product_id();

				if ( ! empty( $this->ddwcpr_configuration['points_earning_exclude_coupon_enabled'] ) ) {
					$amount = ! empty( $this->ddwcpr_configuration['points_earning_include_taxes_enabled'] ) ? $item->get_total() + $item->get_subtotal_tax() : $item->get_total();
				} else {
					$amount = ! empty( $this->ddwcpr_configuration['points_earning_include_taxes_enabled'] ) ? $item->get_subtotal() + $item->get_subtotal_tax() : $item->get_subtotal();
				}

				$item_points = $this->ddwcpr_calculate_earning_points_for_amount( $amount, $product_id );

				if ( $item_points > 0 && $add_item_meta ) {
					wc_add_order_item_meta( $item_id, '_ddwcpr_earned_points', $item_points );
				}

				$points += $item_points;
			}

			if ( ! empty( $this->ddwcpr_configuration['points_earning_include_shipping_enabled'] ) ) {
				$shipping_total = $order->get_shipping_total();

				if ( ! empty( $this->ddwcpr_configuration['points_earning_include_taxes_enabled'] ) ) {
					$shipping_total += $order->get_shipping_tax();
				}

				if ( $shipping_total > 0 ) {
					$shipping_points = $this->ddwcpr_calculate_earning_points_for_amount( $shipping_total );
					$points += $shipping_points;

					if ( $shipping_points > 0 && $add_item_meta ) {
						foreach ( $order->get_items( 'shipping' ) as $item_id => $shipping_item ) {
							wc_add_order_item_meta( $item_id, '_ddwcpr_earned_points', $shipping_points );
						}
					}
				}
			}

			return $points;
		}

		/**
		 * Get points for simple earning rule function
		 *
		 * @param string $type
		 * @param int|null $user_id
		 * @param int|null $level_id
		 * @param int|null $rating
		 * @return int
		 */
		public function ddwcpr_calculate_points_for_simple_earning_rule( $type, $user_id = null, $level_id = null, $rating = null ) {
			$points = 0;

			$rules = $this->ddwcpr_get_earning_rules( [
				'per_page'     => 100,
				'offset'       => 0,
				'status'       => 'active',
				'current_date' => current_time( 'Y-m-d' ),
				'types'        => [ $type ],
				'orderby'      => 'priority',
				'order'        => 'ASC',
			] );

			if ( ! empty( $rules ) ) {
				if ( ! empty( $user_id ) ) {
					$user = get_userdata( $user_id );
				} else {
					$user = wp_get_current_user();
				}

				foreach ( $rules as $rule ) {
					$additional_data = maybe_unserialize( $rule['additional_data'] );
					$points          = $additional_data['points_value'];

					return $points;
				}
			}

			return $points;
		}

		/**
		 * Calculate earning points for review submission function
		 *
		 * @param int $product_id
		 * @param object $product_id
		 * @param int $user_id
		 * @return int
		 */
		public function ddwcpr_calculate_earning_points_for_review_submission( $product_id, $product, $user_id, $rating ) {
			$points = 0;

			if ( $product_id ) {
				if ( ! $product ) {
					$product = wc_get_product( $product_id );

					if ( ! $product ) {
						return $points;
					}
				}

				$product_exclude_flag = (
					(
						! empty( $this->ddwcpr_configuration['points_earning_exclude_sale_products_enabled'] )
						&& $product->is_on_sale()
					)
					|| in_array( strval( $product_id ), $this->ddwcpr_configuration['points_earning_excluded_products'], true )
					|| ! empty( array_intersect( $this->ddwcpr_configuration['points_earning_excluded_categories'], wc_get_product_cat_ids( $product_id ) ) )
				);

				if ( $product_exclude_flag ) {
					return $points;
				}
			}

			return $this->ddwcpr_calculate_points_for_simple_earning_rule( 'review_submission', $user_id, null, $rating );
		}

		/**
		 * Award birthday points function
		 *
		 * @return void
		 */
		public function ddwcpr_award_birthday_points() {
			// Get today's month and day
			$today_month = current_time( 'm' );
			$today_day   = current_time( 'd' );

			// Query to get users whose birthday matches today
			$users = $this->wpdb->get_results(
				$this->wpdb->prepare(
					"SELECT u.ID
					FROM {$this->wpdb->users} AS u
					INNER JOIN {$this->wpdb->usermeta} AS um
						ON u.ID = um.user_id
					WHERE um.meta_key = '_ddwcpr_birthday'
					AND DATE_FORMAT(um.meta_value, '%%m-%%d') = %s",
					"{$today_month}-{$today_day}"
				),
				ARRAY_A
			);

			$log_helper = new DDWCPR_Log_Helper( $this->ddwcpr_configuration );

			foreach ( $users as $user ) {
				$user_id = $user['ID'];

				if ( $log_helper->ddwcpr_check_birthday_log_exists( $user_id, current_time( 'Y' ) ) ) {
					continue;
				}

				$points_for_birthday = $this->ddwcpr_calculate_points_for_simple_earning_rule( 'birthday', $user_id );

				if ( $points_for_birthday > 0 ) {
					// Award earned points
					$data = [
						'points'      => $points_for_birthday,
						'user_id'     => $user_id,
						'description' => sprintf( /* translators: 1: Points label */ esc_html__( 'Points awarded for birthday (%s)', 'loyaltyx-points-and-rewards-for-woocommerce' ), ddwcpr_get_points_label( $points_for_birthday ) ),
						'event'       => 'birthday',
					];

					$this->point_helper->ddwcpr_add_user_points( $data );
				}
			}
		}
	}
}
