<?php
/**
 * WP Async Request With Cron
 */

declare( strict_types=1 );

namespace FiboFilters\Indexer\BackgroundProcessing;

use FiboFilters\Indexer\Logger;

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

/**
 * Abstract AsyncRequestWithCron class.
 */
abstract class AsyncRequestWithCron extends AsyncRequest {

	/**
	 * Action
	 *
	 * (default value: 'async_request')
	 *
	 * @var string
	 * @access protected
	 */
	protected $action = 'async_request_with_cron';

	/**
	 * Cron_hook_identifier
	 *
	 * @var mixed
	 * @access protected
	 */
	protected $cron_hook_identifier;

	/** @var Logger */
	protected $logger;

	/**
	 * Initiate new async request
	 *
	 * @param Logger $logger Logger.
	 */
	public function __construct( Logger $logger ) {
		$this->logger = $logger;

		parent::__construct( $this->logger );

		$this->cron_hook_identifier = $this->identifier . '_cron';
	}

	public function init_cron(): void {
		add_action( $this->cron_hook_identifier, [ $this, 'handle_cron_healthcheck' ] );
	}

	/**
	 * Maybe handle
	 *
	 * Check for correct nonce and pass to handler.
	 */
	public function maybe_handle(): void {
		// Don't lock up other requests while processing.
		session_write_close();

		check_ajax_referer( $this->identifier, 'nonce' );

		$raw_post_data = @file_get_contents( 'php://input' );
		if ( $raw_post_data !== false ) {
			parse_str( $raw_post_data, $params );
			$this->data = $params;
		}

		// Clear running task via cron as fallback.
		$this->clear_scheduled_event();

		$this->handle();

		wp_die();
	}

	/**
	 * Handle cron healthcheck
	 */
	public function handle_cron_healthcheck(): void {
		$this->logger->log( $this->name . ' Handle async request via cron healthcheck', 'debug', 'file', 'bg-process' );

		$this->handle();

		exit;
	}

	/**
	 * Schedule event
	 *
	 * @return AsyncRequestWithCron
	 */
	public function schedule_event(): AsyncRequestWithCron {
		if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
			wp_schedule_single_event( time() + 60, $this->cron_hook_identifier );
		}

		return $this;
	}

	/**
	 * Clear scheduled event
	 */
	protected function clear_scheduled_event(): void {
		$timestamp = wp_next_scheduled( $this->cron_hook_identifier );

		if ( $timestamp ) {
			wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
		}
	}
}
