<?php
/**
 * Background processing via WP Cron.
 *
 * @package MasterQuiz
 * @since   1.0.0
 */

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

/**
 * Class MasterQuiz_Background_Process
 *
 * Manages background quiz generation using WP Cron single events.
 *
 * @since 1.0.0
 */
class MasterQuiz_Background_Process {

	/**
	 * Schedule a quiz generation job.
	 *
	 * @since 1.0.0
	 *
	 * @param string $job_id The unique job identifier.
	 */
	public function schedule_generation( $job_id ) {
		// Job is processed inline on the first status poll — no cron spawn needed.
		MasterQuiz_Logger::info( 'Job queued for inline processing', array( 'job_id' => $job_id ) );
	}

	/**
	 * Process a quiz generation job.
	 *
	 * This is the WP Cron callback that runs the actual generation.
	 *
	 * @since 1.0.0
	 *
	 * @param string $job_id The unique job identifier.
	 */
	public function process_job( $job_id ) {
		$job_data = get_transient( 'masterquiz_job_' . $job_id );

		if ( empty( $job_data ) ) {
			MasterQuiz_Logger::error( 'Job not found', array( 'job_id' => $job_id ) );
			return;
		}

		// Prevent double-processing.
		if ( 'processing' === $job_data['status'] || 'completed' === $job_data['status'] ) {
			return;
		}

		// Ensure enough execution time for AI API calls.
		if ( function_exists( 'set_time_limit' ) ) {
			set_time_limit( 120 ); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- required for long-running AI API calls.
		}

		try {
			$input     = $job_data['input'];
			$file_path = $input['file_path'];
			$user_id   = $job_data['user_id'];
			$pdf_text  = '';

			// Step 1: Use text pre-extracted on upload, or parse PDF now.
			$upload_ref = get_transient( 'masterquiz_upload_' . $user_id );
			if ( ! empty( $upload_ref['pdf_text'] ) ) {
				$pdf_text = $upload_ref['pdf_text'];
				$this->update_job( $job_id, $job_data, 'processing', 20, __( 'Generating quiz with AI...', 'masterquiz-ai' ) );
			} else {
				$this->update_job( $job_id, $job_data, 'processing', 10, __( 'Extracting text from PDF...', 'masterquiz-ai' ) );
				$extractor = new MasterQuiz_Pdf_Extractor();
				$pdf_text  = $extractor->extract_text( $file_path );
				if ( is_wp_error( $pdf_text ) ) {
					throw new Exception( $pdf_text->get_error_message() );
				}
				$this->update_job( $job_id, $job_data, 'processing', 30, __( 'Generating quiz with AI...', 'masterquiz-ai' ) );
			}

			// Step 2: Generate quiz.
			$generator = new MasterQuiz_Quiz_Generator();
			$quiz_data = $generator->generate_quiz( $pdf_text, array(
				'num_questions'  => $input['num_questions'],
				'question_types' => $input['question_types'],
				'quiz_mode'      => $input['quiz_mode'],
				'quiz_title'     => $input['quiz_title'],
			) );

			if ( is_wp_error( $quiz_data ) ) {
				throw new Exception( $quiz_data->get_error_message() );
			}

			$this->update_job( $job_id, $job_data, 'processing', 80, __( 'Quiz generated. Finalizing...', 'masterquiz-ai' ) );

			// Store quiz data.
			set_transient( 'masterquiz_quiz_' . $job_id, $quiz_data, DAY_IN_SECONDS );

			// Step 3: Auto-create LearnDash quiz if enabled.
			$ld_result = null;

			if (
				! empty( $input['auto_learndash'] ) &&
				MasterQuiz_Learndash::is_active() &&
				get_option( 'masterquiz_auto_create_quiz', 1 )
			) {
				$this->update_job( $job_id, $job_data, 'processing', 90, __( 'Creating LearnDash quiz...', 'masterquiz-ai' ) );

				$learndash = new MasterQuiz_Learndash();
				$ld_result = $learndash->create_quiz( $quiz_data, array(
					'course_id'   => $input['course_id'] ?? 0,
					'passing_pct' => absint( get_option( 'masterquiz_quiz_passing_percentage', 80 ) ),
				) );

				if ( is_wp_error( $ld_result ) ) {
					MasterQuiz_Logger::warning( 'LearnDash quiz creation failed', array(
						'job_id' => $job_id,
						'error'  => $ld_result->get_error_message(),
					) );
					$ld_result = null;
				}
			}

			// Step 4: Cleanup uploaded PDF.
			if ( file_exists( $file_path ) ) {
				wp_delete_file( $file_path );
			}

			// Delete upload transient.
			$user_id = $job_data['user_id'];
			delete_transient( 'masterquiz_upload_' . $user_id );

			// Mark job as completed.
			$job_data['status']     = 'completed';
			$job_data['progress']   = 100;
			$job_data['message']    = __( 'Quiz generated successfully!', 'masterquiz-ai' );
			$job_data['updated_at'] = time();
			$job_data['result']     = array(
				'question_count' => count( $quiz_data['questions'] ?? array() ),
				'model'          => $quiz_data['model'] ?? 'unknown',
				'ld_quiz'        => $ld_result,
			);

			set_transient( 'masterquiz_job_' . $job_id, $job_data, HOUR_IN_SECONDS );

			MasterQuiz_Logger::info( 'Job completed', array(
				'job_id'    => $job_id,
				'questions' => count( $quiz_data['questions'] ?? array() ),
			) );

		} catch ( Exception $e ) {
			$job_data['status']     = 'failed';
			$job_data['progress']   = 0;
			$job_data['message']    = __( 'Quiz generation failed.', 'masterquiz-ai' );
			$job_data['error']      = $e->getMessage();
			$job_data['updated_at'] = time();

			set_transient( 'masterquiz_job_' . $job_id, $job_data, HOUR_IN_SECONDS );

			MasterQuiz_Logger::error( 'Job failed', array(
				'job_id' => $job_id,
				'error'  => $e->getMessage(),
			) );
		}
	}

	/**
	 * Update job status in transient.
	 *
	 * @since 1.0.0
	 *
	 * @param string $job_id   Job identifier.
	 * @param array  $job_data Current job data (passed by reference).
	 * @param string $status   New status.
	 * @param int    $progress Progress percentage.
	 * @param string $message  Status message.
	 */
	private function update_job( $job_id, &$job_data, $status, $progress, $message ) {
		$job_data['status']     = $status;
		$job_data['progress']   = $progress;
		$job_data['message']    = $message;
		$job_data['updated_at'] = time();

		set_transient( 'masterquiz_job_' . $job_id, $job_data, HOUR_IN_SECONDS );
	}
}
