<?php
/**
 * Image AJAX Handler
 * Handles secure AJAX communication for image generation functionality.
 *
 * @package AgenticWP
 */

namespace Agentic_WP;

defined( 'ABSPATH' ) || exit;

use Agentic_WP\Error_Handler;

/**
 * AJAX handler for image generation interface.
 *
 * @since 1.0.0
 */
class Image_Ajax {

	/**
	 * Image generator instance.
	 *
	 * @var Image_Generator
	 */
	private Image_Generator $generator;

	/**
	 * Registers AJAX hooks.
	 */
	public function __construct() {
		$this->generator = new Image_Generator();

		add_action( 'wp_ajax_agenticwp_generate_image', array( $this, 'handle_generate_image' ) );
		add_action( 'wp_ajax_agenticwp_save_image', array( $this, 'handle_save_image' ) );
		add_action( 'wp_ajax_agenticwp_get_recent_images', array( $this, 'handle_get_recent_images' ) );
	}

	/**
	 * Generate an image and return base64 data for preview.
	 *
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_generate_image(): void {
		try {
			if ( ! $this->verify_request() ) {
				wp_send_json_error( array( 'message' => __( 'Security check failed.', 'agenticwp' ) ), 403 );
			}

			// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_request().
			$prompt = $this->sanitize_prompt( wp_unslash( $_POST['prompt'] ?? '' ) );
			if ( empty( $prompt ) ) {
				wp_send_json_error( array( 'message' => __( 'Image prompt is required.', 'agenticwp' ) ), 400 );
			}

			$options = array(
				'size'          => $this->sanitize_size( wp_unslash( $_POST['size'] ?? '1024x1024' ) ),
				'quality'       => $this->sanitize_quality( wp_unslash( $_POST['quality'] ?? 'high' ) ),
				'output_format' => $this->sanitize_format( wp_unslash( $_POST['format'] ?? 'png' ) ),
				'background'    => $this->sanitize_background( wp_unslash( $_POST['background'] ?? 'auto' ) ),
			);
			// phpcs:enable WordPress.Security.NonceVerification.Missing

			$result = $this->generator->generate( $prompt, $options );

			if ( is_wp_error( $result ) ) {
				Error_Handler::log_error(
					'image_ajax',
					$result,
					array( 'prompt' => substr( $prompt, 0, 100 ) )
				);

				wp_send_json_error(
					array(
						'message' => $result->get_error_message(),
						'code'    => $result->get_error_code(),
					),
					500
				);
			}

			$b64_json = $result['b64_json'] ?? '';
			if ( empty( $b64_json ) ) {
				wp_send_json_error(
					array( 'message' => __( 'No image data received from API.', 'agenticwp' ) ),
					500
				);
			}

			wp_send_json_success(
				array(
					'b64_json' => $b64_json,
					'format'   => $options['output_format'],
					'size'     => $result['size'] ?? $options['size'],
					'quality'  => $result['quality'] ?? $options['quality'],
				)
			);
		} catch ( \Throwable $e ) {
			Error_Handler::log_error(
				'image_ajax',
				$e->getMessage(),
				array( 'trace' => $e->getTraceAsString() )
			);
			wp_send_json_error(
				array( 'message' => __( 'An unexpected error occurred.', 'agenticwp' ) ),
				500
			);
		}
	}

	/**
	 * Save a base64 image to the WordPress media library.
	 *
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_save_image(): void {
		try {
			if ( ! $this->verify_request() ) {
				wp_send_json_error( array( 'message' => __( 'Security check failed.', 'agenticwp' ) ), 403 );
			}

			// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_request().
			$b64_json = wp_unslash( $_POST['b64_json'] ?? '' );
			if ( empty( $b64_json ) ) {
				wp_send_json_error( array( 'message' => __( 'Image data is required.', 'agenticwp' ) ), 400 );
			}

			$filename = sanitize_file_name( wp_unslash( $_POST['filename'] ?? '' ) );
			if ( empty( $filename ) ) {
				$filename = 'ai-generated-' . time();
			}

			$format = $this->sanitize_format( wp_unslash( $_POST['format'] ?? 'png' ) );
			$prompt = $this->sanitize_prompt( wp_unslash( $_POST['prompt'] ?? '' ) );
			// phpcs:enable WordPress.Security.NonceVerification.Missing

			$result = $this->generator->save_image( $b64_json, $filename, $format, $prompt );

			if ( is_wp_error( $result ) ) {
				Error_Handler::log_error(
					'image_ajax',
					$result,
					array( 'context' => 'save_image' )
				);

				wp_send_json_error(
					array(
						'message' => $result->get_error_message(),
						'code'    => $result->get_error_code(),
					),
					500
				);
			}

			wp_send_json_success(
				array(
					'attachment_id' => $result['attachment_id'],
					'url'           => $result['url'],
					'filename'      => $result['filename'],
					'edit_url'      => admin_url( 'upload.php?item=' . $result['attachment_id'] ),
				)
			);
		} catch ( \Throwable $e ) {
			Error_Handler::log_error(
				'image_ajax',
				$e->getMessage(),
				array(
					'context' => 'save_image',
					'trace'   => $e->getTraceAsString(),
				)
			);
			wp_send_json_error(
				array( 'message' => __( 'An unexpected error occurred.', 'agenticwp' ) ),
				500
			);
		}
	}

	/**
	 * Get recent generated images for the history panel.
	 *
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_get_recent_images(): void {
		try {
			if ( ! $this->verify_request( false ) ) {
				wp_send_json_error( array( 'message' => __( 'Security check failed.', 'agenticwp' ) ), 403 );
			}

			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_request().
			$limit = absint( $_POST['limit'] ?? 10 );
			$limit = min( $limit, 50 ); // Cap at 50 images.

			$images = $this->generator->get_recent_images( $limit );

			wp_send_json_success(
				array( 'images' => $images )
			);
		} catch ( \Throwable $e ) {
			Error_Handler::log_error(
				'image_ajax',
				$e->getMessage(),
				array(
					'context' => 'get_recent_images',
					'trace'   => $e->getTraceAsString(),
				)
			);
			wp_send_json_error(
				array( 'message' => __( 'Failed to load recent images.', 'agenticwp' ) ),
				500
			);
		}
	}

	/**
	 * Validates nonce and capability.
	 *
	 * @param bool $check_api_key Whether to verify API key presence.
	 * @return bool True if request is valid.
	 */
	private function verify_request( bool $check_api_key = true ): bool {
		$nonce_value = sanitize_text_field( wp_unslash( $_POST['_ajax_nonce'] ?? '' ) );

		if ( ! wp_verify_nonce( $nonce_value, 'agenticwp_image_nonce' ) ) {
			return false;
		}

		if ( ! current_user_can( 'upload_files' ) ) {
			return false;
		}

		if ( $check_api_key && empty( Settings::get_api_key() ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Sanitizes the image prompt.
	 *
	 * @param string $prompt User prompt to sanitize.
	 * @return string Sanitized prompt.
	 */
	private function sanitize_prompt( string $prompt ): string {
		$prompt = sanitize_textarea_field( $prompt );

		// Max length per API docs is 32,000 characters.
		if ( strlen( $prompt ) > 32000 ) {
			$prompt = substr( $prompt, 0, 32000 );
		}

		return trim( $prompt );
	}

	/**
	 * Sanitizes size parameter.
	 *
	 * @param string $size Size value.
	 * @return string Valid size.
	 */
	private function sanitize_size( string $size ): string {
		$valid_sizes = array( '1024x1024', '1536x1024', '1024x1536' );
		return in_array( $size, $valid_sizes, true ) ? $size : '1024x1024';
	}

	/**
	 * Sanitizes quality parameter.
	 *
	 * @param string $quality Quality value.
	 * @return string Valid quality.
	 */
	private function sanitize_quality( string $quality ): string {
		$valid_qualities = array( 'low', 'medium', 'high' );
		return in_array( $quality, $valid_qualities, true ) ? $quality : 'low';
	}

	/**
	 * Sanitizes format parameter.
	 *
	 * @param string $format Format value.
	 * @return string Valid format.
	 */
	private function sanitize_format( string $format ): string {
		$valid_formats = array( 'png', 'jpeg', 'webp' );
		return in_array( $format, $valid_formats, true ) ? $format : 'webp';
	}

	/**
	 * Sanitizes background parameter.
	 *
	 * @param string $background Background value.
	 * @return string Valid background.
	 */
	private function sanitize_background( string $background ): string {
		$valid_backgrounds = array( 'auto', 'transparent', 'opaque' );
		return in_array( $background, $valid_backgrounds, true ) ? $background : 'auto';
	}
}
