<?php
/**
 * Standard Bulk Generator Controller
 *
 * @package AIPT\Api\BulkGenerator\Standard
 * @since 2.5.0
 */

namespace AIPT\Api\BulkGenerator\Standard;

use AIPT\Api\BulkGenerator\BaseBulkGeneratorController;
use AIPT\Api\Constants\RateLimitConstants;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use AIPT\Core\ErrorHandler;

class StandardBulkGeneratorController extends BaseBulkGeneratorController {

	protected const RATE_LIMIT_SCOPE = 'standard';

	private ?StandardGenerator $generator = null;

	public function register_routes(): void {
		register_rest_route( 'aipt/v1', '/standard-bulk-generator/generate', array(
			'methods'             => 'POST',
			'callback'            => array( $this, 'generate_descriptions' ),
			'permission_callback' => array( $this, 'check_permissions_write' ),
			'args'                => array(
				'product_ids' => array(
					'type'              => 'array',
					'required'          => true,
					'sanitize_callback' => function ( $param ) {
						return array_map( 'absint', $param );
					},
				),
				'options'     => array(
					'type'     => 'object',
					'required' => true,
				),
			),
		) );

		register_rest_route( 'aipt/v1', '/standard-bulk-generator/apply', array(
			'methods'             => 'POST',
			'callback'            => array( $this, 'apply_descriptions' ),
			'permission_callback' => array( $this, 'check_permissions_write' ),
			'args'                => array(
				'items' => array(
					'type'     => 'array',
					'required' => true,
				),
			),
		) );
	}

	/**
	 * Generate descriptions for selected products.
	 *
	 * @param WP_REST_Request $request REST request instance.
	 * @return WP_REST_Response|WP_Error Response with generated descriptions or error.
	 */
	public function generate_descriptions( WP_REST_Request $request ) {

		$ai_gate = \AIPT\Core\Services\AiSupportGate::guard();
		if ( $ai_gate instanceof \WP_Error ) {
			return $ai_gate;
		}
		$rate_check = $this->checkRateLimit(
			(int) get_current_user_id(),
			static::RATE_LIMIT_SCOPE,
			RateLimitConstants::STANDARD_MAX_REQUESTS,
			RateLimitConstants::STANDARD_WINDOW_SECONDS
		);
		if ( ! $rate_check['allowed'] ) {
			return $this->rateLimitResponse( $rate_check );
		}

		$product_ids = $request->get_param( 'product_ids' );
		$options     = $request->get_param( 'options' );

		if ( empty( $product_ids ) ) {
			return new WP_Error(
				'invalid_input',
				__( 'No products selected', 'ai-product-tools' ),
				array( 'status' => 400 )
			);
		}

		$options = $this->sanitizeOptions( $options );

		try {
			$generator = $this->getGenerator( $options );
			$results   = $generator->bulkGenerate( $product_ids, $options );

			\AIPT\Core\Services\UsageTracker::record_event(
				'standard_desc',
				'generated',
				is_array( $results ) ? count( $results ) : count( $product_ids ),
				array(
					'product_id' => is_array( $product_ids ) && ! empty( $product_ids )
						? (int) $product_ids[ array_key_first( $product_ids ) ]
						: 0,
				)
			);

			return new WP_REST_Response(
				array(
					'success' => true,
					'data'    => $results,
				),
				200
			);

		} catch ( \Exception $e ) {
			$provider = $options['provider'] ?? get_option( 'aipt_api_provider', 'openai' );
			$error_message = ErrorHandler::format_api_error_message( ucfirst( $provider ), $e->getMessage() );

			$status_code = 500;
			if ( strpos( $e->getMessage(), 'Invalid' ) !== false ) {
				$status_code = 400;
			} elseif ( strpos( $e->getMessage(), 'API Error' ) !== false ) {
				$status_code = 502;
			}

			return new WP_Error(
				'aipt_error',
				$error_message,
				array( 'status' => $status_code )
			);
		}
	}

	/**
	 * Apply generated descriptions to products.
	 *
	 * @param WP_REST_Request $request REST request instance.
	 * @return WP_REST_Response|WP_Error Response with applied results or error.
	 */
	public function apply_descriptions( WP_REST_Request $request ) {
		$items = $request->get_param( 'items' );

		if ( empty( $items ) ) {
			return new WP_Error(
				'invalid_input',
				__( 'No descriptions selected to apply', 'ai-product-tools' ),
				array( 'status' => 400 )
			);
		}

		try {
			$generator = $this->getGenerator( array() );
			$result    = $generator->applyDescriptions( $items );

			$result_items = is_array( $result ) && isset( $result['results'] ) && is_array( $result['results'] ) ? $result['results'] : array();
			$applied_items = array_values( array_filter(
				$result_items,
				static function ( $item ) {
					return is_array( $item ) && ! empty( $item['success'] );
				}
			) );
			$applied_count = isset( $result['applied_count'] ) ? (int) $result['applied_count'] : count( $applied_items );

			\AIPT\Core\Services\UsageTracker::record_event(
				'standard_desc',
				'applied',
				$applied_count,
				array(
					'product_id' => ! empty( $applied_items ) && isset( $applied_items[0]['product_id'] )
						? (int) $applied_items[0]['product_id']
						: 0,
				)
			);

			return new WP_REST_Response(
				array(
					'success' => true,
					'data'    => $result,
				),
				200
			);

		} catch ( \Exception $e ) {
			return new WP_Error(
				'aipt_error',
				ErrorHandler::make_urls_readable( $e->getMessage() ),
				array( 'status' => 500 )
			);
		}
	}

	private function getGenerator( array $options ): StandardGenerator {
		if ( null === $this->generator ) {
			$this->generator = new StandardGenerator( $options );
		}
		return $this->generator;
	}

	private function sanitizeOptions( $options ): array {
		if ( ! is_array( $options ) ) {
			$options = array();
		}

		$sanitized = array(
			'provider'                   => sanitize_text_field( $options['provider'] ?? get_option( 'aipt_api_provider', 'openai' ) ),
			'model'                      => sanitize_text_field( $options['model'] ?? '' ),
			'generateDescription'        => (bool) ( $options['generateDescription'] ?? false ),
			'generateShortDescription'   => (bool) ( $options['generateShortDescription'] ?? false ),
			'generateTags'               => (bool) ( $options['generateTags'] ?? false ),
			'keepExistingDescription'    => (bool) ( $options['keepExistingDescription'] ?? false ),
			'preserve_content_images'    => (bool) ( $options['preserve_content_images'] ?? get_option( 'aipt_preserve_content_images', true ) ),
			'improveExistingDescription' => (bool) ( $options['improveExistingDescription'] ?? false ),
			'additionalTagsCount'        => absint( $options['additionalTagsCount'] ?? 3 ),
			'max_tags_count'             => absint( $options['max_tags_count'] ?? get_option( 'aipt_max_tags_count', 3 ) ),
		);

		if ( isset( $options['language'] ) ) {
			$sanitized['language'] = sanitize_text_field( $options['language'] );
		}
		if ( isset( $options['writing_style'] ) ) {
			$sanitized['writing_style'] = sanitize_text_field( $options['writing_style'] );
		}
		if ( isset( $options['writingStyle'] ) ) {
			$sanitized['writingStyle'] = sanitize_text_field( $options['writingStyle'] );
		}
		if ( isset( $options['content_length_preset'] ) ) {
			$sanitized['content_length_preset'] = sanitize_text_field( $options['content_length_preset'] );
		}
		if ( isset( $options['short_length_preset'] ) ) {
			$sanitized['short_length_preset'] = sanitize_text_field( $options['short_length_preset'] );
		}

		if ( ! empty( $options['prompts'] ) && is_array( $options['prompts'] ) ) {
			$sanitized['prompts'] = array();
			foreach ( array( 'short', 'full', 'tags' ) as $type ) {
				if ( isset( $options['prompts'][ $type ] ) && is_array( $options['prompts'][ $type ] ) ) {
					$sanitized['prompts'][ $type ] = array();
					if ( isset( $options['prompts'][ $type ]['system_prompt'] ) ) {
						$sanitized['prompts'][ $type ]['system_prompt'] = sanitize_textarea_field(
							$options['prompts'][ $type ]['system_prompt']
						);
					}
					if ( isset( $options['prompts'][ $type ]['user_prompt'] ) ) {
						$sanitized['prompts'][ $type ]['user_prompt'] = sanitize_textarea_field(
							$options['prompts'][ $type ]['user_prompt']
						);
					}
				}
			}
		}

		return $sanitized;
	}

}
