<?php
/**
 * File: ecre-functions.php
 *
 * This file contains functions for coupon code generation and management.
 *
 * @package  ECRE
 * @since   1.0.0
 */

$ecre_plugin_list = function_exists( 'get_option' ) ? \get_option( 'active_plugins' ) : array();

if ( function_exists( 'is_multisite' ) && is_multisite() && function_exists( 'get_site_option' ) ) {
	$ecre_network_active_plugins = get_site_option( 'active_sitewide_plugins', array() );
	$ecre_plugin_list            = array_merge( $ecre_plugin_list, array_keys( $ecre_network_active_plugins ) );
}

if ( in_array( 'woocommerce/woocommerce.php', $ecre_plugin_list, true ) ) {
	if ( ! function_exists( 'ecre_generate_unique_coupon_code' ) ) {
		/**
		 * Generate a unique coupon code.
		 *
		 * Creates a random 13-character lowercase alphanumeric coupon code and ensures
		 * it is unique by checking against existing WooCommerce coupons. If a collision
		 * occurs, a new code is generated until a unique one is found.
		 *
		 * @since 1.0.0
		 *
		 * @return string The generated unique coupon code (13 characters, lowercase alphanumeric).
		 */
		function ecre_generate_unique_coupon_code() {
			$code = strtolower( wp_generate_password( 8, false ) );

			// Ensure uniqueness using WooCommerce function.
			while ( wc_get_coupon_id_by_code( $code ) > 0 ) {
				$code = strtolower( wp_generate_password( 8, false ) );
			}

			return $code;
		}
	}

	if ( ! function_exists( 'ecre_coupon_exists' ) ) {
		/**
		 * Check if a coupon with the given code exists.
		 *
		 * Checks the WooCommerce database to determine if a coupon with the specified
		 * code already exists in the system.
		 *
		 * @since 1.0.0
		 *
		 * @param string $code The coupon code to check.
		 *
		 * @return bool True if the coupon exists, false otherwise.
		 */
		function ecre_coupon_exists( $code ) {
			return wc_get_coupon_id_by_code( $code ) > 0;
		}
	}

	if ( ! function_exists( 'ecre_coupon_exists_old' ) ) {
		/**
		 * Check if a coupon with the given code exists.
		 *
		 * @param string $code The coupon code to check.
		 *
		 * @return bool Whether a coupon with the given code exists.
		 *
		 * @since 1.0.0
		 */
		function ecre_coupon_exists_old( $code ) {
			global $wpdb;

			$coupon_id = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT ID FROM {$wpdb->posts} 
					WHERE post_type = %s 
					AND post_title = %s 
					AND post_status IN ('publish', 'draft', 'pending', 'private')
					LIMIT 1",
					'shop_coupon',
					$code
				)
			);

			return ! empty( $coupon_id );
		}
	}

	if ( ! function_exists( 'ecre_referral_coupons' ) ) {
		/**
		 * Get referral coupons for the current user.
		 *
		 * @return array An array of referral coupon codes for the current user.
		 *
		 * @since 1.0.0
		 */
		function ecre_referral_coupons() {
			$referral_user_id = get_current_user_id();

			// Try to get from cache first.
			$cache_key      = 'ecre_referral_coupon_' . $referral_user_id;
			$cached_coupons = wp_cache_get( $cache_key, 'ecre_coupons' );

			if ( false !== $cached_coupons ) {
				return $cached_coupons;
			}

			global $wpdb;

			// Direct database query - much faster than WP_Query with meta_query.
			$result = $wpdb->get_row(
				$wpdb->prepare(
					"SELECT 
						p.ID as coupon_id,
						p.post_title as coupon_code,
						p.post_date as post_date,
						pm_discount_type.meta_value as discount_type,
						pm_amount.meta_value as discount
					FROM {$wpdb->posts} p
					INNER JOIN {$wpdb->postmeta} pm_referral 
						ON p.ID = pm_referral.post_id 
						AND pm_referral.meta_key = 'referral_user_id'
						AND pm_referral.meta_value = %d
					LEFT JOIN {$wpdb->postmeta} pm_discount_type 
						ON p.ID = pm_discount_type.post_id 
						AND pm_discount_type.meta_key = 'discount_type'
					LEFT JOIN {$wpdb->postmeta} pm_amount 
						ON p.ID = pm_amount.post_id 
						AND pm_amount.meta_key = 'coupon_amount'
					WHERE p.post_type = 'shop_coupon'
					AND p.post_status = 'publish'
					ORDER BY p.post_date ASC
					LIMIT 1",
					$referral_user_id
				),
				ARRAY_A
			);

			$coupons = array();

			if ( $result ) {
				$coupon_details = array(
					'coupon_code'   => $result['coupon_code'],
					'discount_type' => $result['discount_type'],
					'discount'      => $result['discount'],
					'generated_at'  => gmdate( 'M d, Y', strtotime( $result['post_date'] ) ),
					'coupon_id'     => $result['coupon_id'],
				);

				$coupons[] = $coupon_details;
			}

			// Cache for 5 minutes.
			wp_cache_set( $cache_key, $coupons, 'ecre_coupons', 30 );
			return $coupons;
		}

	}

	if ( ! function_exists( 'ecre_referral_coupons_with_usage' ) ) {
		/**
		 * Retrieve an array of details for orders that used coupons with a referral_user_id,
		 * excluding orders of the current user.
		 *
		 * @return array An array of order details.
		 */
		function ecre_referral_coupons_with_usage() {
			global $wpdb;

			$user_id = get_current_user_id();

			// Attempt to retrieve cached results.
			$cached_results = wp_cache_get( 'ecre_pro_referral_coupon_invites_' . $user_id );

			// If cached results are not available, execute the database query and cache the results.
			if ( false === $cached_results ) {
				$results = $wpdb->get_results(
					$wpdb->prepare(
						"
						SELECT orders.id, 
							orders.status, 
							orders.date_created_gmt, 
							orders.billing_email, 
							postmeta_completed.meta_value AS referral_status
						FROM {$wpdb->prefix}wc_orders AS orders
						INNER JOIN {$wpdb->prefix}postmeta AS postmeta_referral 
							ON orders.id = postmeta_referral.post_id
						LEFT JOIN {$wpdb->prefix}postmeta AS postmeta_completed 
							ON orders.id = postmeta_completed.post_id 
							AND postmeta_completed.meta_key = 'ecre_referral_order_completed'
						WHERE postmeta_referral.meta_key = '_referral_user_id'
						AND postmeta_referral.meta_value = %d
						AND orders.status <> 'trash'
						",
						$user_id
					),
					ARRAY_A
				);

				// Cache the results.
				wp_cache_set( 'ecre_pro_referral_coupon_invites_' . $user_id, $results, '', 3600 );

				// Assign the results to the cached_results variable.
				$cached_results = $results;
			}

			return $cached_results;
		}
	}

	if ( ! function_exists( 'ecre_reward_coupons' ) ) {
		/**
		 * Get reward coupons for the current user.
		 *
		 * @return array An array of reward coupon codes for the current user.
		 *
		 * @since 1.0.0
		 */
		function ecre_reward_coupons() {
			global $wpdb;
			$reward_user_id = get_current_user_id();

			$query = "
				SELECT 
					p.ID as coupon_id,
					p.post_title as coupon_code,
					p.post_date as generated_at,
					COALESCE(pm1.meta_value, '') as discount_type,
					COALESCE(pm2.meta_value, '') as discount,
					COALESCE(pm3.meta_value, '') as usage_limit,
					COALESCE(pm4.meta_value, '') as usage_count,
					COALESCE(erc.expires_at, pm_expiry.meta_value, pm5.meta_value, '') as expiration_date
				FROM 
					{$wpdb->prefix}posts p
				LEFT JOIN 
					{$wpdb->prefix}postmeta pm1 ON p.ID = pm1.post_id AND pm1.meta_key = 'discount_type'
				LEFT JOIN 
					{$wpdb->prefix}postmeta pm2 ON p.ID = pm2.post_id AND pm2.meta_key = 'coupon_amount'
				LEFT JOIN 
					{$wpdb->prefix}postmeta pm3 ON p.ID = pm3.post_id AND pm3.meta_key = 'usage_limit'
				LEFT JOIN 
					{$wpdb->prefix}postmeta pm4 ON p.ID = pm4.post_id AND pm4.meta_key = 'usage_count'
				LEFT JOIN 
					{$wpdb->prefix}postmeta pm5 ON p.ID = pm5.post_id AND pm5.meta_key = 'date_expires'
				LEFT JOIN 
					{$wpdb->prefix}postmeta pm_expiry ON p.ID = pm_expiry.post_id AND pm_expiry.meta_key = 'expiry_date'
				LEFT JOIN 
					{$wpdb->prefix}ecre_reward_coupons erc ON p.ID = erc.coupon_id
				WHERE 
					p.post_type = 'shop_coupon'
					AND p.post_status = 'publish'
					AND EXISTS (
						SELECT 1 
						FROM {$wpdb->prefix}postmeta pm
						WHERE pm.post_id = p.ID 
						AND pm.meta_key = 'reward_user_id'
						AND pm.meta_value = %d
					)
				ORDER BY 
					p.post_date ASC
			";
			// phpcs:ignore
			$results = $wpdb->get_results( $wpdb->prepare( $query, $reward_user_id ) );

			// Process results to ensure date format is correct for frontend.
			if ( ! empty( $results ) ) {
				foreach ( $results as $key => $coupon ) {
					if ( ! empty( $coupon->expiration_date ) ) {
						// Check if it's a timestamp (numeric).
						if ( is_numeric( $coupon->expiration_date ) ) {
							$results[ $key ]->expiration_date = gmdate( 'Y-m-d', $coupon->expiration_date );
						} elseif ( strpos( $coupon->expiration_date, '0000-00-00' ) !== false ) {
							$results[ $key ]->expiration_date = '';
						}
					}
				}
			}

			return $results;
		}

	}

	if ( ! function_exists( 'ecre_has_orders' ) ) {
		/**
		 * Check if a user has at least one order in WooCommerce.
		 *
		 * @return bool True if the user has at least one order, false otherwise.
		 */
		function ecre_has_orders() {
			$user_id = get_current_user_id();

			// Get completed orders for the user.
			$args = array(
				'customer' => $user_id,
			);

			$user_completed_orders = wc_get_orders( $args );

			// Check if the user has at least one completed order.
			return ! empty( $user_completed_orders ) ? true : false;
		}
	}


	if ( ! function_exists( 'ecre_custom_currency_symbol' ) ) {
		/**
		 * Get WooCommerce currency symbol
		 *
		 * @return string The currency symbol
		 */
		function ecre_custom_currency_symbol() {
			// If WooCommerce is active, use its function to get currency symbol.
			if ( function_exists( 'get_woocommerce_currency_symbol' ) ) {
				$ecre_currency_sign = get_woocommerce_currency_symbol();
				$ecre_currency_sign = str_replace( '&nbsp;', '', $ecre_currency_sign );
				$ecre_currency_sign = html_entity_decode( $ecre_currency_sign );

				return $ecre_currency_sign;
			} else {
				return '$';
			}
		}
	}

	if ( ! function_exists( 'ecre_get_currency_settings' ) ) {
		/**
		 * Get all WooCommerce currency settings
		 *
		 * @return array Array containing all currency settings
		 */
		function ecre_get_currency_settings() {
			$settings = array(
				'symbol'             => '$',
				'position'           => 'left',
				'thousand_separator' => ',',
				'decimal_separator'  => '.',
				'decimals'           => 2,
			);

			// If WooCommerce is active, get actual settings.
			if ( function_exists( 'get_woocommerce_currency_symbol' ) && function_exists( 'get_option' ) ) {
				// Get currency symbol.
				$currency_symbol = get_woocommerce_currency_symbol();
				$currency_symbol = str_replace( '&nbsp;', '', $currency_symbol );
				$currency_symbol = html_entity_decode( $currency_symbol );

				$settings['symbol']             = $currency_symbol;
				$settings['position']           = get_option( 'woocommerce_currency_pos', 'left' );
				$settings['thousand_separator'] = get_option( 'woocommerce_price_thousand_sep', ',' );
				$settings['decimal_separator']  = get_option( 'woocommerce_price_decimal_sep', '.' );
				$settings['decimals']           = absint( get_option( 'woocommerce_price_num_decimals', 2 ) );
			}

			return $settings;
		}
	}

	if ( ! function_exists( 'ecre_format_price' ) ) {
		/**
		 * Format price with currency symbol and separators based on WooCommerce settings
		 *
		 * @param float|string $price The price to format.
		 * @param bool         $include_symbol Whether to include currency symbol (default: true).
		 * @return string The formatted price with currency symbol
		 */
		function ecre_format_price( $price, $include_symbol = true ) {
			// Get all currency settings.
			$settings = ecre_get_currency_settings();

			// Format the price with proper separators and decimals.
			$formatted_price = number_format(
				(float) $price,
				$settings['decimals'],
				$settings['decimal_separator'],
				$settings['thousand_separator']
			);

			// Return without symbol if requested.
			if ( ! $include_symbol ) {
				return $formatted_price;
			}

			// Add currency symbol based on position.
			switch ( $settings['position'] ) {
				case 'left':
					return $settings['symbol'] . $formatted_price;

				case 'right':
					return $formatted_price . $settings['symbol'];

				case 'left_space':
					return $settings['symbol'] . ' ' . $formatted_price;

				case 'right_space':
					return $formatted_price . ' ' . $settings['symbol'];

				default:
					return $settings['symbol'] . $formatted_price;
			}
		}
	}

	if ( ! function_exists( 'ecre_email_preview_data' ) ) {
		/**
		 * Retrieves data for email preview.
		 *
		 * This function fetches various settings and data necessary for email preview,
		 * including referral and reward discounts, coupon codes, etc.
		 *
		 * @since 1.0.0
		 *
		 * @return array An array containing email preview data including:
		 *               - 'referral_discount': The referral discount value with currency sign or percent.
		 *               - 'reward_discount': The reward discount value with currency sign or percent.
		 *               - 'referral_coupon_code': The referral coupon code.
		 *               - 'reward_coupon_code': The reward coupon code.
		 */
		function ecre_email_preview_data() {
			$ecre_currency_sign     = ecre_custom_currency_symbol();
			$referral_discount      = '';
			$reward_discount        = '';
			$referral_discount_type = '';
			$reward_discount_type   = '';
			$coupon_code            = '75V5KLDA';
			$referral_coupon_code   = '';
			$current_user_id        = get_current_user_id();
			$referral_coupon        = get_user_meta( $current_user_id, 'ecre_referral_coupon', true );

			$referral_discount      = get_option( 'ecre_referral_discount' );
			$referral_discount_type = get_option( 'ecre_referral_discount_type' );

			$referral_coupon_code = $referral_coupon ? $referral_coupon : 'ECHO75V5KLDA';

			if ( 'percent' === $referral_discount_type ) {
				$referral_discount = $referral_discount . '% ';
			} else {
				$referral_discount = $referral_discount . $ecre_currency_sign;
			}

			$reward_discount      = get_option( 'ecre_reward_discount' );
			$reward_discount_type = get_option( 'ecre_reward_discount_type' );

			if ( 'percent' === $reward_discount_type ) {
				$reward_discount = $reward_discount . '%';
			} else {
				$reward_discount = $reward_discount . $ecre_currency_sign;
			}

			$data = array(
				'referral_discount'    => $referral_discount,
				'reward_discount'      => $reward_discount,
				'referral_coupon_code' => $referral_coupon_code,
				'reward_coupon_code'   => $coupon_code,
			);
			return $data;
		}
	}

	if ( ! function_exists( 'ecre_check_pro_plugin_exists' ) ) {
		/**
		 * Check if pro exists.
		 */
		function ecre_check_pro_plugin_exists() {
			return file_exists( WP_PLUGIN_DIR . '/echo-rewards-pro/echo-rewards.php' );
		}
	}



	if ( ! function_exists( 'ecre_get_all_product_categories' ) ) {
		/**
		 * Retrieves all product categories.
		 *
		 * This function fetches all product categories, including empty ones.
		 *
		 * @return array List of product categories. Returns an empty array if an error occurs.
		 */
		function ecre_get_all_product_categories() {
			$args = array(
				'taxonomy'   => 'product_cat',
				'hide_empty' => false,
			);

			$product_categories = get_terms( $args );

			if ( ! is_wp_error( $product_categories ) ) {
				return $product_categories;
			} else {
				return array();
			}
		}
	}

	/**
	 * Update all referral coupons based on settings with cancellation support.
	 */
	function ecre_update_referral_coupons( $settings, $process_id = null ) {
		global $wpdb;

		$currency_symbol     = ecre_pro_custom_currency_symbol();
		$coupon_prefix       = $settings['referralCouponPrefix'];
		$coupon_prefix_upper = strtoupper( $coupon_prefix );
		$coupon_prefix_lower = strtolower( $coupon_prefix );
		$referral_discount   = $settings['referralDiscount'];
		$discount_type       = $settings['referralCouponType']['value'];
		$discount            = ( 'percent' === $discount_type ) ? $referral_discount . '%' : $referral_discount . $currency_symbol;

		$selected_product_ids      = isset( $settings['referralIncludeProducts'] ) && is_array( $settings['referralIncludeProducts'] ) ? array_column( $settings['referralIncludeProducts'], 'value' ) : array();
		$exclude_product_ids       = isset( $settings['referralExcludeProducts'] ) && is_array( $settings['referralExcludeProducts'] ) ? array_column( $settings['referralExcludeProducts'], 'value' ) : array();
		$selected_categories       = isset( $settings['referralIncludeCategories'] ) && is_array( $settings['referralIncludeCategories'] ) ? array_column( $settings['referralIncludeCategories'], 'value' ) : array();
		$exclude_categories        = isset( $settings['referralExcludeCategories'] ) && is_array( $settings['referralExcludeCategories'] ) ? array_column( $settings['referralExcludeCategories'], 'value' ) : array();
		$enable_subscription_limit = $settings['enableReferralLimitSubscriptionCoupon'];
		$subscription_limit        = $settings['referralLimitSubscriptionCoupon'];

		$prefix_length = strlen( $coupon_prefix_lower );

		// Update coupon posts with uppercase prefix in one query.
		$wpdb->query(
			$wpdb->prepare(
				"
				UPDATE {$wpdb->posts} AS p
				INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id
				LEFT JOIN {$wpdb->postmeta} AS pm_custom ON p.ID = pm_custom.post_id AND pm_custom.meta_key = 'ecre_custom_referral'
				SET
					p.post_title = CASE
						WHEN LOWER(SUBSTRING(p.post_title, 1, %d)) = %s THEN CONCAT(%s, SUBSTRING(p.post_title, %d))
						ELSE CONCAT(%s, SUBSTRING(p.post_title, %d))
					END,
					p.post_name = CASE
						WHEN LOWER(SUBSTRING(p.post_name, 1, %d)) = %s THEN CONCAT(%s, SUBSTRING(p.post_name, %d))
						ELSE CONCAT(%s, SUBSTRING(p.post_name, %d))
					END,
					p.post_content = CASE
						WHEN pm_custom.meta_value = '1' THEN p.post_content
						ELSE %s
					END,
					p.post_excerpt = CASE
						WHEN pm_custom.meta_value = '1' THEN p.post_excerpt
						ELSE %s
					END
				WHERE
					p.post_type = %s
					AND pm.meta_key = %s
				",
				$prefix_length,
				$coupon_prefix_lower,
				$coupon_prefix_upper,
				$prefix_length + 1,
				$coupon_prefix_upper,
				$prefix_length + 1,
				$prefix_length,
				$coupon_prefix_lower,
				$coupon_prefix_upper,
				$prefix_length + 1,
				$coupon_prefix_upper,
				$prefix_length + 1,
				$discount . ' off coupon',
				$discount . ' off coupon',
				'shop_coupon',
				'referral_user_id'
			)
		);

		// Now update post_excerpt for custom coupons with their existing amount.
		ecre_update_custom_coupon_excerpts( $currency_symbol, $discount_type );

		// Update meta values in optimized batches.
		ecre_update_referral_meta_batch( $referral_discount, $discount_type, $selected_product_ids, $exclude_product_ids, $selected_categories, $exclude_categories, $subscription_limit, $process_id );
		ecre_update_referrers_coupon_codes_batch( $process_id );
	}

	/**
	 * Update referral_coupon_code in wp_ecre_referrers table with chunk processing
	 */
	function ecre_update_referrers_coupon_codes_batch( $process_id = null ) {
		global $wpdb;

		$batch_size = 500;
		$offset     = 0;
		$processed  = 0;

		do {
			// Check if process should be cancelled.
			if ( $process_id ) {
				$current_process = get_option( 'ecre_current_coupon_process' );
				if ( $current_process !== $process_id ) {
					return $processed;
				}
			}

			// Get chunk of referrer IDs that need updating.
			$referrer_chunk = $wpdb->get_results(
				$wpdb->prepare(
					"
					SELECT r.id, r.referral_coupon_id
					FROM {$wpdb->prefix}ecre_referrers r
					INNER JOIN {$wpdb->posts} p ON r.referral_coupon_id = p.ID
					WHERE r.referral_coupon_id IS NOT NULL
					AND p.post_type = %s
					AND (r.referral_coupon_code != p.post_title OR r.referral_coupon_code IS NULL)
					LIMIT %d OFFSET %d
					",
					'shop_coupon',
					$batch_size,
					$offset
				)
			);

			if ( empty( $referrer_chunk ) ) {
				break;
			}

			// Extract referrer IDs and process in chunks (same pattern as ecre_update_referral_meta_batch).
			$referrer_ids = wp_list_pluck( $referrer_chunk, 'id' );

			if ( ! empty( $referrer_ids ) ) {
				$chunk_size = 100;
				$chunks     = array_chunk( $referrer_ids, $chunk_size );

				foreach ( $chunks as $chunk ) {
					$referrer_ids_sanitized = array_map( 'absint', $chunk );

					$query_args = array_merge(
						array( current_time( 'mysql' ) ),
						$referrer_ids_sanitized,
						array( 'shop_coupon' )
					);

					// Following the exact same pattern as ecre_update_referral_meta_batch.
					$wpdb->query(
						$wpdb->prepare(
							"
							UPDATE {$wpdb->prefix}ecre_referrers r
							INNER JOIN {$wpdb->posts} p ON r.referral_coupon_id = p.ID
							SET r.referral_coupon_code = p.post_title,
								r.updated_at = %s
							WHERE r.id IN (" . implode( ',', array_fill( 0, count( $referrer_ids_sanitized ), '%d' ) ) . ')
							AND p.post_type = %s',
							$query_args
						)
					);
				}
			}

			$processed += count( $referrer_chunk );
			$offset    += $batch_size;

			// Memory management.
			wp_cache_flush();
			if ( function_exists( 'gc_collect_cycles' ) ) {
				gc_collect_cycles();
			}

			$chunk_count = count( $referrer_chunk );

		} while ( $chunk_count === $batch_size );

		return $processed;
	}

	/**
	 * Update post_excerpt for custom referral coupons using their existing coupon_amount
	 */
	function ecre_update_custom_coupon_excerpts( $currency_symbol, $discount_type ) {
		global $wpdb;

		// Get all custom referral coupons with their existing coupon amounts.
		$custom_coupons = $wpdb->get_results(
			"SELECT p.ID, pm_amount.meta_value as coupon_amount
			FROM {$wpdb->posts} AS p
			INNER JOIN {$wpdb->postmeta} AS pm_referral ON p.ID = pm_referral.post_id AND pm_referral.meta_key = 'referral_user_id'
			INNER JOIN {$wpdb->postmeta} AS pm_custom ON p.ID = pm_custom.post_id AND pm_custom.meta_key = 'ecre_custom_referral' AND pm_custom.meta_value = '1'
			INNER JOIN {$wpdb->postmeta} AS pm_amount ON p.ID = pm_amount.post_id AND pm_amount.meta_key = 'coupon_amount'
			WHERE p.post_type = 'shop_coupon'"
		);

		if ( ! empty( $custom_coupons ) ) {
			foreach ( $custom_coupons as $coupon ) {
				$existing_amount = floatval( $coupon->coupon_amount );
				$custom_discount_text = ( 'percent' === $discount_type ) ?
					$existing_amount . '%' :
					$existing_amount . $currency_symbol;

				// Update post_excerpt and post_content with existing amount.
				wp_update_post(
					array(
						'ID'           => $coupon->ID,
						'post_excerpt' => $custom_discount_text . ' off coupon',
						'post_content' => $custom_discount_text . ' off coupon',
					)
				);
			}
		}
	}

	if ( ! function_exists( 'ecre_update_referral_meta_batch' ) ) {
		/**
		 * Batch update referral coupon meta data.
		 *
		 * Updates referral-related coupon meta values in controlled batches to avoid
		 * memory exhaustion and long-running queries. Custom referral coupons are
		 * excluded from amount updates while still receiving other meta updates.
		 *
		 * Supports process cancellation via a process ID to safely stop execution
		 * mid-way if required.
		 *
		 * @param float|int   $referral_discount     Discount amount for referral coupons.
		 * @param string      $discount_type         Coupon discount type (e.g. percent, fixed_cart).
		 * @param array       $selected_product_ids  Product IDs allowed for coupon usage.
		 * @param array       $exclude_product_ids   Product IDs excluded from coupon usage.
		 * @param array       $selected_categories   Product categories allowed for coupon usage.
		 * @param array       $exclude_categories    Product categories excluded from coupon usage.
		 * @param int         $subscription_limit    Subscription payment limit for coupons.
		 * @param string|null $process_id           Optional process identifier for cancellation control.
		 *
		 * @return void
		 */
		function ecre_update_referral_meta_batch( $referral_discount, $discount_type, $selected_product_ids, $exclude_product_ids, $selected_categories, $exclude_categories, $subscription_limit, $process_id = null ) {
			global $wpdb;

			$batch_size = 500;
			$offset     = 0;
			$processed  = 0;
			$skipped    = 0;

			do {
				// Check if process should be cancelled.
				if ( $process_id ) {
					$current_process = get_option( 'ecre_current_coupon_process' );
					if ( $current_process !== $process_id ) {
						return;
					}
				}

				// Get batch of coupon IDs.
				$coupon_batch = $wpdb->get_results(
					$wpdb->prepare(
						"
						SELECT p.ID
						FROM {$wpdb->posts} AS p
						INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id
						WHERE p.post_type = %s
						AND pm.meta_key = %s
						LIMIT %d OFFSET %d
						",
						'shop_coupon',
						'referral_user_id',
						$batch_size,
						$offset
					)
				);

				if ( empty( $coupon_batch ) ) {
					break;
				}

				$coupon_ids = wp_list_pluck( $coupon_batch, 'ID' );

				$custom_coupon_ids = array();
				if ( ! empty( $coupon_ids ) ) {
					$chunk_size = 100;
					$chunks     = array_chunk( $coupon_ids, $chunk_size );

					foreach ( $chunks as $chunk ) {
						$coupon_ids_sanitized = array_map( 'absint', $chunk );
						$placeholders         = implode( ',', array_fill( 0, count( $coupon_ids_sanitized ), '%d' ) );
						$query_args           = array_merge( array( 'ecre_custom_referral', '1' ), $coupon_ids_sanitized );

						$chunk_custom_ids = $wpdb->get_col(
							$wpdb->prepare(
								"SELECT post_id
								FROM {$wpdb->postmeta}
								WHERE meta_key = %s
								AND meta_value = %s
								AND post_id IN (" . implode( ',', array_fill( 0, count( $coupon_ids_sanitized ), '%d' ) ) . ')',
								$query_args
							)
						);

						if ( ! empty( $chunk_custom_ids ) ) {
							$custom_coupon_ids = array_merge( $custom_coupon_ids, $chunk_custom_ids );
						}
					}
				}

				// Separate regular coupons from custom ones.
				$regular_coupon_ids = array_diff( $coupon_ids, $custom_coupon_ids );

				// Update coupon_amount and discount_type for regular coupons only.
				if ( ! empty( $regular_coupon_ids ) ) {
					ecre_bulk_update_meta( 'coupon_amount', $referral_discount, $regular_coupon_ids );
				}

				// Update other meta fields for all coupons.
				if ( ! empty( $coupon_ids ) ) {
					ecre_bulk_update_meta( 'discount_type', $discount_type, $coupon_ids );
					ecre_bulk_update_meta( 'product_ids', ( ! empty( $selected_product_ids ) ? implode( ',', $selected_product_ids ) : '' ), $coupon_ids );
					ecre_bulk_update_meta( 'exclude_product_ids', ( ! empty( $exclude_product_ids ) ? implode( ',', $exclude_product_ids ) : '' ), $coupon_ids );
					ecre_bulk_update_meta( 'product_categories', maybe_serialize( $selected_categories ), $coupon_ids );
					ecre_bulk_update_meta( 'exclude_product_categories', maybe_serialize( $exclude_categories ), $coupon_ids );
					ecre_bulk_update_meta( '_wcs_number_payments', $subscription_limit, $coupon_ids );
				}

				$processed += count( $coupon_ids );
				$skipped   += count( $custom_coupon_ids );
				$offset    += $batch_size;

				$coupon_batch_count = count( $coupon_batch );

				// Enhanced memory management.
				wp_cache_flush();

				if ( function_exists( 'gc_collect_cycles' ) ) {
					gc_collect_cycles();
				}
			} while ( $coupon_batch_count === $batch_size );
		}
	}

	if ( ! function_exists( 'ecre_bulk_update_meta' ) ) {
		/**
		 * Bulk insert or update post meta for multiple posts.
		 *
		 * Efficiently updates or inserts a specific meta key/value pair for a list
		 * of post IDs using chunked processing to reduce memory usage.
		 *
		 * @param string $meta_key   Meta key to update.
		 * @param mixed  $meta_value Meta value to store (will be serialized if needed).
		 * @param array  $post_ids   Array of post IDs to update.
		 *
		 * @return void
		 */
		function ecre_bulk_update_meta( $meta_key, $meta_value, $post_ids ) {
			global $wpdb;

			if ( empty( $post_ids ) ) {
				return;
			}

			$meta_value = maybe_serialize( $meta_value );
			$post_ids   = array_map( 'absint', $post_ids );

			$chunk_size = 25;
			$chunks     = array_chunk( $post_ids, $chunk_size );

			foreach ( $chunks as $chunk ) {
				foreach ( $chunk as $post_id ) {
					$existing_meta = $wpdb->get_var(
						$wpdb->prepare(
							"SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = %s",
							$post_id,
							$meta_key
						)
					);

					if ( $existing_meta ) {
						$wpdb->update(
							$wpdb->postmeta,
							array( 'meta_value' => $meta_value ),
							array( 'meta_id' => $existing_meta ),
							array( '%s' ),
							array( '%d' )
						);
					} else {
						$wpdb->insert(
							$wpdb->postmeta,
							array(
								'post_id'    => $post_id,
								'meta_key'   => $meta_key,
								'meta_value' => $meta_value,
							),
							array( '%d', '%s', '%s' )
						);
					}
				}

				// Memory cleanup after each chunk.
				if ( function_exists( 'gc_collect_cycles' ) ) {
					gc_collect_cycles();
				}
			}
		}
	}

	if ( ! function_exists( 'ecre_get_all_wp_pages' ) ) {
		/**
		 * Retrieves all WordPress pages.
		 *
		 * This function queries the WordPress database to fetch and return
		 * an array of all published pages, including their IDs, titles, and
		 * other relevant data. It can be used to display a list of pages
		 * or for further processing in the application.
		 *
		 * @since 1.0.0
		 * @return array An array of all WordPress pages with their details.
		 */
		function ecre_get_all_wp_pages() {
			// Get the home page data.
			$home_page = array(
				'value' => 0,
				'label' => __( 'Home', 'echo-rewards' ),
				'slug'  => 'home',
				'url'   => home_url( '/' ),
			);

			// Get all other pages.
			$pages = get_pages();

			// Initialize the page list with the home page.
			$page_list = array( $home_page );

			// Loop through each page and get the relevant data.
			foreach ( $pages as $page ) {
				$page_list[] = array(
					'value' => $page->ID,
					'label' => $page->post_title,
					'slug'  => $page->post_name,
					'url'   => get_permalink( $page->ID ),
				);
			}

			return $page_list;
		}
	}

	if ( ! function_exists( 'ecre_pro_first_coupon_order_date' ) ) {

		/**
		 * Retrieves the date of the first coupon order for a specific user.
		 *
		 * @param int $user_id The ID of the user.
		 *
		 * @return string|null The date of the first coupon order, or null if no such order is found.
		 */
		function ecre_pro_first_coupon_order_date( $user_id ) {
			// Retrieve all orders for the user.
			$usages_coupon = ecre_pro_referral_coupons_with_usage();

			// Loop through the user's orders to find the actual first coupon order date.
			foreach ( $usages_coupon as $user_order ) {
				$order_obj        = wc_get_order( $user_order['id'] );
				$referral_user_id = $order_obj->get_user_id();
					// Check if coupons were used.
				if ( $user_id && ! empty( $referral_user_id ) ) {
					// Return the date of the first coupon order found.
					return $order_obj->get_date_created()->format( 'Y-m-d' );
				}
			}

			return null;
		}
	}

	if ( ! function_exists( 'ecre_pro_custom_currency_symbol' ) ) {
		/**
		 * Get WooCommerce currency symbol
		 *
		 * @return string The currency symbol
		 */
		function ecre_pro_custom_currency_symbol() {
			// If WooCommerce is active, use its function to get currency symbol.
			if ( function_exists( 'get_woocommerce_currency_symbol' ) ) {
				$ecre_currency_sign = get_woocommerce_currency_symbol();
				$ecre_currency_sign = html_entity_decode( $ecre_currency_sign );

				return $ecre_currency_sign;
			} else {
				return '$';
			}
		}
	}

	if ( ! function_exists( 'ecre_monthly_referral_coupons_usage' ) ) {
		/**
		 * Counts the number of orders in the current month that are associated with coupons having the referral user ID meta set to the current user.
		 *
		 * This function retrieves all coupons associated with the current user's referral ID and counts the number of orders placed in the current month that have used these coupons.
		 *
		 * @return int The count of orders in the current month using referral coupons associated with the current user.
		 */
		function ecre_monthly_referral_coupons_usage() {
			$current_user_id    = get_current_user_id();
			$coupon_usage_count = 0;
			$current_month      = gmdate( 'm' );
			$current_year       = gmdate( 'Y' );

			$args = array(
				'post_type'      => 'shop_coupon',
				'posts_per_page' => -1,
				'meta_query'     => array(
					array(
						'key'     => 'referral_user_id',
						'value'   => $current_user_id,
						'compare' => '=',
					),
				),
				'orderby'        => 'date',
				'order'          => 'ASC',
			);

			$query = new WP_Query( $args );

			if ( $query->have_posts() ) {
				while ( $query->have_posts() ) {
					$query->the_post();
					$coupon_code = strtolower( get_the_title() );

					// Get orders based on the coupon code.
					$orders = wc_get_orders(
						array(
							'date_query'  => array(
								array(
									'year'  => $current_year,
									'month' => $current_month,
								),
							),
							'numberposts' => -1,
							'post_type'   => 'shop_order',
						)
					);

					foreach ( $orders as $order ) {
						$coupon_codes = array_map( 'strtolower', $order->get_coupon_codes() );
						if ( ! empty( $coupon_codes ) ) {
							// Check if the coupon code is in the array of used coupons.
							if ( in_array( $coupon_code, $coupon_codes, true ) ) {
								// Check if the order has the _referral_user_id meta.
								if ( (int) get_post_meta( $order->get_id(), '_referral_user_id', true ) === (int) $current_user_id ) {
									++$coupon_usage_count;
								}
							}
						}
					}

					update_post_meta( get_the_ID(), 'referral_usage_count', $coupon_usage_count );
				}
				wp_reset_postdata();
			}

			return $coupon_usage_count;
		}
	}

	if ( ! function_exists( 'ecre_pro_get_all_orders' ) ) {
		/**
		 * Retrieves all orders from the WooCommerce store.
		 *
		 * This function queries the WooCommerce database to fetch and return
		 * an array of all orders, including their details such as order IDs,
		 * statuses, and customer information. It can be used for order management,
		 * reporting, or analysis purposes within the application.
		 *
		 * @since 1.0.0
		 * @return array An array of all WooCommerce orders with their details.
		 */
		function ecre_pro_get_all_orders() {
			global $wpdb;

			// Attempt to retrieve cached results.
			$cached_results = wp_cache_get( 'ecre_pro_all_orders' );

			// If cached results are not available, execute the database query and cache the results.
			if ( false === $cached_results ) {
				$results = $wpdb->get_results(
					"
					SELECT 
						orders.id, 
						orders.status, 
						orders.date_created_gmt, 
						orders.billing_email 
					FROM {$wpdb->prefix}wc_orders AS orders
					WHERE orders.status <> 'trash'
					",
					ARRAY_A
				);

				// Cache the results.
				wp_cache_set( 'ecre_pro_all_orders', $results, '', 3600 );

				// Assign the results to the cached_results variable.
				$cached_results = $results;
			}

			return $cached_results;
		}
	}


	if ( ! function_exists( 'ecre_get_expiry_status' ) ) {
		/**
		 * Check if the given expiry date is expired or still available.
		 *
		 * @param string $expiry_date The expiry date to check (format: 'Y-m-d').
		 * @return string The status of the reward: 'Expired', 'Available', or 'Not Set'.
		 */
		function ecre_get_expiry_status( $expiry_date ) {
			// Check if the expiry date is not empty or invalid.
			if ( $expiry_date ) {
				// Get the current date in the same format as the expiry date.
				$current_date  = gmdate( 'Y-m-d' );
				$erce_settings = get_option( 'ecre_settings', array() );

				// Compare the expiry date with the current date.
				if ( strtotime( $expiry_date ) < strtotime( $current_date ) ) {
					if ( 'delete' === $erce_settings['rewardPointExpiryAction']['value'] ) {
						return 'expired';
					}

					if ( 'unavailable' === $erce_settings['rewardPointExpiryAction']['value'] ) {
						return 'unavailable';
					}
				} else {
					return 'available';
				}
			}

			return 'Not Set';
		}
	}

	if ( ! function_exists( 'ecre_get_discount_data' ) ) {
		/**
		 * Retrieves discount data for the specified period.
		 *
		 * @param string $period The period for which to retrieve data. Possible values: 'last_month', 'current_month', '7_days', 'yearly'.
		 *
		 * @return array Discount data including total discounts and referral discounts by date.
		 */
		function ecre_get_discount_data( $period ) {
			global $wpdb;

			$date_series_query = '';

			if ( 'last_month' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m-%d') AS order_date
					FROM (
						SELECT a.N + b.N * 10 AS n
						FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a,
							(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
					) num
					WHERE DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m') = DATE_FORMAT(CURDATE() - INTERVAL 1 MONTH, '%Y-%m')
				";
			} elseif ( 'current_month' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m-%d') AS order_date
					FROM (
						SELECT a.N + b.N * 10 AS n
						FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a,
							(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
					) num
					WHERE DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
				";
			} elseif ( '7_days' === $period ) {
				$date_series_query = '
					SELECT CURDATE() - INTERVAL n DAY AS order_date
					FROM (
						SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
					) days
				';
			} elseif ( 'yearly' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL -n MONTH), '%Y-%m') AS order_date
					FROM (
						SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
					) months
					WHERE DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL -n MONTH), '%Y') = DATE_FORMAT(CURDATE(), '%Y')
				";
			} else {
				return array(); // Invalid period, return empty result.
			}

			$cache_key   = 'discount_data_' . md5( $period );
			$cached_data = wp_cache_get( $cache_key, 'custom_cache_group' );

			if ( false !== $cached_data ) {
				return $cached_data;
			}

			$query = "
				WITH date_series AS (
					{$date_series_query}
				)
				SELECT 
					ds.order_date,
					COALESCE(SUM(oim.meta_value), 0) AS total_discount,
					COALESCE(SUM(CASE WHEN pm.meta_key = '_referral_user_id' THEN oim.meta_value ELSE 0 END), 0) AS total_discount_with_referral
				FROM 
					date_series AS ds
				LEFT JOIN 
					{$wpdb->prefix}wc_orders AS o 
					ON (
						('yearly' = '{$period}' AND DATE_FORMAT(o.date_created_gmt, '%Y-%m') = ds.order_date)
						OR ('yearly' != '{$period}' AND DATE(o.date_created_gmt) = ds.order_date)
					)
				LEFT JOIN 
					{$wpdb->prefix}woocommerce_order_items AS oi 
					ON o.id = oi.order_id
				LEFT JOIN 
					{$wpdb->prefix}woocommerce_order_itemmeta AS oim 
					ON oi.order_item_id = oim.order_item_id 
					AND oim.meta_key = 'discount_amount' 
					AND oi.order_item_type = 'coupon'
				LEFT JOIN 
					{$wpdb->prefix}postmeta AS pm 
					ON o.id = pm.post_id 
					AND pm.meta_key = '_referral_user_id'
				GROUP BY 
					ds.order_date
				ORDER BY 
					ds.order_date ASC
			";

			//phpcs:ignore
			$results = $wpdb->get_results( $query, ARRAY_A );

			// Cache the results.
			wp_cache_set( $cache_key, $results, 'custom_cache_group', HOUR_IN_SECONDS );

			return $results;
		}
	}

	if ( ! function_exists( 'ecre_get_sales_data' ) ) {
		/**
		 * Retrieves total sales data for the specified period.
		 *
		 * @param string $period The period for which to retrieve data. Possible values: 'last_month', 'current_month', '7_days', 'yearly'.
		 *
		 * @return array Sales data including total sales and referral sales by date.
		 */
		function ecre_get_sales_data( $period ) {
			global $wpdb;

			$date_series_query = '';

			if ( 'last_month' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m-%d') AS order_date
					FROM (
						SELECT a.N + b.N * 10 AS n
						FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a,
							(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
					) num
					WHERE DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m') = DATE_FORMAT(CURDATE() - INTERVAL 1 MONTH, '%Y-%m')
				";
			} elseif ( 'current_month' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m-%d') AS order_date
					FROM (
						SELECT a.N + b.N * 10 AS n
						FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a,
							(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
					) num
					WHERE DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
				";
			} elseif ( '7_days' === $period ) {
				$date_series_query = '
					SELECT CURDATE() - INTERVAL n DAY AS order_date
					FROM (
						SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
					) days
				';
			} elseif ( 'yearly' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL -n MONTH), '%Y-%m') AS order_date
					FROM (
						SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
					) months
					WHERE DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL -n MONTH), '%Y') = DATE_FORMAT(CURDATE(), '%Y')
				";
			} else {
				return array(); // Invalid period, return empty result.
			}

			$cache_key   = 'sales_data_' . md5( $period );
			$cached_data = wp_cache_get( $cache_key, 'custom_cache_group' );

			if ( false !== $cached_data ) {
				return $cached_data;
			}

			$query = "
				WITH date_series AS (
					{$date_series_query}
				)
				SELECT 
					ds.order_date,
					COALESCE(SUM(oim.meta_value), 0) AS total_sales,
					COALESCE(SUM(CASE WHEN pm.meta_key = '_referral_user_id' THEN oim.meta_value ELSE 0 END), 0) AS total_sales_with_referral
				FROM 
					date_series AS ds
				LEFT JOIN 
					{$wpdb->prefix}wc_orders AS o 
					ON (
						('yearly' = '{$period}' AND DATE_FORMAT(o.date_created_gmt, '%Y-%m') = ds.order_date)
						OR ('yearly' != '{$period}' AND DATE(o.date_created_gmt) = ds.order_date)
					)
				LEFT JOIN 
					{$wpdb->prefix}woocommerce_order_items AS oi 
					ON o.id = oi.order_id
				LEFT JOIN 
					{$wpdb->prefix}woocommerce_order_itemmeta AS oim 
					ON oi.order_item_id = oim.order_item_id 
					AND oim.meta_key = '_line_total' 
					AND oi.order_item_type = 'line_item'
				LEFT JOIN 
					{$wpdb->prefix}postmeta AS pm 
					ON o.id = pm.post_id 
					AND pm.meta_key = '_referral_user_id'
				GROUP BY 
					ds.order_date
				ORDER BY 
					ds.order_date ASC
			";

			//phpcs:ignore
			$results = $wpdb->get_results( $query, ARRAY_A );

			// Cache the results.
			wp_cache_set( $cache_key, $results, 'custom_cache_group', HOUR_IN_SECONDS );

			return $results;
		}
	}

	if ( ! function_exists( 'ecre_get_referral_order_data' ) ) {
		/**
		 * Fetches referral order data for a specific period.
		 *
		 * Generates date series for the given period ('last_month', 'current_month',
		 * '7_days', or 'yearly') and retrieves the count of referral orders. Results are cached.
		 *
		 * @param string $period Time period for the data (e.g., 'last_month').
		 * @return array Array of `order_date` and `referral_order_count`. Empty if invalid period.
		 */
		function ecre_get_referral_order_data( $period ) {
			global $wpdb;

			// Generate the date series query based on the provided period.
			$date_series_query = '';

			if ( 'last_month' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m-%d') AS order_date
					FROM (
						SELECT a.N + b.N * 10 AS n
						FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a,
							(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
					) num
					WHERE DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m') = DATE_FORMAT(CURDATE() - INTERVAL 1 MONTH, '%Y-%m')
				";
			} elseif ( 'current_month' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m-%d') AS order_date
					FROM (
						SELECT a.N + b.N * 10 AS n
						FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a,
							(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
					) num
					WHERE DATE_FORMAT(CURDATE() - INTERVAL n DAY, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m')
				";
			} elseif ( '7_days' === $period ) {
				$date_series_query = '
					SELECT CURDATE() - INTERVAL n DAY AS order_date
					FROM (
						SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
					) days
				';
			} elseif ( 'yearly' === $period ) {
				$date_series_query = "
					SELECT DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL -n MONTH), '%Y-%m') AS order_date
					FROM (
						SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
					) months
					WHERE DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL -n MONTH), '%Y') = DATE_FORMAT(CURDATE(), '%Y')
				";
			} else {
				return array(); // Invalid period, return empty result.
			}

			$cache_key   = 'referral_order_data_' . md5( $period );
			$cached_data = wp_cache_get( $cache_key, 'custom_cache_group' );

			if ( false !== $cached_data ) {
				return $cached_data;
			}

			$query = "
				WITH date_series AS (
					{$date_series_query}
				)
				SELECT 
					ds.order_date,
					COALESCE(COUNT(DISTINCT CASE WHEN pm.meta_key = '_referral_user_id' THEN o.id ELSE NULL END), 0) AS referral_order_count
				FROM 
					date_series AS ds
				LEFT JOIN 
					{$wpdb->prefix}wc_orders AS o 
					ON (
						('yearly' = '{$period}' AND DATE_FORMAT(o.date_created_gmt, '%Y-%m') = ds.order_date)
						OR ('yearly' != '{$period}' AND DATE(o.date_created_gmt) = ds.order_date)
					)
				LEFT JOIN 
					{$wpdb->prefix}postmeta AS pm 
					ON o.id = pm.post_id 
					AND pm.meta_key = '_referral_user_id'
				GROUP BY 
					ds.order_date
				ORDER BY 
					ds.order_date ASC
			";

			// Run the query and fetch results.
			//phpcs:ignore
			$results = $wpdb->get_results( $query, ARRAY_A );

			// Cache the results.
			wp_cache_set( $cache_key, $results, 'custom_cache_group', HOUR_IN_SECONDS );

			return $results;
		}
	}


	if ( ! function_exists( 'ecre_get_top_10_coupons_with_referral' ) ) {
		/**
		 * Get top 10 coupons with discount details within a given time period.
		 *
		 * @param string $time_period Allowed values: 'last_month', 'current_month', '7_days', 'yearly'.
		 * @return array Top 10 coupons data.
		 */
		function ecre_get_top_10_coupons_with_referral( $time_period = 'current_month' ) {
			global $wpdb;

			// Table names with prefixes.
			$orders_table         = $wpdb->prefix . 'wc_orders';
			$order_items_table    = $wpdb->prefix . 'woocommerce_order_items';
			$order_itemmeta_table = $wpdb->prefix . 'woocommerce_order_itemmeta';
			$postmeta_table       = $wpdb->prefix . 'postmeta';

			// Define date conditions based on the time period.
			$date_condition = '';
			switch ( $time_period ) {
				case 'last_month':
					$date_condition = "o.date_created_gmt BETWEEN DATE_FORMAT(NOW() - INTERVAL 1 MONTH, '%Y-%m-01') AND LAST_DAY(NOW() - INTERVAL 1 MONTH)";
					break;
				case 'current_month':
					$date_condition = "o.date_created_gmt BETWEEN DATE_FORMAT(NOW(), '%Y-%m-01') AND LAST_DAY(NOW())";
					break;
				case '7_days':
					$date_condition = 'o.date_created_gmt >= DATE_SUB(NOW(), INTERVAL 7 DAY)';
					break;
				case 'yearly':
					$date_condition = "o.date_created_gmt BETWEEN DATE_FORMAT(NOW(), '%Y-01-01') AND DATE_FORMAT(NOW(), '%Y-12-31')";
					break;
				default:
					$date_condition = 'o.date_created_gmt >= DATE_SUB(NOW(), INTERVAL 7 DAY)';
					break;
			}

			// Set up cache key for transient caching.
			$cache_key   = "top_10_coupons_{ $time_period }";
			$cached_data = wp_cache_get( $cache_key );

			// If cached data exists, return it.
			if ( false !== $cached_data ) {
				return $cached_data;
			}

			// SQL query to fetch top 10 coupons.
			$query = "
				SELECT 
					oi.order_item_name AS coupon_code,
					COUNT(o.id) AS total_orders,
					SUM(oim.meta_value) AS total_discount,
					DATE_FORMAT(o.date_created_gmt, '%Y-%m-%d') AS creation_date,
					'N/A' AS expiration_date, -- Placeholder for expiration
					'percent' AS discount_type -- Placeholder for discount type
				FROM 
					{$order_items_table} AS oi
				INNER JOIN 
					{$orders_table} AS o ON oi.order_id = o.id
				INNER JOIN 
					{$order_itemmeta_table} AS oim 
					ON oi.order_item_id = oim.order_item_id 
					AND oim.meta_key = 'discount_amount'
				LEFT JOIN 
					{$postmeta_table} AS pm 
					ON pm.post_id = oi.order_id 
					AND pm.meta_key = '_referral_user_id'
				WHERE 
					oi.order_item_type = 'coupon'
					AND pm.meta_value IS NOT NULL
					AND {$date_condition}
				GROUP BY 
					oi.order_item_name, DATE_FORMAT(o.date_created_gmt, '%Y-%m-%d')
				ORDER BY 
					total_discount DESC
				LIMIT 10
			";

			// Execute the query.
			//phpcs:ignore
			$results = $wpdb->get_results( $query );

			// Cache the results for 1 hour.
			wp_cache_set( $cache_key, $results, '', HOUR_IN_SECONDS );

			return $results;
		}
	}

	if ( ! function_exists( 'ecre_is_woocommerce_subscriptions_active' ) ) {
		/**
		 * Checks if the WooCommerce Subscriptions plugin is active.
		 *
		 * This function determines whether the WooCommerce Subscriptions plugin is
		 * currently active, either at the site level or network-wide in a multisite setup.
		 *
		 * @return bool True if WooCommerce Subscriptions is active, false otherwise.
		 */
		function ecre_is_woocommerce_subscriptions_active() {
			// Get the list of active plugins from the database.
			$active_plugins = get_option( 'active_plugins', array() );

			// Check if WooCommerce Subscriptions is in the list of active plugins.
			if ( in_array( 'woocommerce-subscriptions/woocommerce-subscriptions.php', $active_plugins, true ) ) {
				return true;
			}

			// For multisite installations, check the network-activated plugins.
			if ( is_multisite() ) {
				$active_network_plugins = get_site_option( 'active_sitewide_plugins', array() );

				if ( isset( $active_network_plugins['woocommerce-subscriptions/woocommerce-subscriptions.php'] ) ) {
					return true;
				}
			}

			return false;
		}
	}

	if ( ! function_exists( 'ecre_get_woocommerce_order_statuses' ) ) {
		/**
		 * Retrieves the available WooCommerce order statuses and formats them for use in select options.
		 *
		 * This function checks if the `wc_get_order_statuses` function exists, then fetches the WooCommerce
		 * order statuses and formats them into an array of arrays containing 'value' (order status key)
		 * and 'label' (order status name) to be used in form select options.
		 *
		 * @return array An array of order status options, each containing a 'value' and 'label'.
		 *               Returns an empty array if WooCommerce is not available or order statuses cannot be fetched.
		 *
		 * @since 1.0.0
		 */
		function ecre_get_woocommerce_order_statuses() {
			if ( ! function_exists( 'wc_get_order_statuses' ) ) {
				return array();
			}

			$statuses       = wc_get_order_statuses();
			$status_options = array_map(
				function ( $label, $key ) {
					return array(
						'value' => $key,
						'label' => __( $label, 'echo-rewards' ),
					);
				},
				array_values( $statuses ),
				array_keys( $statuses )
			);

			return $status_options;
		}
	}
}

if ( ! function_exists( 'ecre_is_pro_latest_version' ) ) {
	/**
	 * Checks if a specified plugin is active and running a version that is at least 2.0.
	 *
	 * This function determines whether the specified plugin is active and if its version
	 * is greater than or equal to 2.0. It uses the WordPress filesystem API to safely
	 * access and read the plugin file.
	 *
	 * @param string $plugin_path Relative path to the plugin's main file within the `wp-content/plugins/` directory.
	 *                            Example: 'plugin-folder/plugin-main-file.php'.
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem object for handling file operations.
	 *
	 * @return bool True if the plugin is active and its version is 2.0 or higher. False otherwise.
	 */
	function ecre_is_pro_latest_version( $plugin_path ) {
		global $wp_filesystem;

		if ( is_plugin_active( $plugin_path ) ) {
			// Initialize WordPress filesystem API.
			if ( ! function_exists( 'WP_Filesystem' ) ) {
				require_once ABSPATH . 'wp-admin/includes/file.php';
			}
			WP_Filesystem();

			// Get the plugin's main file path.
			$plugin_file = WP_PLUGIN_DIR . '/' . $plugin_path;

			// Read the file safely.
			if ( $wp_filesystem->exists( $plugin_file ) ) {
				$plugin_contents = $wp_filesystem->get_contents( $plugin_file );

				// Extract the version using regex.
				preg_match( '/^ \* Version:\s*(.*)$/mi', $plugin_contents, $matches );
				$plugin_version = isset( $matches[1] ) ? trim( $matches[1] ) : '';

				// Compare the version.
				return version_compare( $plugin_version, '2.0', '>=' );
			}
		}

		return false;
	}

}

if ( ! function_exists( 'ecre_default_settings' ) ) {
	/**
	 * Retrieves the default settings for the ECRE plugin.
	 *
	 * This function defines and returns the default configuration settings
	 * used by the ECRE plugin. It ensures that all necessary settings are
	 * available and set to their initial values when the plugin is activated
	 * or when settings are reset.
	 *
	 * @since 1.0.0
	 * @return array An associative array containing the default settings.
	 */
	function ecre_default_settings() {

		$referral_discount_type       = get_option( 'ecre_referral_discount_type', 'percent' );
		$referral_discount_type_label = __( 'Percentage', 'echo-rewards' );

		$reward_discount_type       = get_option( 'ecre_reward_discount_type', 'percent' );
		$reward_discount_type_label = __( 'Percentage', 'echo-rewards' );

		$referral_widget_possition       = get_option( 'vertical_left', 'left' );
		$referral_widget_possition_label = __( 'Vertical left', 'echo-rewards' );

		if ( ! empty( $referral_widget_possition ) ) {
			if ( 'vertical_left' === $referral_widget_possition ) {
				$referral_widget_possition       = 'left';
				$referral_widget_possition_label = __( 'Vertical left', 'echo-rewards' );
			} elseif ( 'vertical_right' === $referral_widget_possition ) {
				$referral_widget_possition       = 'right';
				$referral_widget_possition_label = __( 'Vertical right', 'echo-rewards' );
			}
		}

		if ( ! empty( $referral_discount_type ) ) {
			if ( 'percent' === $referral_discount_type ) {
				$referral_discount_type_label = __( 'Percentage', 'echo-rewards' );
			} elseif ( 'fixed' === $referral_discount_type ) {
				$referral_discount_type_label = __( 'Fixed', 'echo-rewards' );
			}
		}

		if ( ! empty( $reward_discount_type ) ) {
			if ( 'percent' === $reward_discount_type ) {
				$reward_discount_type_label = __( 'Percentage', 'echo-rewards' );
			} elseif ( 'fixed' === $reward_discount_type ) {
				$reward_discount_type_label = __( 'Fixed', 'echo-rewards' );
			}
		}

		return array(
			'enableReferralProgram'                 => get_option( 'ecre_referral_program_status', 1 ),
			'enableReferralLink'                    => '',
			'referralDiscount'                      => get_option( 'ecre_referral_discount', 5 ),
			'noOrderMessageToReferrer'              => get_option( 'ecre_referral_status_message', __( 'You need to have at-least an order in your account before you can refer others', 'echo-rewards' ) ),
			'referralWidgetPosition'                => array(
				'value' => $referral_widget_possition,
				'label' => $referral_widget_possition_label,
			),
			'referralDiscountCapping'               => get_option( 'ecre_referral_discount_capping', 0 ),
			'referralMenuName'                      => get_option( 'ecre_referral_menu_name', __( 'EchoRewards Program', 'echo-rewards' ) ),
			'referralMonthlyLimit'                  => get_option( 'ecre_monthly_referral_limit', 5 ),
			'referralMinimumPurchaseAmount'         => get_option( 'ecre_referral_minimum_purchase_amount', 0 ),
			'referralCouponPrefix'                  => get_option( 'ecre_referral_coupon_prefix', 'ECHO' ),
			'canRefferOthers'                       => get_option( 'ecre_referral_status', '' ),
			'canUseReferralCoupon'                  => get_option( 'ecre_referral_new_customer', '' ),
			'enableReferralLimit'                   => '',
			'enableTabOnWooCommerceProduct'         => get_option( 'ecre_referral_tab_on_product_page', 1 ),
			'enableReferralFloatingWidget'          => get_option( 'ecre_referral_floating_widget', false ),
			'enableReferralSocialSharing'           => get_option( 'ecre_referral_social_sharing', 1 ),
			'hideReferralMenuIcon'                  => get_option( 'ecre_hide_referral_menu_icon', '' ),
			'is_user_loggedin'                      => '',
			'pagesForWidgets'                       => array(
				array(
					'value' => 0,
					'label' => __( 'Home', 'echo-rewards' ),
					'slug'  => 'home',
					'url'   => '',
				),
				array(
					'value' => 27,
					'label' => __( 'Cart', 'echo-rewards' ),
					'slug'  => 'cart',
					'url'   => '',
				),
				array(
					'value' => 9,
					'label' => __( 'My account', 'echo-rewards' ),
					'slug'  => 'my-account',
					'url'   => '',
				),
				array(
					'value' => 6,
					'label' => __( 'Shop', 'echo-rewards' ),
					'slug'  => 'shop',
					'url'   => '',
				),
				array(
					'value' => 8,
					'label' => __( 'Checkout', 'echo-rewards' ),
					'slug'  => 'checkout',
					'url'   => '',
				),
			),
			'referralIncludeProducts'               => array(),
			'referralExcludeProducts'               => array(),
			'referralIncludeCategories'             => array(),
			'referralExcludeCategories'             => array(),
			'referralCouponType'                    => array(
				'value' => $referral_discount_type,
				'label' => $referral_discount_type_label,
			),
			'socialMediaOptions'                    => array(
				array(
					'label' => __( 'Facebook', 'echo-rewards' ),
					'value' => 'Facebook',
				),
				array(
					'label' => __( 'WhatsApp', 'echo-rewards' ),
					'value' => 'WhatsApp',
				),
			),
			'rewardType'                            => array(
				'value' => $reward_discount_type,
				'label' => $reward_discount_type_label,
			),
			'rewardPointExpiryAction'               => array(
				'value' => 'unavailable',
				'label' => __( 'Make the available points unavailable', 'echo-rewards' ),
			),
			'rewardPoint'                           => 10,
			'redeemPoint'                           => 1,
			'redeemLimit'                           => 5,
			'enableRedeemLimit'                     => 1,
			'enableRewardPointExpiry'               => '',
			'rewardPointExpiry'                     => 7,
			'minimumRewardPointAmount'              => 25,
			'redeemDiscount'                        => 1,
			'rewardDiscount'                        => get_option( 'ecre_reward_discount', 5 ),
			'rewardDiscountCapping'                 => get_option( 'ecre_reward_discount_capping', 0 ),
			'rewardMinimumPurchaseAmount'           => get_option( 'ecre_reward_minimum_purchase_amount', 0 ),
			'enableRewardExpiry'                    => '',
			'rewardCouponValidity'                  => get_option( 'ecre_reward_coupon_validity', 7 ),
			'enableRewardCouponUsageLimit'          => '',
			'rewardCouponUsageLimit'                => get_option( 'ecre_reward_coupon_usage_limit', 1 ),
			'rewardIncludeProducts'                 => array(),
			'rewardExcludeProducts'                 => array(),
			'rewardIncludeCategories'               => array(),
			'rewardExcludeCategories'               => array(),
			'enableRefferalEmailInvitation'         => get_option( 'ecre_referral_enable_email_notifications', 1 ),
			'referralEmailSubject'                  => get_option( 'ecre_referral_email_subject', __( 'Here is a discount for you!', 'echo-rewards' ) ),
			'referralEmailHeading'                  => get_option( 'ecre_referral_email_heading', sprintf( __( 'Discount for your first purchase on %s', 'echo-rewards' ), site_url() ) ),
			'referralEmailBody'                     => get_option( 'ecre_referral_email_description', sprintf( __( '%s has some awesome products. Check them out with an awesome discount for your first purchase. Use the coupon code during checkout or visit the link and purchase', 'echo-rewards' ), site_url() ) ),
			'enableRewardEmailInvitation'           => get_option( 'ecre_reward_enable_email_notifications', 1 ),
			'rewardEmailSubject'                    => get_option( 'ecre_reward_email_subject', __( 'You got rewards!', 'echo-rewards' ) ),
			'rewardEmailHeading'                    => get_option( 'ecre_reward_email_heading', __( 'Congratulations! You have received a new reward', 'echo-rewards' ) ),
			'rewardEmailBody'                       => get_option( 'ecre_reward_email_description', __( 'You\'ve received a new reward by sharing your coupon code & referral link', 'echo-rewards' ) ),
			'referralMenuIcon'                      => get_option( 'ecre_referral_icon', '' ),
			'referralSignupCouponNote'              => __( 'This coupon can be applied for subscription sign up fee discount only', 'echo-rewards' ),
			'referralRecurringCouponNote'           => __( 'This coupon can be applied for subscription renewal fee discount only', 'echo-rewards' ),
			'enableReferralLimitSubscriptionCoupon' => '',
			'referralLimitSubscriptionCoupon'       => 5,
			'enableRewardLimitSubscriptionCoupon'   => '',
			'rewardLimitSubscriptionCoupon'         => 5,
			'enableRewardDelayTime'                 => false,
			'rewardDelayTime'                       => 0,
			'rewardOrderStatus'                     => array(
				'value' => 'wc-completed',
				'label' => __( 'Completed', 'echo-rewards' ),
			),
		);
	}

	if ( ! function_exists( 'ecre_calculate_coupon_discount_amount' ) ) {
		function ecre_calculate_coupon_discount_amount( $order, $coupon_code ) {
			$discount_amount = 0;
			foreach ( $order->get_items( 'coupon' ) as $item ) {
				if ( $item->get_code() === $coupon_code ) {
					$discount_amount = abs( $item->get_discount() );
					break;
				}
			}
			return $discount_amount;
		}
	}

	if ( ! function_exists( 'ecre_get_customer_names_from_order' ) ) {
		/**
		 * Retrieves the customer's name information from the order.
		 *
		 * This function extracts the billing first name, last name, and full name from the provided WooCommerce order object.
		 * If the full name is empty, it attempts to retrieve the user's display name from the WordPress user data. If no user
		 * is associated with the order, it defaults to 'Guest'.
		 *
		 * @since 1.0.0
		 *
		 * @param \WC_Order $order The WooCommerce order object from which customer details are extracted.
		 *
		 * @return array An associative array containing the customer's first name, last name, and full name:
		 *               - `firstname`: The customer's billing first name.
		 *               - `lastname`: The customer's billing last name.
		 *               - `fullname`: The customer's full name, or 'Guest' if not available.
		 */
		function ecre_get_customer_names_from_order( $order ) {
			$firstname = $order->get_billing_first_name();
			$lastname  = $order->get_billing_last_name();
			$fullname  = trim( $firstname . ' ' . $lastname );

			if ( empty( $fullname ) ) {
				$user_id = $order->get_user_id();
				if ( $user_id ) {
					$user     = get_user_by( 'id', $user_id );
					$fullname = $user ? $user->display_name : 'Guest';
				} else {
					$fullname = 'Guest';
				}
			}

			return array(
				'firstname' => $firstname,
				'lastname'  => $lastname,
				'fullname'  => $fullname,
			);
		}
	}



	if ( ! function_exists( 'ecre_merge_with_custom_settings' ) ) {
		/**
		 * Merges global settings with user-specific custom settings.
		 *
		 * This function merges the provided global settings with custom settings for a specific user. If no user ID is provided
		 * or if no custom settings exist for the user, the function returns the global settings as-is. If the database class
		 * `\ECRE\Ecre_Database` exists, it fetches the user's custom settings from the database and merges them with the global
		 * settings, with the user's settings overriding the global ones. If an error occurs while fetching custom settings,
		 * the global settings are returned.
		 *
		 * @since 1.0.0
		 *
		 * @param array $global_settings The global settings array to be merged.
		 * @param int   $user_id         The ID of the user whose custom settings should be merged (optional).
		 *
		 * @return array The merged settings array, with custom settings overriding the global ones.
		 */
		function ecre_merge_with_custom_settings( $global_settings, $user_id = null ) {
			// If no user ID, return global as-is.
			if ( empty( $user_id ) ) {
				return $global_settings;
			}

			// If database class doesn't exist, return global settings.
			if ( ! class_exists( '\ECRE\Ecre_Database' ) ) {
				return $global_settings;
			}

			try {
				$database        = new \ECRE\Ecre_Database();
				$custom_settings = $database->get_user_custom_settings( $user_id );

				// If no custom settings, return global as-is.
				if ( empty( $custom_settings ) ) {
					return $global_settings;
				}

				// Merge: custom settings override global.
				return array_merge( $global_settings, $custom_settings );

			} catch ( Exception $e ) {
				return $global_settings;
			}
		}
	}
}
