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

namespace DDWCPointsAndRewards\Helper\Dashboard;

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

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

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

		/**
		 * Construct
		 *
		 * @param array $ddwcpr_configuration
		 */
		public function __construct( $ddwcpr_configuration ) {
			global $wpdb;
			$this->wpdb                 = $wpdb;
			$this->ddwcpr_configuration = $ddwcpr_configuration;
		}

		/**
		 * Get dashboard data function
		 *
		 * @return array
		 */
		public function get_dashboard_data() {
			// Get date range for filtering (default to last 30 days)
			$date_range = $this->get_date_range();
			$from_date  = $date_range['from'];
			$to_date    = $date_range['to'];

			// Get summary statistics
			$total_points_issued   = $this->get_total_points_issued( $from_date, $to_date );
			$total_points_redeemed = $this->get_total_points_redeemed( $from_date, $to_date );
			$outstanding_points    = $this->get_outstanding_points( $from_date, $to_date );
			$active_coupons        = $this->get_active_coupons_count();
			$revenue_with_rewards  = $this->get_revenue_with_rewards( $from_date, $to_date );
			$total_discount_value  = $this->get_total_discount_value( $from_date, $to_date );

			// Get chart data
			$points_earned_vs_redeemed = $this->get_points_earned_vs_redeemed_chart_data( $from_date, $to_date );
			$revenue_impact            = $this->get_revenue_impact_chart_data( $from_date, $to_date );

			// Get recent activities
			$recent_activities = $this->get_recent_activities( 10 );

			return [
				'summary' => [
					'total_points_issued'    => $total_points_issued,
					'total_points_redeemed'  => $total_points_redeemed,
					'outstanding_points'     => $outstanding_points,
					'active_coupons'         => $active_coupons,
					'revenue_with_rewards'   => $revenue_with_rewards,
					'total_discount_value'   => $total_discount_value,
				],
				'charts' => [
					'points_earned_vs_redeemed' => $points_earned_vs_redeemed,
					'revenue_impact'            => $revenue_impact,
				],
				'tables' => [
					'recent_activities' => $recent_activities,
				],
				'date_range'   => $date_range,
			];
		}


		/**
		 * Get total points issued
		 *
		 * @param string $from_date
		 * @param string $to_date
		 * @return array
		 */
		public function get_total_points_issued( $from_date, $to_date ) {
			$current_period = $this->wpdb->get_var( $this->wpdb->prepare(
				"SELECT SUM(points) FROM {$this->wpdb->ddwcpr_points_log} 
				WHERE points > 0 AND DATE(date) BETWEEN %s AND %s",
				$from_date, $to_date
			) ) ?: 0;

			// Get previous period for comparison
			$days_diff = ( strtotime( $to_date ) - strtotime( $from_date ) ) / ( 60 * 60 * 24 );
			$prev_from = current_time( 'Y-m-d', false, strtotime( $from_date . ' -' . $days_diff . ' days' ) );
			$prev_to = current_time( 'Y-m-d', false, strtotime( $from_date . ' -1 day' ) );

			$previous_period = $this->wpdb->get_var( $this->wpdb->prepare(
				"SELECT SUM(points) FROM {$this->wpdb->ddwcpr_points_log} 
				WHERE points > 0 AND DATE(date) BETWEEN %s AND %s",
				$prev_from, $prev_to
			) ) ?: 0;

			$change_percentage = $previous_period > 0 ? ( ( $current_period - $previous_period ) / $previous_period ) * 100 : 0;

			return [
				'value'        => intval( $current_period ),
				'change'       => round( $change_percentage, 1 ),
				'is_positive'  => $change_percentage >= 0,
			];
		}

		/**
		 * Get total points redeemed
		 *
		 * @param string $from_date
		 * @param string $to_date
		 * @return array
		 */
		public function get_total_points_redeemed( $from_date, $to_date ) {
			// Only count actual redemptions for rewards (exclude manual adjustments, imports, expiry, and order reversals)
			$current_period = abs( $this->wpdb->get_var( $this->wpdb->prepare(
				"SELECT SUM(points) FROM {$this->wpdb->ddwcpr_points_log} 
				WHERE points < 0 
					AND DATE(date) BETWEEN %s AND %s
					AND event NOT IN ('points_expired')
					AND event NOT LIKE 'order\_%'",
				$from_date, $to_date
			) ) ?: 0 );

			// Get previous period for comparison
			$days_diff = ( strtotime( $to_date ) - strtotime( $from_date ) ) / ( 60 * 60 * 24 );
			$prev_from = date( 'Y-m-d', strtotime( $from_date . ' -' . ceil( $days_diff ) . ' days' ) );
			$prev_to   = date( 'Y-m-d', strtotime( $from_date . ' -1 day' ) );

			$previous_period = abs( $this->wpdb->get_var( $this->wpdb->prepare(
				"SELECT SUM(points) FROM {$this->wpdb->ddwcpr_points_log} 
				WHERE points < 0 
					AND DATE(date) BETWEEN %s AND %s
					AND event NOT IN ('points_expired')
					AND event NOT LIKE 'order\_%'",
				$prev_from, $prev_to
			) ) ?: 0 );

			$change_percentage = $previous_period > 0 ? ( ( $current_period - $previous_period ) / $previous_period ) * 100 : 0;

			return [
				'value'        => intval( $current_period ),
				'change'       => round( abs( $change_percentage ), 1 ),
				'is_positive'  => $change_percentage >= 0,
			];
		}

		/**
		 * Get outstanding points (unredeemed)
		 *
		 * @param string $from_date
		 * @param string $to_date
		 * @return array
		 */
		public function get_outstanding_points( $from_date, $to_date ) {
			// Outstanding points = total available points across all users (current liability)
			// This is the sum of all points in the log (earned - redeemed/expired) up to today
			$current_outstanding = intval( $this->wpdb->get_var(
				"SELECT SUM(points) FROM {$this->wpdb->ddwcpr_points_log}"
			) ?: 0 );

			// Get outstanding points as of the day before the selected period started
			// to calculate the change during the period
			$previous_outstanding = intval( $this->wpdb->get_var( $this->wpdb->prepare(
				"SELECT SUM(points) FROM {$this->wpdb->ddwcpr_points_log}
				WHERE DATE(date) < %s",
				$from_date
			) ) ?: 0 );

			// Calculate change percentage
			$change = 0;
			if ( $previous_outstanding > 0 ) {
				$change = ( ( $current_outstanding - $previous_outstanding ) / $previous_outstanding ) * 100;
			} elseif ( $current_outstanding > 0 && $previous_outstanding == 0 ) {
				$change = 100; // 100% increase if previous was 0
			}

			return [
				'value'        => intval( $current_outstanding ),
				'change'       => round( abs( $change ), 1 ),
				'is_positive'  => $change >= 0,
			];
		}

		/**
		 * Get active coupons count
		 *
		 * @return array
		 */
		public function get_active_coupons_count() {
			$now_ts = current_time( 'timestamp' );
			$count  = (int) $this->wpdb->get_var( $this->wpdb->prepare(
				"SELECT COUNT(DISTINCT p.ID)
				FROM {$this->wpdb->posts} p
				INNER JOIN {$this->wpdb->postmeta} pm_rule 
					ON pm_rule.post_id = p.ID AND pm_rule.meta_key = 'ddwcpr_rule_type'
				LEFT JOIN {$this->wpdb->postmeta} pm_exp 
					ON pm_exp.post_id = p.ID AND pm_exp.meta_key = 'date_expires'
				LEFT JOIN {$this->wpdb->postmeta} pm_usage 
					ON pm_usage.post_id = p.ID AND pm_usage.meta_key = 'usage_count'
				WHERE p.post_type = 'shop_coupon' 
					AND p.post_status = 'publish'
					AND (pm_exp.meta_value IS NULL OR pm_exp.meta_value = '' OR CAST(pm_exp.meta_value AS UNSIGNED) >= %d)
					AND (pm_usage.meta_value IS NULL OR pm_usage.meta_value = '' OR CAST(pm_usage.meta_value AS UNSIGNED) = 0)",
				$now_ts
			) );

			return [
				'value'        => $count,
				'change'       => 0, // No comparison for coupon count
				'is_positive'  => true,
			];
		}

		/**
		 * Get points earned vs redeemed chart data with intelligent time breakdown
		 *
		 * @param string $from_date
		 * @param string $to_date
		 * @return array
		 */
		public function get_points_earned_vs_redeemed_chart_data( $from_date, $to_date ) {
			return $this->get_chart_data_with_grouping( $from_date, $to_date );
		}

		/**
		 * Get top customers by points
		 *
		 * @param int $limit
		 * @return array
		 */
		public function get_top_customers_by_points( $limit = 5 ) {
			$customers = $this->wpdb->get_results( $this->wpdb->prepare(
				"SELECT 
					u.ID,
					u.display_name,
					u.user_email,
					SUM(pl.points) as current_balance
				FROM {$this->wpdb->users} u
				LEFT JOIN {$this->wpdb->ddwcpr_points_log} pl ON u.ID = pl.user_id
				GROUP BY u.ID, u.display_name, u.user_email
					HAVING current_balance > 0
					ORDER BY current_balance DESC
					LIMIT %d",
					$limit
			), ARRAY_A );

			return $customers;
		}

		/**
		 * Get date range for filtering
		 *
		 * @return array
		 */
		public function get_date_range() {
			$range = ! empty( $_GET['date_range'] ) ? sanitize_text_field( wp_unslash( $_GET['date_range'] ) ) : '30_days';

			switch ( $range ) {
				case 'today':
					return [
						'from'  => current_time( 'Y-m-d' ),
						'to'    => current_time( 'Y-m-d' ),
						'label' => esc_html__( 'Today', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case '7_days':
					return [
						'from'  => date( 'Y-m-d', strtotime( 'monday this week' ) ),
						'to'    => current_time( 'Y-m-d' ),
						'label' => esc_html__( 'This Week', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case '30_days':
					return [
						'from'  => current_time( 'Y-m-01' ),
						'to'    => current_time( 'Y-m-d' ),
						'label' => esc_html__( 'This Month', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case 'last_week':
					$last_monday = date( 'Y-m-d', strtotime( 'monday last week' ) );
					$last_sunday = date( 'Y-m-d', strtotime( 'sunday last week' ) );
					return [
						'from'  => $last_monday,
						'to'    => $last_sunday,
						'label' => esc_html__( 'Last Week', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case 'last_month':
					return [
						'from'  => date( 'Y-m-01', strtotime( 'first day of last month' ) ),
						'to'    => date( 'Y-m-t', strtotime( 'last day of last month' ) ),
						'label' => esc_html__( 'Last Month', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case '90_days':
					return [
						'from'  => date( 'Y-m-d', strtotime( '-90 days' ) ),
						'to'    => current_time( 'Y-m-d' ),
						'label' => esc_html__( 'Last 3 Months', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case '180_days':
					return [
						'from'  => date( 'Y-m-d', strtotime( '-180 days' ) ),
						'to'    => current_time( 'Y-m-d' ),
						'label' => esc_html__( 'Last 6 Months', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case 'year_to_date':
					return [
						'from'  => current_time( 'Y-01-01' ),
						'to'    => current_time( 'Y-m-d' ),
						'label' => esc_html__( 'Year to Date', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case 'last_year':
					return [
						'from'  => date( 'Y-01-01', strtotime( '-1 year' ) ),
						'to'    => date( 'Y-12-31', strtotime( '-1 year' ) ),
						'label' => esc_html__( 'Last Year', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case 'all_time':
					return [
						'from'  => '2020-01-01', // Plugin start date
						'to'    => current_time( 'Y-m-d' ),
						'label' => esc_html__( 'All Time', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
				case 'custom':
					$from = ! empty( $_GET['from_date'] ) ? sanitize_text_field( wp_unslash( $_GET['from_date'] ) ) : current_time( 'Y-m-d', false, strtotime( '-30 days' ) );
					$to   = ! empty( $_GET['to_date'] ) ? sanitize_text_field( wp_unslash( $_GET['to_date'] ) ) : current_time( 'Y-m-d' );
					return [
						'from'  => $from,
						'to'    => $to,
						'label' => sprintf( esc_html__( '%s to %s', 'loyaltyx-points-and-rewards-for-woocommerce' ), $from, $to ),
					];
				default:
					return [
						'from'  => current_time( 'Y-m-d', false, strtotime( '-30 days' ) ),
						'to'    => current_time( 'Y-m-d' ),
						'label' => esc_html__( 'This Month', 'loyaltyx-points-and-rewards-for-woocommerce' ),
					];
			}
		}

		/**
		 * Get chart data with intelligent grouping
		 *
		 * @param string $from_date
		 * @param string $to_date
		 * @param string $user_where_clause Additional WHERE clause for user-specific data
		 * @return array
		 */
		public function get_chart_data_with_grouping( $from_date, $to_date, $user_where_clause = '' ) {
			// Determine appropriate grouping and date format based on range
			$days_diff = ( strtotime( $to_date ) - strtotime( $from_date ) ) / ( 60 * 60 * 24 );

			if ( $days_diff <= 7 ) {
				// 1 week or less: group by day
				$date_format         = 'Y-m-d';
				$group_by            = 'DATE(date)';
				$date_display_format = 'M j';
			} elseif ( $days_diff <= 90 ) {
				// 3 months or less: group by day for better granularity
				$date_format         = 'Y-m-d';
				$group_by            = 'DATE(date)';
				$date_display_format = 'M j';
			} elseif ( $days_diff <= 365 ) {
				// 1 year or less: group by month
				$date_format         = 'Y-m';
				$group_by            = 'DATE_FORMAT(date, "%Y-%m")';
				$date_display_format = 'M Y';
			} else {
				// More than 1 year: group by quarter
				$date_format         = 'Y-m';
				$group_by            = 'CONCAT(YEAR(date), "-Q", QUARTER(date))';
				$date_display_format = 'Q Y';
			}

			$where_clause = "WHERE DATE(date) BETWEEN %s AND %s";
			if ( $user_where_clause ) {
				$where_clause .= " AND " . $user_where_clause;
			}

			$data = $this->wpdb->get_results( $this->wpdb->prepare(
				"SELECT 
					{$group_by} as period,
					SUM(CASE WHEN points > 0 THEN points ELSE 0 END) as earned,
					SUM(CASE WHEN points < 0 THEN ABS(points) ELSE 0 END) as redeemed
				FROM {$this->wpdb->ddwcpr_points_log} 
					{$where_clause}
					GROUP BY {$group_by} 
					ORDER BY period ASC",
				$from_date, $to_date
			), ARRAY_A );

			// Process the data to ensure consistent date format
			$data_by_date = [];

			// First, organize data by date
			foreach ( $data as $row ) {
				$date_value = $row['period'];

				// Convert different period formats to a consistent date for display
				if ( $days_diff > 365 ) {
					// For quarterly data, convert to first month of quarter
					$year = substr( $date_value, 0, 4 );
					$quarter = substr( $date_value, -1 );
					$month = ( $quarter - 1 ) * 3 + 1;
					$date = $year . '-' . str_pad( $month, 2, '0', STR_PAD_LEFT ) . '-01';
				} else {
					// For daily/monthly data, use as is
					$date = $date_value;
				}

				$data_by_date[$date] = [
					'date'     => $date,
					'earned'   => intval( $row['earned'] ),
					'redeemed' => intval( $row['redeemed'] )
				];
			}

			// Fill in missing dates with zero values for daily data
			if ( $days_diff <= 90 ) {
				$current_date = $from_date;
				while ( $current_date <= $to_date ) {
					if ( ! isset( $data_by_date[$current_date] ) ) {
						$data_by_date[$current_date] = [
							'date'     => $current_date,
							'earned'   => 0,
							'redeemed' => 0
						];
					}
					$current_date = date( 'Y-m-d', strtotime( $current_date . ' +1 day' ) );
				}
			}

			// Sort by date and return
			ksort( $data_by_date );
			return array_values( $data_by_date );
		}

		/**
		 * Generate chart colors using brand color shades only
		 *
		 * @param int $count
		 * @return array
		 */
		public function generate_chart_colors( $count ) {
			$colors = [];
			// Brand color shades - different shades of blue
			$brand_shades = [
				'#0256ff', // Primary blue
				'#3b82f6', // Lighter blue
				'#60a5fa', // Even lighter blue
				'#93c5fd', // Light blue
				'#dbeafe', // Very light blue
				'#1e40af', // Darker blue
				'#1d4ed8', // Dark blue
				'#2563eb', // Medium blue
				'#1e3a8a', // Very dark blue
				'#312e81'  // Darkest blue
			];

			for ( $i = 0; $i < $count; $i++ ) {
				$base_color = $brand_shades[$i % count( $brand_shades )];
				$colors[] = [
					'background' => $base_color,
					'border'     => '#f2f2f2' // Consistent light border
				];
			}

			return $colors;
		}

		/**
		 * Get recent activities
		 *
		 * @param int $limit
		 * @param string $user_where_clause Additional WHERE clause for user-specific data
		 * @return array
		 */
		public function get_recent_activities( $limit = 10, $user_where_clause = '' ) {
			$where_clause = "WHERE 1=1";
			if ( $user_where_clause ) {
				$where_clause .= " AND " . $user_where_clause;
			}

			$activities = $this->wpdb->get_results( $this->wpdb->prepare(
				"SELECT 
					pl.*,
					u.display_name,
					u.user_email
				FROM {$this->wpdb->ddwcpr_points_log} pl
				LEFT JOIN {$this->wpdb->users} u ON pl.user_id = u.ID
				{$where_clause}
				ORDER BY pl.date DESC
				LIMIT %d",
				$limit
			), ARRAY_A );

			return $activities ?: [];
		}

		/**
		 * Get revenue from orders with rewards (where rewards coupons were applied)
		 *
		 * @param string $from_date
		 * @param string $to_date
		 * @return array
		 */
		public function get_revenue_with_rewards( $from_date, $to_date ) {
			// Get orders with rewards coupons applied (orders where _ddwcpr_coupon_applied meta is set)
			$order_ids = wc_get_orders( [
				'limit'        => -1,
				'return'       => 'ids',
				'status'       => [ 'wc-completed', 'wc-processing' ],
				'date_created' => $from_date . '...' . $to_date,
				'meta_key'     => '_ddwcpr_coupon_applied',
				'meta_value'   => '1',
			] );

			if ( empty( $order_ids ) ) {
				return [
					'value'       => 0,
					'change'      => 0,
					'is_positive' => true,
				];
			}

			// Calculate total revenue from orders where rewards coupons were used
			$revenue = 0;
			foreach ( (array) $order_ids as $oid ) {
				$order = wc_get_order( $oid );
				if ( ! $order ) { continue; }
				$revenue += (float) $order->get_total();
			}

			// Get previous period for comparison
			$days_diff = ( strtotime( $to_date ) - strtotime( $from_date ) ) / ( 60 * 60 * 24 );
			$prev_from = date( 'Y-m-d', strtotime( $from_date . ' -' . ceil( $days_diff ) . ' days' ) );
			$prev_to   = date( 'Y-m-d', strtotime( $from_date . ' -1 day' ) );

			$prev_order_ids = wc_get_orders( [
				'limit'        => -1,
				'return'       => 'ids',
				'status'       => [ 'wc-completed', 'wc-processing' ],
				'date_created' => $prev_from . '...' . $prev_to,
				'meta_key'     => '_ddwcpr_coupon_applied',
				'meta_value'   => '1',
			] );

			$prev_revenue = 0;
			if ( ! empty( $prev_order_ids ) ) {
				foreach ( (array) $prev_order_ids as $oid ) {
					$order = wc_get_order( $oid );
					if ( ! $order ) { continue; }
					$prev_revenue += (float) $order->get_total();
				}
			}

			$change = $prev_revenue > 0 ? ( ( $revenue - $prev_revenue ) / $prev_revenue ) * 100 : 0;

			return [
				'value'       => round( $revenue, 2 ),
				'change'      => round( abs( $change ), 1 ),
				'is_positive' => $change >= 0,
			];
		}

		/**
		 * Get revenue impact chart data (comparing revenue with rewards vs without)
		 *
		 * @param string $from_date
		 * @param string $to_date
		 * @return array
		 */
		public function get_revenue_impact_chart_data( $from_date, $to_date ) {
			$days_diff = ( strtotime( $to_date ) - strtotime( $from_date ) ) / ( 60 * 60 * 24 );

			// Determine grouping based on date range (match points chart logic)
			if ( $days_diff <= 90 ) {
				$interval_str = 'day';
			} elseif ( $days_diff <= 365 ) {
				$interval_str = 'month';
			} else {
				$interval_str = 'quarter';
			}

			// Get all orders in the period (HPOS-safe)
			$order_ids = wc_get_orders( [
				'limit'       => -1,
				'return'      => 'ids',
				'status'      => [ 'wc-completed', 'wc-processing' ],
				'date_after'  => new \WC_DateTime( $from_date . ' 00:00:00', new \DateTimeZone( wc_timezone_string() ) ),
				'date_before' => new \WC_DateTime( $to_date . ' 23:59:59', new \DateTimeZone( wc_timezone_string() ) ),
			] );

			// Identify orders with rewards by order meta flag set at checkout
			$reward_order_ids = [];
			foreach ( (array) $order_ids as $oid ) {
				$order = wc_get_order( $oid );
				if ( ! $order ) { continue; }
				if ( $order->get_meta( '_ddwcpr_coupon_applied' ) ) {
					$reward_order_ids[] = (int) $oid;
				}
			}

			// Build labels + index map once
			$labels               = [];
			$with_rewards_data    = [];
			$without_rewards_data = [];
			$label_index          = [];

			if ( 'day' === $interval_str ) {
				$current = $from_date; $idx = 0;
				while ( $current <= $to_date ) {
					$labels[] = $current;
					$with_rewards_data[] = 0;
					$without_rewards_data[] = 0;
					$label_index[ $current ] = $idx++;
					$current = date( 'Y-m-d', strtotime( $current . ' +1 day' ) );
				}
			} elseif ( 'month' === $interval_str ) {
				$start = new \DateTime( date( 'Y-m-01', strtotime( $from_date ) ) );
				$end   = new \DateTime( date( 'Y-m-01', strtotime( $to_date ) ) );
				$idx = 0;
				while ( $start <= $end ) {
					$key = $start->format( 'Y-m-01' );
					$labels[] = $key;
					$with_rewards_data[] = 0;
					$without_rewards_data[] = 0;
					$label_index[ $key ] = $idx++;
					$start->modify( '+1 month' );
				}
			} else { // quarter
				$sy = intval( date( 'Y', strtotime( $from_date ) ) );
				$sm = intval( date( 'n', strtotime( $from_date ) ) );
				$sq = intval( ceil( $sm / 3 ) );
				$ey = intval( date( 'Y', strtotime( $to_date ) ) );
				$em = intval( date( 'n', strtotime( $to_date ) ) );
				$eq = intval( ceil( $em / 3 ) );

				$y = $sy; $q = $sq; $idx = 0;
				while ( $y < $ey || ( $y === $ey && $q <= $eq ) ) {
					$month = ( $q - 1 ) * 3 + 1;
					$key = sprintf( '%04d-%02d-01', $y, $month );
					$labels[] = $key;
					$with_rewards_data[] = 0;
					$without_rewards_data[] = 0;
					$label_index[ $key ] = $idx++;
					$q++;
					if ( $q > 4 ) { $q = 1; $y++; }
				}
			}

			// Single pass accumulation
			foreach ( (array) $order_ids as $oid ) {
				$order = wc_get_order( $oid );
				if ( ! $order ) { continue; }
				$created = $order->get_date_created();
				if ( ! $created ) { continue; }
				$y = (int) $created->date_i18n( 'Y' );
				$m = (int) $created->date_i18n( 'n' );
				$label = '';
				if ( 'day' === $interval_str ) {
					$label = $created->date_i18n( 'Y-m-d' );
				} elseif ( 'month' === $interval_str ) {
					$label = sprintf( '%04d-%02d-01', $y, $m );
				} else {
					$q = (int) ceil( $m / 3 );
					$label = sprintf( '%04d-%02d-01', $y, ( ( $q - 1 ) * 3 + 1 ) );
				}
				if ( ! isset( $label_index[ $label ] ) ) { continue; }
				$i = $label_index[ $label ];
				$total = (float) $order->get_total();
				if ( in_array( $oid, $reward_order_ids, true ) ) {
					$with_rewards_data[ $i ] += $total;
				} else {
					$without_rewards_data[ $i ] += $total;
				}
			}

			// Return raw data - datasets will be configured in JavaScript
			$data = [];
			foreach ( $labels as $index => $date ) {
				$data[] = [
					'date'            => $date,
					'with_rewards'    => $with_rewards_data[ $index ],
					'without_rewards' => $without_rewards_data[ $index ],
				];
			}

			return $data;
		}

		/**
		 * Get total discount value from rewards coupons applied to orders
		 *
		 * @param string $from_date
		 * @param string $to_date
		 * @return array
		 */
		public function get_total_discount_value( $from_date, $to_date ) {
			// Get orders where rewards coupons were applied
			$order_ids = wc_get_orders( [
				'limit'        => -1,
				'return'       => 'ids',
				'status'       => [ 'wc-completed', 'wc-processing' ],
				'date_created' => $from_date . '...' . $to_date,
				'meta_key'     => '_ddwcpr_coupon_applied',
				'meta_value'   => '1',
			] );

			$total_discount = 0;

			if ( ! empty( $order_ids ) ) {
				foreach ( (array) $order_ids as $oid ) {
					$order = wc_get_order( $oid );
					if ( ! $order ) { continue; }

					// Get the rewards coupon IDs used in this order
					$rewards_coupon_ids = $order->get_meta( '_ddwcpr_coupon_ids' );
					if ( empty( $rewards_coupon_ids ) || ! is_array( $rewards_coupon_ids ) ) {
						continue;
					}

					// Get all coupons used in this order
					$order_coupons = $order->get_items( 'coupon' );
					
					foreach ( $order_coupons as $item_id => $item ) {
						$coupon_code = $item->get_code();
						$coupon = new \WC_Coupon( $coupon_code );
						
						// Check if this coupon is one of the rewards coupons
						if ( $coupon && $coupon->get_id() && in_array( $coupon->get_id(), $rewards_coupon_ids ) ) {
							// Get the discount amount for this specific coupon
							$discount_amount = (float) $item->get_discount();
							$total_discount += $discount_amount;
						}
					}
				}
			}

			// Get previous period for comparison
			$days_diff = ( strtotime( $to_date ) - strtotime( $from_date ) ) / ( 60 * 60 * 24 );
			$prev_from = date( 'Y-m-d', strtotime( $from_date . ' -' . ceil( $days_diff ) . ' days' ) );
			$prev_to   = date( 'Y-m-d', strtotime( $from_date . ' -1 day' ) );

			$prev_order_ids = wc_get_orders( [
				'limit'        => -1,
				'return'       => 'ids',
				'status'       => [ 'wc-completed', 'wc-processing' ],
				'date_created' => $prev_from . '...' . $prev_to,
				'meta_key'     => '_ddwcpr_coupon_applied',
				'meta_value'   => '1',
			] );

			$prev_discount = 0;

			if ( ! empty( $prev_order_ids ) ) {
				foreach ( (array) $prev_order_ids as $oid ) {
					$order = wc_get_order( $oid );
					if ( ! $order ) { continue; }

					$rewards_coupon_ids = $order->get_meta( '_ddwcpr_coupon_ids' );
					if ( empty( $rewards_coupon_ids ) || ! is_array( $rewards_coupon_ids ) ) {
						continue;
					}

					$order_coupons = $order->get_items( 'coupon' );
					
					foreach ( $order_coupons as $item_id => $item ) {
						$coupon_code = $item->get_code();
						$coupon = new \WC_Coupon( $coupon_code );
						
						if ( $coupon && $coupon->get_id() && in_array( $coupon->get_id(), $rewards_coupon_ids ) ) {
							$discount_amount = (float) $item->get_discount();
							$prev_discount += $discount_amount;
						}
					}
				}
			}

			$change = $prev_discount > 0 ? ( ( $total_discount - $prev_discount ) / $prev_discount ) * 100 : 0;

			return [
				'value'       => round( $total_discount, 2 ),
				'change'      => round( abs( $change ), 1 ),
				'is_positive' => $change >= 0,
			];
		}
	}
}
