<?php
/**
 * Bulk generation manager using Action Scheduler.
 *
 * @package CatalogPilot\AiStudio
 */

namespace CatalogPilot\AiStudio;

defined( 'ABSPATH' ) || exit;

final class Bulk {

	const JOB_OPTION = 'cpais_bulk_job';
	const HOOK       = 'cpais_process_bulk_item';
	const GROUP      = 'cpais';

	private static $instance = null;

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

	private function __construct() {
		add_action( self::HOOK, array( __CLASS__, 'process_item' ), 10, 2 );
	}

	public static function start( array $product_ids, array $job_settings ) {
		$product_ids = array_values( array_unique( array_filter( array_map( 'absint', $product_ids ) ) ) );
		if ( empty( $product_ids ) ) {
			return new \WP_Error( 'cpais_bulk_empty', __( 'No products selected.', 'catalogpilot-ai-studio-for-woocommerce' ) );
		}

		$existing = get_option( self::JOB_OPTION );
		if ( is_array( $existing ) && 'running' === ( $existing['status'] ?? '' ) ) {
			return new \WP_Error( 'cpais_bulk_in_progress', __( 'A bulk job is already running. Cancel it first.', 'catalogpilot-ai-studio-for-woocommerce' ) );
		}

		$defaults = array(
			'tone'        => 'professional',
			'length'      => 'medium',
			'language'    => 'en',
			'parts'       => array( 'short_description', 'long_description' ),
			'do_text'     => true,
			'do_seo'      => false,
			'do_image'    => false,
			'apply_text'  => false,
			'apply_seo'   => false,
			'image_provider' => 'openai',
			'image_model'    => '',
			'size'           => '1024x1024',
			'style'          => 'studio',
			'attach_as'      => 'featured',
			'delay'          => 2,
		);
		$job_settings = wp_parse_args( $job_settings, $defaults );

		$job = array(
			'id'           => wp_generate_uuid4(),
			'status'       => 'running',
			'total'        => count( $product_ids ),
			'done'         => 0,
			'failed'       => 0,
			'settings'     => $job_settings,
			'errors'       => array(),
			'product_ids'  => $product_ids,
			'created_at'   => time(),
		);
		update_option( self::JOB_OPTION, $job, false );

		$delay = max( 0, (int) $job_settings['delay'] );
		$i     = 0;
		foreach ( $product_ids as $pid ) {
			$when = time() + ( $i * $delay );
			if ( function_exists( 'as_schedule_single_action' ) ) {
				as_schedule_single_action( $when, self::HOOK, array( $job['id'], $pid ), self::GROUP );
			} else {
				wp_schedule_single_event( $when, self::HOOK, array( $job['id'], $pid ) );
			}
			$i++;
		}

		return $job;
	}

	public static function status() {
		$job = get_option( self::JOB_OPTION );
		return is_array( $job ) ? $job : null;
	}

	public static function cancel() {
		$job = get_option( self::JOB_OPTION );
		if ( ! is_array( $job ) ) {
			return false;
		}
		$job['status']      = 'canceled';
		$job['completed_at'] = time();
		update_option( self::JOB_OPTION, $job, false );

		if ( function_exists( 'as_unschedule_all_actions' ) ) {
			as_unschedule_all_actions( self::HOOK, null, self::GROUP );
		}
		return true;
	}

	public static function clear() {
		delete_option( self::JOB_OPTION );
		return true;
	}

	public static function retry_failed() {
		$job = get_option( self::JOB_OPTION );
		if ( ! is_array( $job ) ) {
			return new \WP_Error( 'cpais_bulk_no_job', __( 'No job to retry.', 'catalogpilot-ai-studio-for-woocommerce' ) );
		}
		if ( 'running' === $job['status'] ) {
			return new \WP_Error( 'cpais_bulk_in_progress', __( 'Job is still running.', 'catalogpilot-ai-studio-for-woocommerce' ) );
		}
		$failed_ids = array_map( 'absint', array_keys( $job['errors'] ?? array() ) );
		$failed_ids = array_values( array_filter( $failed_ids ) );
		if ( empty( $failed_ids ) ) {
			return new \WP_Error( 'cpais_bulk_nothing_to_retry', __( 'No failed items.', 'catalogpilot-ai-studio-for-woocommerce' ) );
		}

		// Reset counters for the retry batch.
		$job['id']          = wp_generate_uuid4();
		$job['status']      = 'running';
		$job['total']       = count( $failed_ids );
		$job['done']        = 0;
		$job['failed']      = 0;
		$job['errors']      = array();
		$job['product_ids'] = $failed_ids;
		$job['created_at']  = time();
		unset( $job['completed_at'] );
		update_option( self::JOB_OPTION, $job, false );

		$delay = max( 0, (int) ( $job['settings']['delay'] ?? 2 ) );
		$i     = 0;
		foreach ( $failed_ids as $pid ) {
			$when = time() + ( $i * $delay );
			if ( function_exists( 'as_schedule_single_action' ) ) {
				as_schedule_single_action( $when, self::HOOK, array( $job['id'], $pid ), self::GROUP );
			} else {
				wp_schedule_single_event( $when, self::HOOK, array( $job['id'], $pid ) );
			}
			$i++;
		}

		return $job;
	}

	public static function process_item( $job_id, $product_id ) {
		$job = get_option( self::JOB_OPTION );
		if ( ! is_array( $job ) || $job['id'] !== $job_id ) {
			return;
		}
		if ( 'running' !== $job['status'] ) {
			return;
		}

		$product = wc_get_product( $product_id );
		if ( ! $product ) {
			$job['failed']++;
			$job['errors'][ $product_id ] = __( 'Product not found.', 'catalogpilot-ai-studio-for-woocommerce' );
			self::advance( $job );
			return;
		}

		$settings     = Settings::get_all();
		$job_settings = $job['settings'];
		$merged       = array_merge( $settings, $job_settings );

		$succeeded = true;

		if ( ! empty( $job_settings['do_text'] ) ) {
			$res = Generator::run_text( $product, $merged );
			if ( is_wp_error( $res ) ) {
				$succeeded = false;
				$job['errors'][ $product_id ] = 'text: ' . $res->get_error_message();
			} elseif ( ! empty( $job_settings['apply_text'] ) ) {
				Generator::apply_text_to_product( $product, $res['content'] );
			}
		}

		if ( $succeeded && ! empty( $job_settings['do_seo'] ) ) {
			$res = Generator::run_seo( $product, $merged );
			if ( is_wp_error( $res ) ) {
				$succeeded = false;
				$prev = $job['errors'][ $product_id ] ?? '';
				$job['errors'][ $product_id ] = trim( $prev . ' seo: ' . $res->get_error_message() );
			} elseif ( ! empty( $job_settings['apply_seo'] ) ) {
				SEO::apply( $product_id, $res['content'] );
			}
		}

		if ( $succeeded && ! empty( $job_settings['do_image'] ) ) {
			$res = Generator::run_image( $product, $merged );
			if ( is_wp_error( $res ) ) {
				$succeeded = false;
				$prev = $job['errors'][ $product_id ] ?? '';
				$job['errors'][ $product_id ] = trim( $prev . ' image: ' . $res->get_error_message() );
			}
		}

		if ( $succeeded ) {
			$job['done']++;
		} else {
			$job['failed']++;
		}

		self::advance( $job );
	}

	private static function advance( array $job ) {
		if ( $job['done'] + $job['failed'] >= $job['total'] ) {
			$job['status']       = 'completed';
			$job['completed_at'] = time();
		}
		update_option( self::JOB_OPTION, $job, false );
	}
}
