<?php
/**
 * File: Ecre_Order_Tracking.php
 *
 * The Ecre_Order_Tracking class is responsible for tracking referral orders when an order is completed in WooCommerce.
 *
 * @package ECRE
 * @since   1.0.0
 */

namespace ECRE;

if ( ! class_exists( 'Ecre_Order_Tracking' ) ) {
	/**
	 * The Ecre_Order_Tracking class handles tracking referral orders.
	 *
	 * @since 1.0.0
	 */
	class Ecre_Order_Tracking {
		/**
		 * Holds the settings configuration for the ECRE order tracking system.
		 *
		 * This property stores various settings retrieved from the database,
		 * such as email templates, discount configurations, and tracking options.
		 *
		 * @var array
		 */
		public $erce_settings;

		/**
		 * Holds the settings configuration for the ECRE order tracking system.
		 *
		 * This property stores various settings retrieved from the database,
		 * such as email templates, discount configurations, and tracking options.
		 *
		 * @var array
		 */
		public $is_pro;

		/**
		 * The default plugin settings used for order tracking behavior.
		 *
		 * @var array
		 */
		public $default_settings;

		private $database;

		/**
		 * Ecre_Order_Tracking constructor.
		 *
		 * Initializes the Ecre_Order_Tracking class and hooks into the
		 * 'woocommerce_order_status_completed' action to track and process
		 * referral-related logic upon order completion.
		 *
		 * @param bool  $is_pro           Indicates whether the user has a professional (pro) account.
		 * @param array $default_settings The default plugin settings used for order tracking behavior.
		 *
		 * @since 1.0.0
		 */
		public function __construct( $is_pro, $default_settings ) {
			$this->erce_settings    = get_option( 'ecre_settings', array() );
			$this->is_pro           = $is_pro;
			$this->default_settings = $default_settings;

			if ( class_exists( '\ECRE\Ecre_Database' ) ) {
				$this->database = new \ECRE\Ecre_Database();
			}

			add_action( 'woocommerce_order_status_changed', array( $this, 'ecre_track_referral_orders_on_status_change' ), 10, 4 );
			add_action( 'ecre_reward_scheduled', array( $this, 'ecre_track_referral_orders_on_completed_scheduled' ), 10, 1 );
			add_action( 'woocommerce_admin_order_data_after_order_details', array( $this, 'ecre_display_referral_details_in_order_admin' ), 10, 1 );
		}

		/**
		 * Tracks referral orders when a WooCommerce order status changes.
		 *
		 * This function checks if an order's status changes to 'completed'. If so, it processes referral
		 * rewards by generating coupons or reward points for referrers.
		 *
		 * @param int    $order_id   The unique WooCommerce order ID.
		 * @param string $old_status The previous status of the order.
		 * @param string $new_status The new status of the order.
		 * @param object $order      The WooCommerce order object.
		 *
		 * @since 2.3.1
		 *
		 * @return void
		 */
		public function ecre_track_referral_orders_on_status_change( $order_id, $old_status, $new_status, $order ) {
			// $order = wc_get_order( $order_id );

			if ( ! $order ) {
				return;
			}

			// CHANGE THIS: Use existing database instance.
			if ( $this->database ) {
				$this->database->update_referral_status( $order_id, $new_status );
			}

			$reward_status = ! $this->is_pro
			? 'completed'
			: ( isset( $this->erce_settings['rewardOrderStatus']['value'] )
				? str_replace( 'wc-', '', $this->erce_settings['rewardOrderStatus']['value'] )
				: 'completed'
			);

			$enable_reward_delay_time = isset( $this->erce_settings['enableRewardDelayTime'] ) ? $this->erce_settings['enableRewardDelayTime'] : false;
			$reward_delay_day         = isset( $this->erce_settings['rewardDelayTime'] ) ? $this->erce_settings['rewardDelayTime'] : 0;

			if ( $new_status === $reward_status ) {
				if ( $this->is_pro && $enable_reward_delay_time && $reward_delay_day > 0 ) {
					$schedule_status = get_post_meta( $order_id, 'ecre_reward_schedule_status', true );

					if ( 'complete' !== $schedule_status && 'cancelled' !== $schedule_status ) {
						// Calculate the timestamp for the scheduled event.
						$timestamp = time() + ( $reward_delay_day * DAY_IN_SECONDS );

						// Create a unique hook name for the order.
						$unique_hook = 'ecre_schedule_referral_order_completion_' . $order_id;

						// Clear any previously scheduled event for the same order.
						if ( wp_next_scheduled( $unique_hook, array( $order_id ) ) ) {
							wp_clear_scheduled_hook( $unique_hook, array( $order_id ) );
						}

						// Schedule the event.
						wp_schedule_single_event( $timestamp, 'ecre_reward_scheduled', array( $order_id ) );
					}
				} else {
					// Run immediately if no delay is specified.
					$this->ecre_track_referral_orders_on_completed( $order_id );
				}
			}
		}

		/**
		 * Handles scheduled referral order completion.
		 *
		 * @param int $order_id The WooCommerce order ID.
		 */
		public function ecre_track_referral_orders_on_completed_scheduled( $order_id ) {
			update_post_meta( $order_id, 'ecre_reward_schedule_status', 'complete' );
			$this->ecre_track_referral_orders_on_completed( $order_id );
		}

		/**
		 * Tracks referral orders upon order completion and generates rewards for referrers.
		 *
		 * This function checks if a completed order used a referral coupon. If so, it generates a reward
		 * (coupon or reward points) for the referrer, marks the order as processed for rewards, and
		 * optionally sends a reward notification email.
		 *
		 * @param int $order_id The ID of the completed order.
		 *
		 * @return void
		 */
		public function ecre_track_referral_orders_on_completed( $order_id ) {
			$order = wc_get_order( $order_id );

			if ( ! $order ) {
				return;
			}

			// Check if the order already has a coupon generated.
			$coupon_generated       = get_post_meta( $order_id, 'ecre_reward_coupon_generated', true );
			$reward_point_generated = get_post_meta( $order_id, 'ecre_reward_point_generated', true );

			if ( $coupon_generated || $reward_point_generated ) {
				return;
			}

			$user_id                    = absint( $order->get_user_id() );
			$coupons_used               = $order->get_coupon_codes();
			$enable_email_notifications = isset( $this->erce_settings['enableRewardEmailInvitation'] ) ? $this->erce_settings['enableRewardEmailInvitation'] : false;
			$reward_type                = '';
			$settings_reward_type       = isset( $this->erce_settings['rewardType']['value'] ) ? $this->erce_settings['rewardType']['value'] : '';

			if ( ! $this->is_pro && ( 'percent' !== $settings_reward_type && 'fixed' !== $settings_reward_type ) ) {
				$reward_type = $this->default_settings['rewardType']['value'];
			} else {
				$reward_type = $settings_reward_type;
			}

			if ( ! empty( $coupons_used ) ) {
				foreach ( $coupons_used as $coupon_code ) {
					$coupon_id        = wc_get_coupon_id_by_code( $coupon_code );
					$referral_user_id = absint( get_post_meta( $coupon_id, 'referral_user_id', true ) );

					// Check if user ID is available.
					if ( $user_id ) {
						$user_id = (int) $user_id;
					}

					// Check if referral user ID is available.
					if ( $referral_user_id ) {
						$referral_user_id = (int) $referral_user_id;
					}

					if ( $referral_user_id ) {
						$inserted_coupon = '';

						if ( $this->is_pro ) {
							if ( 'reward_point' === strval( $reward_type ) ) {
								echo_rewards_pro()->helpers->generate_reward_point( $referral_user_id, $order_id );
								update_post_meta( $order_id, 'ecre_reward_point_generated', true );
							} else {
								$inserted_coupon = echo_rewards_pro()->helpers->generate_reward_coupon( $referral_user_id, $order_id );
								update_post_meta( $coupon_id, 'applied_coupon_code', esc_html( $inserted_coupon ) );
								update_post_meta( $order_id, 'ecre_reward_coupon_generated', true );
							}
						} else {
							$inserted_coupon = $this->ecre_generate_reward_coupon( $referral_user_id, $coupon_id, $coupon_code, $order_id );
							update_post_meta( $coupon_id, 'applied_coupon_code', esc_html( $inserted_coupon ) );
							update_post_meta( $order_id, 'ecre_reward_coupon_generated', true );
						}

						// Update referrer reward stats (total_rewards_issued + conversion_rate).
						if ( $this->database ) {
							$this->database->update_referrer_rewards_on_completion( $referral_user_id );
							$this->database->update_dashboard_summary_rewards_on_completion( $referral_user_id );
						}

						// If enable mail settings then only run.
						if ( $enable_email_notifications ) {
							$wc_emails    = WC()->mailer();
							$emails_array = $wc_emails ? $wc_emails->get_emails() : array();
							
							if ( isset( $emails_array['Ecre_Email'] ) && is_object( $emails_array['Ecre_Email'] ) ) {
								$emails_array['Ecre_Email']->trigger( $referral_user_id, esc_html( $inserted_coupon ) );
							}
						}
					}

					update_post_meta( $order_id, 'ecre_referral_order_completed', true );
				}
			}
		}

		/**
		 * Generates a reward coupon for a given user ID if the user does not already have one.
		 *
		 * This function creates a unique reward coupon for a user based on various settings such as discount amount,discount type
		 * (percent or fixed), product/category restrictions, subscription limits, and more. The coupon is created using WooCommerce's
		 * `shop_coupon` post type, and metadata is saved for various coupon properties like usage limit, valid products, and categories.
		 * After creating the coupon, the function stores coupon-related data in the database for easy retrieval, including associating
		 * it with the referrer and the order.
		 *
		 * @since 1.0.0
		 *
		 * @param int    $referral_user_id     The ID of the user for whom the reward coupon is generated.
		 * @param int    $referral_coupon_id   The referral coupon ID associated with the user.
		 * @param string $referral_coupon_code The referral coupon code associated with the user.
		 * @param int    $order_id             The ID of the order associated with the referral.
		 *
		 * @return string|false The generated coupon code, or `false` if the coupon could not be created.
		 */
		public function ecre_generate_reward_coupon( $referral_user_id, $referral_coupon_id, $referral_coupon_code, $order_id ) {
			$this->erce_settings = ecre_merge_with_custom_settings( $this->erce_settings, $referral_user_id );
			// Generate a new reward coupon.
			$coupon_code          = ecre_generate_unique_coupon_code();
			$currency_symbol      = ecre_custom_currency_symbol();
			$amount               = $this->erce_settings['rewardDiscount'];
			$settings_reward_type = isset( $this->erce_settings['rewardType']['value'] ) ? $this->erce_settings['rewardType']['value'] : '';
			$discount_type        = '';

			if ( ! $this->is_pro && ( 'percent' !== $settings_reward_type && 'fixed' !== $settings_reward_type ) ) {
				$discount_type = $this->default_settings['rewardType']['value'];
			} else {
				$discount_type = $settings_reward_type;
			}

			$discount                  = ( 'percent' === $discount_type ) ? $amount . '%' : $amount . $currency_symbol;
			$selected_product_ids      = isset( $this->erce_settings['rewardIncludeProducts'] ) && is_array( $this->erce_settings['rewardIncludeProducts'] ) ? array_column( $this->erce_settings['rewardIncludeProducts'], 'value' ) : array();
			$exclude_product_ids       = isset( $this->erce_settings['rewardExcludeProducts'] ) && is_array( $this->erce_settings['rewardExcludeProducts'] ) ? array_column( $this->erce_settings['rewardExcludeProducts'], 'value' ) : array();
			$selected_categories       = isset( $this->erce_settings['rewardIncludeCategories'] ) && is_array( $this->erce_settings['rewardIncludeCategories'] ) ? array_column( $this->erce_settings['rewardIncludeCategories'], 'value' ) : array();
			$exclude_categories        = isset( $this->erce_settings['rewardExcludeCategories'] ) && is_array( $this->erce_settings['rewardExcludeCategories'] ) ? array_column( $this->erce_settings['rewardExcludeCategories'], 'value' ) : array();
			$enable_subscription_limit = $this->erce_settings['enableRewardLimitSubscriptionCoupon'];
			$subscription_limit        = $this->erce_settings['rewardLimitSubscriptionCoupon'];

			$coupon = array(
				'post_title'   => $coupon_code,
				'post_content' => $discount . ' off coupon',
				'post_excerpt' => $discount . ' off coupon',
				'post_status'  => 'publish',
				'post_author'  => $referral_user_id,
				'post_type'    => 'shop_coupon',
			);

			$new_coupon_id = wp_insert_post( $coupon );

			// Handle Expiry Date.
			$enable_expiry = isset( $this->erce_settings['enableRewardExpiry'] ) ? $this->erce_settings['enableRewardExpiry'] : 0;
			$validity_days = isset( $this->erce_settings['rewardCouponValidity'] ) ? (int) $this->erce_settings['rewardCouponValidity'] : 0;
			$expiry_date   = null;

			if ( $enable_expiry && $validity_days > 0 ) {
				$expiry_date = gmdate( 'Y-m-d', strtotime( "+{$validity_days} days" ) );
				update_post_meta( $new_coupon_id, 'date_expires', $expiry_date );
			}

			if ( $this->is_pro && ! empty( $enable_subscription_limit ) ) {
				update_post_meta( $new_coupon_id, '_wcs_number_payments', $subscription_limit );
			}

			update_post_meta( $new_coupon_id, 'discount_type', $discount_type );
			update_post_meta( $new_coupon_id, 'coupon_amount', $amount );
			update_post_meta( $new_coupon_id, 'individual_use', 'yes' );
			update_post_meta( $new_coupon_id, 'reward_user_id', $referral_user_id );
			if ( $this->erce_settings['enableRewardCouponUsageLimit'] && $this->erce_settings['rewardCouponUsageLimit'] > 0 ) {
				update_post_meta( $new_coupon_id, 'usage_limit', $this->erce_settings['rewardCouponUsageLimit'] );
			}

			if ( ! empty( $selected_product_ids ) ) {
				update_post_meta( $new_coupon_id, 'product_ids', implode( ',', $selected_product_ids ) );
			}

			if ( ! empty( $exclude_product_ids ) ) {
				update_post_meta( $new_coupon_id, 'exclude_product_ids', implode( ',', $exclude_product_ids ) );
			}

			if ( ! empty( $selected_categories ) ) {
				update_post_meta( $new_coupon_id, 'product_categories', $selected_categories );
			}

			if ( ! empty( $exclude_categories ) ) {
				update_post_meta( $new_coupon_id, 'exclude_product_categories', $exclude_categories );
			}

			$new_coupon           = new \WC_Coupon( $new_coupon_id );
			$inserted_coupon_code = $new_coupon->get_code();
			update_post_meta( $order_id, 'ecre_reward_coupon_code', $inserted_coupon_code );
			update_post_meta( $order_id, 'ecre_reward_coupon_id', $new_coupon_id );

			update_post_meta( $new_coupon_id, 'ecre_applied_referral_user_id', $referral_user_id );
			update_post_meta( $new_coupon_id, 'ecre_applied_referral_coupon_code', $referral_coupon_code );
			update_post_meta( $new_coupon_id, 'ecre_applied_referral_coupon_id', $referral_coupon_id );

			// Store coupon in our dedicated reward coupons table.
			if ( class_exists( '\ECRE\Ecre_Database' ) ) {

				$coupon_data = array(
					'referrer_user_id'      => $referral_user_id,
					'order_id'              => $order_id,
					'coupon_code'           => $inserted_coupon_code,
					'coupon_id'             => $new_coupon_id,
					'discount_type'         => $discount_type,
					'discount_amount'       => $amount,
					'usage_limit'           => $this->erce_settings['enableRewardCouponUsageLimit'] ? $this->erce_settings['rewardCouponUsageLimit'] : 0,
					'usage_count'           => 0,
					'status'                => 'active',
					'expires_at'            => ( $enable_expiry && $validity_days > 0 ) ? gmdate( 'Y-m-d H:i:s', strtotime( "+{$validity_days} days" ) ) : null,
					'include_products'              => ! empty( $selected_product_ids ) ? $selected_product_ids : null,
					'exclude_products'              => ! empty( $exclude_product_ids ) ? $exclude_product_ids : null,
					'include_product_categories'    => ! empty( $selected_categories ) ? $selected_categories : null,
					'exclude_product_categories'    => ! empty( $exclude_categories ) ? $exclude_categories : null,
				);

				$this->database->store_reward_coupon_data( $coupon_data );
			}

			return $inserted_coupon_code;
		}

		/**
		 * Display referral details in the WooCommerce admin order details page.
		 *
		 * This function checks for a '_referral_user_id' post meta in the order. If it exists,
		 * it fetches the corresponding user's details and displays them in the admin order details page.
		 *
		 * @param WC_Order $order The WooCommerce order object.
		 */
		public function ecre_display_referral_details_in_order_admin( $order ) {
			$order_id = $order->get_id();
			// Get the referral user ID from the order meta.
			$referral_user_id = get_post_meta( $order_id, '_referral_user_id', true );
			$reward_user_id   = get_post_meta( $order_id, '_reward_user_id', true );

			$reward_type          = '';
			$settings_reward_type = isset( $this->erce_settings['rewardType']['value'] ) ? $this->erce_settings['rewardType']['value'] : '';

			if ( ! $this->is_pro && ( 'percent' !== $settings_reward_type && 'fixed' !== $settings_reward_type ) ) {
				$reward_type = $this->default_settings['rewardType']['value'];
			} else {
				$reward_type = $settings_reward_type;
			}

			if ( ! empty( $referral_user_id ) ) {
				// Get user data based on the referral user ID.
				$user    = get_user_by( 'id', $referral_user_id );
				$coupons = $order->get_coupon_codes();

				// Get the scheduled reward timestamp.
				$scheduled_time     = wp_next_scheduled( 'ecre_reward_scheduled', array( $order_id ) );
				$schedule_status    = get_post_meta( $order_id, 'ecre_reward_schedule_status', true );
				$reward_coupon_code = get_post_meta( $order_id, 'ecre_reward_coupon_code', true );
				$reward_coupon_id   = get_post_meta( $order_id, 'ecre_reward_coupon_id', true );
				$reward_point       = get_post_meta( $order_id, 'ecre_reward_point', true );

				if ( $user ) {
					?>
					<div class="ecre-referral-details" style="margin-top:20px; display:inline-block; width:100%;">
						<h4>
							<?php echo esc_html__( 'Referral Details', 'echo-rewards' ); ?>:
						</h4>
						<p>
							<strong>
								<?php echo esc_html__( 'Referrer', 'echo-rewards' ); ?>:
							</strong>
							<a href="mailto:<?php echo esc_attr( $user->user_email ); ?>">
								<?php echo esc_html( $user->user_email ); ?>
							</a>  
							<span style="margin-left:3px;">| <?php echo esc_html( $user->display_name ); ?> </span>
						</p>
						<p>
							<strong>
								<?php echo esc_html__( 'Referral coupon', 'echo-rewards' ); ?>:
							</strong>
							<span>
								<?php
								$coupons = $order->get_coupon_codes();
								echo ! empty( $coupons ) ? esc_html( implode( ', ', $coupons ) ) : esc_html__( 'None', 'echo-rewards' );
								?>
							</span>
						</p>
				
						<p>
							<?php if ( 'reward_point' !== $reward_type ) { ?>
								<strong><?php echo esc_html__( 'Reward coupon', 'echo-rewards' ); ?>:</strong>
								<span>
									<?php
									if ( $scheduled_time ) {
										$time_remaining = human_time_diff( time(), $scheduled_time );
										// translators: %s is the time remaining until the reward is issued.
										printf( esc_html__( 'Will be issued in %s', 'echo-rewards' ), esc_html( $time_remaining ) );
									} elseif ( ! empty( $reward_coupon_id ) ) {
										$coupon = new \WC_Coupon( $reward_coupon_id );
										if ( $coupon && $coupon->get_id() ) {
											echo esc_html( $coupon->get_code() );
											$coupon_edit_link = admin_url( 'post.php?post=' . absint( $reward_coupon_id ) . '&action=edit' );
											echo ' <a href="' . esc_url( $coupon_edit_link ) . '" style="color:#0073aa; text-decoration:underline;">' . esc_html__( 'Manage', 'echo-rewards' ) . '</a>';
										} else {
											echo esc_html__( 'Not available', 'echo-rewards' );
										}
									} else {
										echo esc_html__( 'Not available', 'echo-rewards' );
									}
									?>
								</span>
							<?php } ?>

							<?php if ( 'reward_point' === $reward_type ) { ?>
								<strong><?php echo esc_html__( 'Reward points', 'echo-rewards' ); ?>:</strong>
								<span>
									<?php
									if ( $scheduled_time ) {
										$time_remaining = human_time_diff( time(), $scheduled_time );
										// translators: %s is the time remaining until the reward is issued.
										printf( esc_html__( 'Will be issued in %s', 'echo-rewards' ), esc_html( $time_remaining ) );
									} elseif ( ! empty( $reward_point ) ) {
										echo esc_html( $reward_point ) . ' ' . esc_html__( 'points', 'echo-rewards' );
									} else {
										echo esc_html__( 'Not available', 'echo-rewards' );
									}
									?>
								</span>
							<?php } ?>

							<?php if ( $scheduled_time ) : ?>
								<a href="#" class="button issue-now" data-order-id="<?php echo esc_attr( $order_id ); ?>">
									<?php esc_html_e( 'Issue Now', 'echo-rewards' ); ?>
								</a>
								<a href="#" class="button cancel-schedule" data-order-id="<?php echo esc_attr( $order_id ); ?>">
									<?php esc_html_e( 'Cancel', 'echo-rewards' ); ?>
								</a>
							<?php endif; ?>
						</p>
					</div>
					<?php if ( $this->is_pro ) { ?>
					<div id="ecre_schedule_confirmation_popup" class="ecre-schedule-popup-overlay">
						<div class="ecre-popup-box">
							<button id="ecre-popup-close" class="ecre-popup-close">✖</button>
							<h3 id="ecre-popup-title"><?php esc_html_e( 'Confirm Action', 'echo-rewards' ); ?></h3>
							<p id="ecre-popup-message"><?php esc_html_e( 'Are you sure you want to proceed?', 'echo-rewards' ); ?></p>
							<div class="ecre-popup-buttons">
								<button id="ecre-popup-cancel" class="ecre-popup-btn ecre-cancel"><?php esc_html_e( 'Cancel', 'echo-rewards' ); ?></button>
								<button id="ecre-popup-confirm" class="ecre-popup-btn ecre-confirm"><?php esc_html_e( 'Confirm', 'echo-rewards' ); ?></button>
							</div>
						</div>
					</div>
					<?php } ?>
					<?php
				}
			}
		}
	}
}
