<?php
/**
 * Class Auto_Sync_Cron
 */

namespace BwWinnersGlobalSite\Sync;

if ( ! class_exists( __NAMESPACE__ . '\Auto_Sync_Cron' ) ) {

	class Auto_Sync_Cron {

		const SYNC_HOOK = 'bw_winners_auto_sync_cron';
		const TASK_HOOK = 'bw_winners_auto_task_cron';

		const CRON_LOCK  = 'bw_winners_auto_sync_lock';
		const OPTION_KEY = 'bw_winners_auto_sync_task';

		const SYNC_RECURRENCE = 'daily';
		const TASK_RECURRENCE = 'bw_winners_fast';

		private $sync_tasks;

		public function __construct( $sync_tasks ) {

			$this->sync_tasks = $sync_tasks;

			add_filter( 'cron_schedules', [ $this, 'add_cron_schedule_recurrence' ] );

			add_action( 'init', [ $this, 'schedule_crons' ] );

			add_action( self::SYNC_HOOK, [ $this, 'schedule_sync' ] );
			add_action( self::TASK_HOOK, [ $this, 'run_task' ] );
		}

		public function add_cron_schedule_recurrence ( $schedules ) {
			$schedules[ self::TASK_RECURRENCE ] = [
				'interval' => 60, // 1 minute (as often as WP allows)
				'display'  => 'BW Winners Fast (1 minute)',
			];
			return $schedules;
		}

		public function get_task () {
			return get_option( self::OPTION_KEY );
		}

		/**
		 * Schedule cron if not already scheduled
		 */
		public function schedule_crons() {

			if ( ! wp_next_scheduled( self::SYNC_HOOK ) ) {
				wp_schedule_event( time(), self::SYNC_RECURRENCE, self::SYNC_HOOK );
			}
			
			if ( ! wp_next_scheduled( self::TASK_HOOK ) ) {
				wp_schedule_event( time(), self::TASK_RECURRENCE, self::TASK_HOOK );
			}

		}

		/**
		 * Main cron entry point
		 */
		public function schedule_sync () {

			$enable_auto_sync = \BwWinnersGlobalSite\Options::get_option( 'enable_auto_sync' );

			if ( ! $enable_auto_sync ) {
				return;
			}
			
			$task = $this->get_task();

			if (
				$task &&
				isset( $task['status'] ) &&
				! in_array( $task['status'], [ 'complete', 'failed' ], true )
			) {
				return;
			}			
			$task = [
				'status'     => 'pending',
				'errors'      => [],
			];

			update_option( self::OPTION_KEY, $task, false );
		}

		public function run_task () {

			if ( get_transient( self::CRON_LOCK ) ) {
				return;
			}

			set_transient( self::CRON_LOCK, 1, 5 * MINUTE_IN_SECONDS );

			try {
				$task = $this->get_task();

				if ( ! $task ) {
					return;
				}

				switch ( $task['status'] ) {
					case 'pending':
						$task = $this->sync_tasks->init_task();
						update_option( self::OPTION_KEY, $task, false );
						break;

					case 'running':
						$task = $this->sync_tasks->sync_task( $task );
						update_option( self::OPTION_KEY, $task, false );
						break;

					case 'cleanup':
						$task = $this->sync_tasks->clean_task( $task );
						update_option( self::OPTION_KEY, $task, false );
						break;	

					default:
						return;
				}

			} catch ( \Throwable $e ) {
				$this->sync_tasks->fail_task( $task, $e->getMessage() );
			} finally {
				delete_transient(self::CRON_LOCK);
			}
		}
	}
}
