<?php
/**
 * Countdown Handler Class
 *
 * @package PromoSDK
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}


if ( ! class_exists( 'Countdown_Handler' ) ) {
	/**
	 * Countdown Handler Class
	 *
	 * Handles countdown time calculations for recurring and non-recurring promos.
	 *
	 * @since 1.0.0
	 */
	class Countdown_Handler {
		/**
		 * Get countdown end time
		 *
		 * @param array $promo_data Promotional data.
		 * @return string|null ISO 8601 datetime string or null.
		 */
		public function get_countdown_end_time( $promo_data ) {
			if ( ! is_array( $promo_data ) ) {
				return null;
			}

			// Check if promo is recurring.
			$is_recurring = isset( $promo_data['is_recurring'] ) && $promo_data['is_recurring'];

			if ( $is_recurring ) {
				return $this->get_recurring_end_time( $promo_data );
			}

			return $this->get_non_recurring_end_time( $promo_data );
		}

		/**
		 * Get end time for recurring promo
		 *
		 * Calculates the current cycle end time based on campaign start date and recurring interval.
		 *
		 * @param array $promo_data Promotional data.
		 * @return string|null ISO 8601 datetime string or null.
		 */
		private function get_recurring_end_time( $promo_data ) {
			// Validate required fields.
			if ( ! isset( $promo_data['start_date'] ) || ! isset( $promo_data['end_date'] ) ) {
				return null;
			}

			if ( ! isset( $promo_data['recurring_type'] ) || ! isset( $promo_data['recurring_interval'] ) ) {
				return null;
			}

			try {
				$now        = new DateTime( 'now', wp_timezone() );
				$start_date = new DateTime( $promo_data['start_date'], wp_timezone() );
				$end_date   = new DateTime( $promo_data['end_date'], wp_timezone() );

				// Check if campaign is active.
				if ( $now < $start_date || $now > $end_date ) {
					return null;
				}

				// Calculate cycle duration in seconds.
				$recurring_type     = $promo_data['recurring_type'];
				$recurring_interval = absint( $promo_data['recurring_interval'] );

				if ( 'hours' === $recurring_type ) {
					$cycle_duration_seconds = $recurring_interval * 3600; // hours to seconds.
				} elseif ( 'days' === $recurring_type ) {
					$cycle_duration_seconds = $recurring_interval * 86400; // days to seconds.
				} else {
					return null;
				}

				// Calculate time elapsed since campaign start.
				$time_since_start = $now->getTimestamp() - $start_date->getTimestamp();

				// Calculate which cycle we're in.
				$cycle_number = floor( $time_since_start / $cycle_duration_seconds );

				// Calculate current cycle start and end times.
				$cycle_start_timestamp = $start_date->getTimestamp() + ( $cycle_number * $cycle_duration_seconds );
				$cycle_end_timestamp   = $cycle_start_timestamp + $cycle_duration_seconds;

				// Create DateTime objects for cycle times.
				$cycle_end = new DateTime( '@' . $cycle_end_timestamp );
				$cycle_end->setTimezone( wp_timezone() );

				// Make sure cycle end doesn't exceed campaign end date.
				if ( $cycle_end > $end_date ) {
					$cycle_end = $end_date;
				}

				// Check if we're still within the current cycle.
				if ( $now->getTimestamp() <= $cycle_end->getTimestamp() ) {
					return $cycle_end->format( 'c' ); // ISO 8601 format.
				}

				// Not in active cycle.
				return null;
			} catch ( Exception $e ) {
				return null;
			}
		}

		/**
		 * Get end time for non-recurring promo
		 *
		 * @param array $promo_data Promotional data.
		 * @return string|null ISO 8601 datetime string or null.
		 */
		private function get_non_recurring_end_time( $promo_data ) {
			if ( ! isset( $promo_data['end_date'] ) ) {
				return null;
			}

			try {
				$now      = new DateTime( 'now', wp_timezone() );
				$end_date = new DateTime( $promo_data['end_date'], wp_timezone() );

				// Check if promo is still active.
				if ( $now <= $end_date ) {
					return $end_date->format( 'c' ); // ISO 8601 format.
				}

				// Promo expired.
				return null;
			} catch ( Exception $e ) {
				return null;
			}
		}

		/**
		 * Check if promo is in active cycle
		 *
		 * @param array $promo_data Promotional data.
		 * @return bool True if active, false otherwise.
		 */
		public function is_in_active_cycle( $promo_data ) {
			if ( ! is_array( $promo_data ) ) {
				return false;
			}

			// Check if promo is recurring.
			$is_recurring = isset( $promo_data['is_recurring'] ) && $promo_data['is_recurring'];

			if ( $is_recurring ) {
				return $this->is_in_recurring_cycle( $promo_data );
			}

			return $this->is_in_non_recurring_period( $promo_data );
		}

		/**
		 * Check if in recurring cycle
		 *
		 * Calculates if current time is within an active recurring cycle.
		 *
		 * @param array $promo_data Promotional data.
		 * @return bool True if in active cycle, false otherwise.
		 */
		private function is_in_recurring_cycle( $promo_data ) {
			// Simply check if we can get a valid end time.
			$end_time = $this->get_recurring_end_time( $promo_data );
			return null !== $end_time;
		}

		/**
		 * Check if in non-recurring period
		 *
		 * @param array $promo_data Promotional data.
		 * @return bool True if active, false otherwise.
		 */
		private function is_in_non_recurring_period( $promo_data ) {
			if ( ! isset( $promo_data['start_date'] ) || ! isset( $promo_data['end_date'] ) ) {
				return false;
			}

			try {
				$now        = new DateTime( 'now', wp_timezone() );
				$start_date = new DateTime( $promo_data['start_date'], wp_timezone() );
				$end_date   = new DateTime( $promo_data['end_date'], wp_timezone() );

				return $now >= $start_date && $now <= $end_date;
			} catch ( Exception $e ) {
				return false;
			}
		}

		/**
		 * Calculate remaining seconds
		 *
		 * @param string $end_time End datetime string.
		 * @return int Remaining seconds.
		 */
		public function calculate_remaining_seconds( $end_time ) {
			if ( empty( $end_time ) ) {
				return 0;
			}

			try {
				$now      = new DateTime( 'now', wp_timezone() );
				$end_date = new DateTime( $end_time, wp_timezone() );

				$interval = $now->diff( $end_date );

				// Calculate total seconds.
				$remaining_seconds = ( $interval->days * 24 * 60 * 60 )
					+ ( $interval->h * 60 * 60 )
					+ ( $interval->i * 60 )
					+ $interval->s;

				// If time has passed, return 0.
				if ( $interval->invert ) {
					return 0;
				}

				return $remaining_seconds;
			} catch ( Exception $e ) {
				return 0;
			}
		}
	}
}
