<?php
/**
 * Email Queue
 */

namespace RadiusTheme\RadiusBooking\Emails;

use ActionScheduler_Store;
if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}
/**
 * Class EmailQueue
 * A utility class for managing email queuing, scheduling, and processing using Action Scheduler.
 */
class EmailQueue {

	/**
	 * Adds an email to the queue for scheduled sending.
	 *
	 * This method schedules an email to be sent at a specified time using the Action Scheduler.
	 * If Action Scheduler is not available, the email is sent immediately as a fallback.
	 *
	 * @param string $email_id The ID of the email template or type.
	 * @param array $email_data An associative array containing the email data, such as the recipient and message details.
	 * @param int|null $timestamp The Unix timestamp at which the email should be sent. Defaults to the current time if not specified.
	 *
	 * @return string|bool Returns the action ID if the email was successfully scheduled, or `false` on failure.
	 */
	public static function add( $email_id, $email_data, $timestamp = null ) {
		if ( ! function_exists( 'as_schedule_single_action' ) ) {
			// Fallback: send immediately if Action Scheduler not available
			$email_manager = new EmailManager();
			$email         = $email_manager->get_email( $email_id );
			return $email ? $email->send( $email_data ) : false;
		}

		$timestamp = $timestamp ? $timestamp : time();

		// Schedule the email
		$action_id = as_schedule_single_action(
			$timestamp,
			'rtrb_send_queued_email',
			array(
				'email_id'   => $email_id,
				'email_data' => $email_data,
			),
			'booking-emails'
		);

		// EmailLogger::log('queued', 'Email added to queue', array(
		// 'email_id' => $email_id,
		// 'to' => $email_data['to'],
		// 'action_id' => $action_id,
		// 'scheduled_at' => date('Y-m-d H:i:s', $timestamp)
		// ));

		return $action_id;
	}

	/**
	 * Schedule a recurring email or a single email action.
	 *
	 * @param int $email_id The ID of the email to be scheduled.
	 * @param array $email_data The data associated with the email.
	 * @param int $timestamp The timestamp at which the action should first be triggered.
	 * @param int|null $interval_in_seconds Optional. The interval in seconds for recurring actions. If null, a single email is scheduled.
	 *
	 * @return bool|mixed Returns the result of the recurring action scheduling, the result of the single email scheduling, or false if the scheduling function is not available.
	 */
	public static function schedule_recurring( $email_id, $email_data, $timestamp, $interval_in_seconds = null ) {
		if ( ! function_exists( 'as_schedule_recurring_action' ) ) {
			return false;
		}

		if ( $interval_in_seconds ) {
			return as_schedule_recurring_action(
				$timestamp,
				$interval_in_seconds,
				'rtrb_send_queued_email',
				array(
					'email_id'   => $email_id,
					'email_data' => $email_data,
				),
				'booking-emails'
			);
		} else {
			return self::add( $email_id, $email_data, $timestamp );
		}
	}

	/**
	 * Schedules a reminder email for a booking.
	 *
	 * @param int $email_id The ID of the email to be sent.
	 * @param array $email_data An array containing email data, such as recipient and content.
	 * @param string $booking_datetime The datetime of the booking in 'Y-m-d H:i:s' format.
	 * @param int $hours_before The number of hours before the booking to send the reminder.
	 *
	 * @return string|bool Returns the action ID of the scheduled reminder on success, or false on failure.
	 */
	public static function schedule_reminder( $email_id, $email_data, $booking_datetime, $hours_before ) {
		if ( ! function_exists( 'as_schedule_single_action' ) ) {
			return false;
		}

		$reminder_timestamp = strtotime( $booking_datetime ) - ( $hours_before * 3600 );

		// Don't schedule if time has passed
		if ( $reminder_timestamp <= time() ) {
			return false;
		}

		$action_id = as_schedule_single_action(
			$reminder_timestamp,
			'rtrb_send_reminder_email',
			array(
				'email_id'   => $email_id,
				'email_data' => $email_data,
			),
			'booking-emails-reminders'
		);

		// EmailLogger::log('reminder_scheduled', 'Reminder email scheduled', array(
		// 'email_id' => $email_id,
		// 'to' => $email_data['to'],
		// 'action_id' => $action_id,
		// 'reminder_at' => date('Y-m-d H:i:s', $reminder_timestamp)
		// ));

		return $action_id;
	}

	/**
	 * Processes a queued email by retrieving the email instance and sending it.
	 *
	 * @param int $email_id The unique identifier of the email to process.
	 * @param array $email_data An associative array of data to be included in the email.
	 *
	 * @return bool|mixed Returns the result of the email sending process, or false on failure.
	 */
	public static function process_queued_email( $email_id, $email_data ) {
		$email_manager = new EmailManager();
		$email         = $email_manager->get_email( $email_id );

		// if (!$email) {
		// EmailLogger::log('error', 'Email class not found in queue processor', array(
		// 'email_id' => $email_id
		// ));
		// return false;
		// }

		return $email->send( $email_data );
	}

	/**
	 * Process a reminder email by delegating to the queued email processor.
	 *
	 * @param int|string $email_id The ID of the email to process.
	 * @param array $email_data The data associated with the email.
	 *
	 * @return bool|mixed The result of processing the email, or false on failure.
	 */
	public static function process_reminder_email( $email_id, $email_data ) {
		return self::process_queued_email( $email_id, $email_data );
	}

	/**
	 * Cancel a specific scheduled action by its ID.
	 *
	 * @param int $action_id The ID of the action to cancel.
	 *
	 * @return bool True if the action was successfully canceled, false otherwise.
	 */
	public static function cancel( $action_id ) {
		if ( ! function_exists( 'as_unschedule_action' ) ) {
			return false;
		}

		as_unschedule_action( 'rtrb_send_queued_email', array( 'action_id' => $action_id ), 'booking-emails' );

		return true;
	}

	/**
	 * Cancels all queued and reminder emails associated with a specific booking.
	 *
	 * The method unschedules all actions related to sending emails and reminders for a booking.
	 * It uses the `as_unschedule_all_actions` function to remove actions from the queue.
	 *
	 * @param int $booking_id The unique identifier of the booking whose emails are to be canceled.
	 *
	 * @return bool Returns true if the function executed successfully or false if the required function does not exist.
	 */
	public static function cancel_booking_emails( $booking_id ) {
		if ( ! function_exists( 'as_unschedule_all_actions' ) ) {
			return false;
		}

		// Cancel queued emails
		as_unschedule_all_actions( 'rtrb_send_queued_email', array( 'booking_id' => $booking_id ), 'booking-emails' );

		// Cancel reminders
		as_unschedule_all_actions( 'rtrb_send_reminder_email', array( 'booking_id' => $booking_id ), 'booking-emails-reminders' );

		return true;
	}

	/**
	 * Retrieves the count of pending scheduled email actions in the booking email group.
	 *
	 * This method checks for all actions scheduled with the hook 'rtrb_send_queued_email'
	 * and a status of 'pending' in the 'booking-emails' group. If the required
	 * function `as_get_scheduled_actions` is not available, it returns 0.
	 *
	 * @return int The number of pending scheduled actions. Returns 0 if the required function is unavailable.
	 */
	public static function get_pending_count() {
		if ( ! function_exists( 'as_get_scheduled_actions' ) ) {
			return 0;
		}

		$actions = as_get_scheduled_actions(
			array(
				'hook'   => 'rtrb_send_queued_email',
				'status' => ActionScheduler_Store::STATUS_PENDING,
				'group'  => 'booking-emails',
			),
			'ids'
		);

		return count( $actions );
	}

	/**
	 * Retrieves the count of failed scheduled email actions.
	 *
	 * This method fetches all failed actions associated with the specified hook and group.
	 * It checks if the `as_get_scheduled_actions` function is available before proceeding.
	 *
	 * @return int Returns the number of failed actions. Returns 0 if the required function does not exist.
	 */
	public static function get_failed_count() {
		if ( ! function_exists( 'as_get_scheduled_actions' ) ) {
			return 0;
		}

		$actions = as_get_scheduled_actions(
			array(
				'hook'   => 'rtrb_send_queued_email',
				'status' => ActionScheduler_Store::STATUS_FAILED,
				'group'  => 'booking-emails',
			),
			'ids'
		);

		return count( $actions );
	}

	/**
	 * Retries all failed email actions in the 'booking-emails' group.
	 *
	 * The method retrieves all failed scheduled actions associated with the
	 * 'rtrb_send_queued_email' hook and re-schedules them using the specified arguments.
	 * It uses the `as_get_scheduled_actions` function to fetch failed actions and retries them.
	 *
	 * @return int Returns the number of failed actions that were successfully retried. Returns 0 if the required function does not exist.
	 */
	public static function retry_failed() {
		if ( ! function_exists( 'as_get_scheduled_actions' ) ) {
			return 0;
		}

		$failed_actions = as_get_scheduled_actions(
			array(
				'hook'   => 'rtrb_send_queued_email',
				'status' => ActionScheduler_Store::STATUS_FAILED,
				'group'  => 'booking-emails',
			)
		);

		$retried = 0;
		foreach ( $failed_actions as $action ) {
			$args = $action->get_args();
			self::add( $args['email_id'], $args['email_data'] );
			++$retried;
		}

		return $retried;
	}
}
