<?php
/**
 * Cron Class for WPStack AI ALT Genius
 * Handles background processing and scheduling.
 *
 * @package WPStack_AI_ALT_Genius
 */

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Handles Cron Logic.
 */
class Aialtg_Cron {

	/**
	 * Option key.
	 *
	 * @var string
	 */
	private $option_name = 'aialtg_settings';

	/**
	 * Cron hook name.
	 *
	 * @var string
	 */
	public const CRON_HOOK = 'aialtg_cron_process_images';

	/**
	 * Custom interval name.
	 *
	 * @var string
	 */
	public const INTERVAL_NAME = 'aialtg_custom_interval';

	/**
	 * Constructor.
	 */
	public function __construct() {
		// Register Schedule.
		add_filter( 'cron_schedules', array( $this, 'add_custom_cron_schedule' ) );

		// Register Worker.
		add_action( self::CRON_HOOK, array( $this, 'process_cron_batch' ) );

		// Watchdog for Cron Health.
		add_action( 'admin_init', array( $this, 'check_cron_health' ) );
	}

	/**
	 * Adds a custom interval to WP Cron based on settings.
	 *
	 * @param array $schedules Existing schedules.
	 * @return array Modified schedules.
	 */
	public function add_custom_cron_schedule( $schedules ) {
		$options = get_option( $this->option_name );
		$minutes = isset( $options['cron_interval'] ) ? (int) $options['cron_interval'] : 5;
		if ( $minutes < 1 ) {
			$minutes = 1;
		}

		$schedules[ self::INTERVAL_NAME ] = array(
			'interval' => $minutes * 60,
			/* translators: %d: number of minutes */
			'display'  => sprintf( __( 'Every %d Minutes (WPStack AI ALT Genius)', AIALTG_TEXT_DOMAIN ), $minutes ),
		);
		return $schedules;
	}

	/**
	 * Cron Worker: Processes a batch of images.
	 */
	public function process_cron_batch() {
		$options = get_option( $this->option_name );
		// Double check if enabled.
		if ( empty( $options['cron_enabled'] ) ) {
			return;
		}

		$batch_size = isset( $options['cron_batch_size'] ) ? (int) $options['cron_batch_size'] : 1;
		if ( $batch_size < 1 ) {
			$batch_size = 1;
		}

		$provider    = isset( $options['provider'] ) ? $options['provider'] : 'openrouter';
		$nvidia_keys = Aialtg_Helpers::get_nvidia_keys( $options );
		$num_keys    = ( 'nvidia' === $provider && count( $nvidia_keys ) > 1 ) ? count( $nvidia_keys ) : 0;
		if ( $num_keys > 1 && $batch_size < $num_keys ) {
			$batch_size = $num_keys;
		}

		// Use the allowed types for the query if available.
		$allowed_mimes = 'image'; // default
		if ( class_exists( 'Aialtg_Settings' ) && method_exists( 'Aialtg_Settings', 'get_allowed_mimes' ) ) {
			$allowed_mimes = Aialtg_Settings::get_allowed_mimes();
		}

		// Query images that have NOT been processed by the plugin.
		$args = array(
			'post_type'      => 'attachment',
			'post_status'    => 'inherit',
			'post_mime_type' => $allowed_mimes,
			'posts_per_page' => $batch_size,
			'fields'         => 'ids',
			// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
			'meta_query'     => array(
				array(
					'key'     => '_aialtg_processed',
					'compare' => 'NOT EXISTS',
				),
			),
		);

		$images = get_posts( $args );

		if ( ! empty( $images ) ) {
			$generator = new Aialtg_Generator();

			if ( $num_keys > 1 ) {
				$key_groups = array_fill( 0, $num_keys, array() );
				foreach ( $images as $idx => $image_id ) {
					$key_groups[ $idx % $num_keys ][] = $image_id;
				}
				foreach ( $key_groups as $key_idx => $group_images ) {
					foreach ( $group_images as $image_id ) {
						$this->process_single_image( $generator, $image_id, $nvidia_keys[ $key_idx ] );
					}
				}
			} else {
				foreach ( $images as $image_id ) {
					$this->process_single_image( $generator, $image_id, '' );
					if ( count( $images ) > 1 ) {
						sleep( 1 );
					}
				}
			}

			delete_transient( 'aialtg_stats' );
		}
	}

	/**
	 * Process a single image and log the result.
	 */
	private function process_single_image( $generator, $image_id, $api_key = '' ) {
		$result = $generator->process_image( $image_id, 'cron', $api_key );

		if ( is_wp_error( $result ) ) {
			update_post_meta( $image_id, '_aialtg_processed', 'failed' );
			update_post_meta( $image_id, '_aialtg_error_log', substr( $result->get_error_message(), 0, 250 ) );
		} else {
			delete_post_meta( $image_id, '_aialtg_error_log' );
		}
	}

	/**
	 * Watchdog: Checks if cron is enabled but missing from schedule.
	 * Runs on admin pages to ensure reliability.
	 */
	public function check_cron_health() {
		// Only check if we are in the admin context to save frontend resources.
		if ( ! is_admin() ) {
			return;
		}

		$options = get_option( $this->option_name );
		if ( isset( $options['cron_enabled'] ) && '1' === $options['cron_enabled'] ) {
			if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
				// Reschedule immediately.
				wp_schedule_event( time() + 10, self::INTERVAL_NAME, self::CRON_HOOK );
			}
		}
	}
}