<?php

namespace Fotogenic_AI;

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

/**
 * Unique Action Scheduler / WP-Cron bridge for parent Store Queues.
 */
final class Store_Queue_Scheduler {
	public const HOOK_TICK = 'fotogenic_ai_store_queue_tick';
	public const GROUP = 'fotogenic_ai_store_queue';
	private static ?Store_Queue_Scheduler $instance = null;

	private function __construct() {}

	public static function instance(): Store_Queue_Scheduler {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	public function schedule_tick( string $queue_uuid, int $user_id, int $delay_seconds = 2 ): bool {
		$queue_uuid = strtolower( trim( $queue_uuid ) );
		if ( ! wp_is_uuid( $queue_uuid ) || $user_id <= 0 || ! Background_Runtime_State::is_enabled() ) {
			return false;
		}
		$delay = max( 1, min( 300, $delay_seconds ) );
		$args  = [ 'queue_uuid' => $queue_uuid, 'user_id' => $user_id ];
		if ( $this->has_action_scheduler() ) {
			try {
				$supports_pending_query = function_exists( 'as_get_scheduled_actions' );
				if ( $supports_pending_query && $this->has_pending_action( $args ) ) {
					return true;
				}
				$action_id = as_schedule_single_action( time() + $delay, self::HOOK_TICK, $args, self::GROUP, ! $supports_pending_query );
				if ( is_numeric( $action_id ) && $action_id > 0 ) {
					return true;
				}
				if ( $supports_pending_query && $this->has_pending_action( $args ) ) {
					return true;
				}
			} catch ( \Throwable $error ) {
				unset( $error );
				Logger::instance()->warn( 'store_queue_scheduler_schedule_failed' );
			}
		}
		$cron_args = [ $queue_uuid, $user_id ];
		if ( wp_next_scheduled( self::HOOK_TICK, $cron_args ) ) {
			return true;
		}
		$scheduled = wp_schedule_single_event( time() + $delay, self::HOOK_TICK, $cron_args, true );
		return ! is_wp_error( $scheduled ) && false !== $scheduled && Background_Runtime_State::is_enabled();
	}

	public function has_scheduled_tick( string $queue_uuid, int $user_id ): bool {
		$queue_uuid = strtolower( trim( $queue_uuid ) );
		if ( ! wp_is_uuid( $queue_uuid ) || $user_id <= 0 || ! Background_Runtime_State::is_enabled() ) {
			return false;
		}
		$args = [ 'queue_uuid' => $queue_uuid, 'user_id' => $user_id ];
		if ( $this->has_action_scheduler() ) {
			try {
				if ( function_exists( 'as_get_scheduled_actions' ) ) {
					return $this->has_pending_action( $args );
				}
				if ( function_exists( 'as_has_scheduled_action' ) && as_has_scheduled_action( self::HOOK_TICK, $args, self::GROUP ) ) {
					return true;
				}
			} catch ( \Throwable $error ) {
				unset( $error );
				Logger::instance()->warn( 'store_queue_scheduler_lookup_failed' );
			}
		}
		return (bool) wp_next_scheduled( self::HOOK_TICK, [ $queue_uuid, $user_id ] );
	}

	public function unschedule_tick( string $queue_uuid, int $user_id ): void {
		$queue_uuid = strtolower( trim( $queue_uuid ) );
		$args       = [ 'queue_uuid' => $queue_uuid, 'user_id' => $user_id ];
		if ( $this->has_action_scheduler() && function_exists( 'as_unschedule_action' ) ) {
			try {
				as_unschedule_action( self::HOOK_TICK, $args, self::GROUP );
			} catch ( \Throwable $error ) {
				unset( $error );
			}
		}
		wp_clear_scheduled_hook( self::HOOK_TICK, [ $queue_uuid, $user_id ] );
		wp_clear_scheduled_hook( self::HOOK_TICK, [ $args ] );
	}

	public function deactivation_cleanup(): void {
		wp_unschedule_hook( self::HOOK_TICK );
		if ( $this->has_action_scheduler() && function_exists( 'as_unschedule_all_actions' ) ) {
			as_unschedule_all_actions( self::HOOK_TICK );
		}
	}

	private function has_action_scheduler(): bool {
		if ( ! function_exists( 'as_schedule_single_action' ) ) {
			return false;
		}
		if ( class_exists( '\\ActionScheduler' ) && method_exists( '\\ActionScheduler', 'is_initialized' ) ) {
			return (bool) \ActionScheduler::is_initialized();
		}
		return did_action( 'action_scheduler_init' ) > 0;
	}

	private function has_pending_action( array $args ): bool {
		if ( ! function_exists( 'as_get_scheduled_actions' ) ) {
			return false;
		}
		$ids = as_get_scheduled_actions(
			[ 'hook' => self::HOOK_TICK, 'args' => $args, 'group' => self::GROUP, 'status' => 'pending', 'per_page' => 1 ],
			'ids'
		);
		return ! empty( $ids );
	}
}
