<?php

namespace VendorTasksDokanClickUp\Queue;

use VendorTasksDokanClickUp\Settings\PluginSettings;
use VendorTasksDokanClickUp\VendorIntegration\Registration;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Retry Scheduler
 *
 * Registers a WP-Cron job that processes the pending task queue every 15 minutes,
 * retrying ClickUp task creation for vendors that failed on registration.
 *
 * @since 1.1.0
 * @package VendorTasksDokanClickUp
 * @subpackage Queue
 */
class RetryScheduler {

	/**
	 * WP-Cron hook name
	 *
	 * @var string
	 */
	public const CRON_HOOK = 'vendor_tasks_dokan_clickup_retry_queue';

	/**
	 * Custom cron schedule interval name
	 *
	 * @var string
	 */
	private const CRON_INTERVAL = 'vendor_tasks_dokan_clickup_15min';

	/**
	 * Class constructor
	 *
	 * @since 1.1.0
	 */
	public function __construct() {
		add_filter( 'cron_schedules', array( $this, 'add_cron_interval' ) );
		add_action( self::CRON_HOOK, array( $this, 'process_queue' ) );
	}

	/**
	 * Register a 15-minute cron recurrence
	 *
	 * @since 1.1.0
	 *
	 * @param array $schedules Existing schedules.
	 * @return array
	 */
	public function add_cron_interval( array $schedules ): array {
		$schedules[ self::CRON_INTERVAL ] = array(
			'interval' => 15 * MINUTE_IN_SECONDS,
			'display'  => __( 'Every 15 minutes', 'alamin-vendor-tasks-dokan-clickup' ),
		);
		return $schedules;
	}

	/**
	 * Schedule the cron event (call on plugin activation)
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	public function schedule_cron(): void {
		if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
			wp_schedule_event( time(), self::CRON_INTERVAL, self::CRON_HOOK );
		}
	}

	/**
	 * Unschedule the cron event (call on plugin deactivation)
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	public function unschedule_cron(): void {
		$timestamp = wp_next_scheduled( self::CRON_HOOK );
		if ( $timestamp ) {
			wp_unschedule_event( $timestamp, self::CRON_HOOK );
		}
	}

	/**
	 * Process the pending queue — retries failed task creation
	 *
	 * Called by WP-Cron every 15 minutes.
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	public function process_queue(): void {
		$ps = new PluginSettings();

		if ( ! $ps->is_retry_failed_tasks() ) {
			return;
		}

		$max_attempts = $ps->get_max_retry_attempts();
		$queue        = new PendingQueue();
		// Process at most $max_attempts * 2 items per run
		$pending = $queue->next_batch( $max_attempts * 2 );

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

		vendor_tasks_dokan_clickup()->log(
			sprintf( 'Processing retry queue: %d pending vendor(s).', count( $pending ) ),
			'info'
		);

		$registration = new Registration();

		foreach ( $pending as $item ) {
			$vendor_id = (int) $item['vendor_id'];
			$attempts  = (int) $item['attempts'];

			if ( $attempts >= $max_attempts ) {
				vendor_tasks_dokan_clickup()->log(
					sprintf(
						'Vendor ID %d reached max retry attempts (%d). Removing from queue.',
						$vendor_id,
						$max_attempts
					),
					'error'
				);
				$queue->dequeue( $vendor_id );

				/**
				 * Fires when ClickUp task creation has permanently failed for a vendor.
				 *
				 * @since 1.1.0
				 *
				 * @param int $vendor_id Vendor user ID.
				 * @param int $attempts  Number of attempts made.
				 */
				do_action( 'vendor_tasks_dokan_clickup_task_failed', $vendor_id, $attempts );

				continue;
			}

			$result = $registration->create_clickup_task_for_vendor( $vendor_id );

			if ( true === $result ) {
				$queue->dequeue( $vendor_id );
				vendor_tasks_dokan_clickup()->log(
					sprintf( 'Retry succeeded for vendor ID %d.', $vendor_id ),
					'info'
				);
			} else {
				$queue->increment_attempts( $vendor_id );
				vendor_tasks_dokan_clickup()->log(
					sprintf(
						'Retry attempt %d/%d failed for vendor ID %d.',
						$attempts + 1,
						$max_attempts,
						$vendor_id
					),
					'warning'
				);
			}
		}
	}
}
