<?php

namespace AIPT\Api\BulkGenerator\SeoMeta;

use AIPT\Api\BulkGenerator\BaseBulkGeneratorController;
use AIPT\Api\BulkGenerator\SeoMeta\Core\SeoPluginDetector;
use AIPT\Api\BulkGenerator\SeoMeta\Core\SeoMetaWriter;
use AIPT\Api\BulkGenerator\SeoMeta\SeoMetaHistoryManager;
use AIPT\Api\BulkGenerator\SeoMeta\SeoMetaDuplicationChecker;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

class SeoMetaGeneratorController extends BaseBulkGeneratorController {

	protected const RATE_LIMIT_SCOPE = 'seo_meta';

	private $service;
	private $writer;
	private $history_manager;
	private $duplication_checker;

	public function __construct(
		$service = null,
		$writer = null,
		$history_manager = null,
		$duplication_checker = null
	) {
		$this->service              = $service ?? new SeoMetaGeneratorService();
		$this->writer               = $writer ?? new SeoMetaWriter();
		$this->history_manager      = $history_manager ?? new SeoMetaHistoryManager();
		$this->duplication_checker  = $duplication_checker ?? new SeoMetaDuplicationChecker();
	}

	public function register_routes() {
		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/bulk-generate',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'bulk_generate' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
				'args'                => array(
					'productIds' => array(
						'type'              => 'array',
						'required'          => true,
						'sanitize_callback' => function ( $param ) {
							return array_map( 'absint', $param );
						},
					),
					'options'    => array(
						'type'              => 'object',
						'required'          => true,
						'sanitize_callback' => array( $this, 'sanitize_options' ),
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/bulk-apply',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'bulk_apply' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
				'args'                => array(
					'results' => array(
						'type'              => 'array',
						'required'          => true,
						'sanitize_callback' => array( $this, 'sanitize_results' ),
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/bulk-reject',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'bulk_reject' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
				'args'                => array(
					'results' => array(
						'type'              => 'array',
						'required'          => true,
						'sanitize_callback' => array( $this, 'sanitize_results' ),
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/detect-plugin',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'detect_plugin' ),
				'permission_callback' => array( $this, 'check_permissions' ),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/products',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_products' ),
				'permission_callback' => array( $this, 'check_permissions' ),
				'args'                => array(
					'search'              => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					),
					'category'            => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					),
					'page'                => array(
						'type'              => 'integer',
						'default'           => 1,
						'minimum'           => 1,
						'sanitize_callback' => 'absint',
					),
					'per_page'            => array(
						'type'              => 'integer',
						'default'           => 20,
						'minimum'           => 1,
						'maximum'           => 1000,
						'sanitize_callback' => array( $this, 'sanitize_per_page' ),
					),
					'orderby'             => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
					'order'               => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
					'status'              => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
					'stock_status'        => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
					'descriptionFilter'   => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
					'hasDescription'      => array(
						'type'              => 'boolean',
						'sanitize_callback' => function ( $value ) {
							return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
						},
					),
					'hasShortDescription' => array(
						'type'              => 'boolean',
						'sanitize_callback' => function ( $value ) {
							return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
						},
					),
					'has_image'           => array(
						'type'              => array( 'boolean', 'null' ),
						'sanitize_callback' => function ( $value ) {
							if ( '' === $value ) {
								return null;
							}
							return filter_var( $value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
						},
					),
					'has_gallery'         => array(
						'type'              => array( 'boolean', 'null' ),
						'sanitize_callback' => function ( $value ) {
							if ( '' === $value ) {
								return null;
							}
							return filter_var( $value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
						},
					),
					'sku_status'          => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
					'product_type'        => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
					),
					'featured'            => array(
						'type'              => array( 'boolean', 'null' ),
						'sanitize_callback' => function ( $value ) {
							if ( '' === $value ) {
								return null;
							}
							return filter_var( $value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
						},
					),
					'on_sale'             => array(
						'type'              => array( 'boolean', 'null' ),
						'sanitize_callback' => function ( $value ) {
							if ( '' === $value ) {
								return null;
							}
							return filter_var( $value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
						},
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/categories',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_categories' ),
				'permission_callback' => array( $this, 'check_permissions' ),
				'args'                => array(),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/history',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_history' ),
				'permission_callback' => array( $this, 'check_permissions' ),
				'args'                => array(
					'page'       => array(
						'type'              => 'integer',
						'default'           => 1,
						'sanitize_callback' => 'absint',
					),
					'per_page'   => array(
						'type'              => 'integer',
						'default'           => 20,
						'sanitize_callback' => array( $this, 'sanitize_per_page' ),
					),
					'status'     => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					),
					'product_id' => array(
						'type'              => 'integer',
						'sanitize_callback' => 'absint',
					),
					'search'     => array(
						'type'              => 'string',
						'default'           => '',
						'sanitize_callback' => 'sanitize_text_field',
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/history/(?P<id>\d+)/rollback',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'rollback_history' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
				'args'                => array(
					'id' => array(
						'type'              => 'integer',
						'required'          => true,
						'sanitize_callback' => 'absint',
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/history/(?P<id>\d+)',
			array(
				'methods'             => WP_REST_Server::DELETABLE,
				'callback'            => array( $this, 'delete_history' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
				'args'                => array(
					'id' => array(
						'type'              => 'integer',
						'required'          => true,
						'sanitize_callback' => 'absint',
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/history/bulk-delete',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'bulk_delete_history' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
				'args'                => array(
					'ids' => array(
						'type'              => 'array',
						'required'          => true,
						'items'             => array( 'type' => 'integer' ),
						'sanitize_callback' => function ( $ids ) {
							return array_map( 'absint', (array) $ids );
						},
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/history/delete-all',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'delete_all_history' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/check-duplicates',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'check_duplicates' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
				'args'                => array(
					'title'              => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					),
					'description'        => array(
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_textarea_field',
					),
					'exclude_product_id' => array(
						'type'              => 'integer',
						'sanitize_callback' => 'absint',
					),
				),
			)
		);

		\register_rest_route(
			'aipt/v1',
			'/seo-meta-generator/set-focus-keyword',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'set_focus_keyword' ),
				'permission_callback' => array( $this, 'check_permissions_write' ),
				'args'                => array(
					'product_id'    => array(
						'type'              => 'integer',
						'required'          => true,
						'sanitize_callback' => 'absint',
					),
					'focus_keyword' => array(
						'type'              => 'string',
						'required'          => true,
						'sanitize_callback' => 'sanitize_text_field',
					),
				),
			)
		);

	}

	/**
	 * Sanitizes per_page parameter with upper bound.
	 *
	 * Ceiling raised from 100 to 1000 to match Advanced Description
	 * (`Desc/Controllers/GenerationController.php:643`) and allow bulk
	 * SEO meta review at 500/1000 rows per page.
	 *
	 * @param mixed $value Raw per_page value.
	 * @return int Sanitized value between 1 and 1000.
	 */
	public function sanitize_per_page( $value ) {
		$per_page = absint( $value );
		return max( 1, min( 1000, $per_page ) );
	}

	/**
	 * Sanitizes the options parameter for generation requests.
	 *
	 * @param mixed $options Raw options from request.
	 *
	 * @return array Sanitized options array.
	 */
	public function sanitize_options( $options ) {
		if ( ! is_array( $options ) ) {
			return array();
		}

		$sanitized = array();

		if ( isset( $options['tone'] ) && is_string( $options['tone'] ) ) {
			$sanitized['tone'] = \sanitize_text_field( $options['tone'] );
		}
		if ( isset( $options['language'] ) && is_string( $options['language'] ) ) {
			$sanitized['language'] = \sanitize_text_field( $options['language'] );
		}

		if ( isset( $options['provider'] ) && is_string( $options['provider'] ) ) {
			$sanitized['provider'] = \sanitize_text_field( $options['provider'] );
		}
		if ( isset( $options['model'] ) && is_string( $options['model'] ) ) {
			$sanitized['model'] = \sanitize_text_field( $options['model'] );
		}

		if ( isset( $options['titleMaxLength'] ) ) {
			$sanitized['titleMaxLength'] = \absint( $options['titleMaxLength'] );
		}
		if ( isset( $options['descMaxLength'] ) ) {
			$sanitized['descMaxLength'] = \absint( $options['descMaxLength'] );
		}
		if ( isset( $options['variantCount'] ) ) {
			$sanitized['variantCount'] = max( 1, min( 5, \absint( $options['variantCount'] ) ) );
		}

		$boolean_fields = array(
			'generateTitle',
			'generateDescription',
			'generateFocusKeyword',
			'optimizeForFocusKeyword',
			'generateOgMeta',
		);
		foreach ( $boolean_fields as $field ) {
			if ( isset( $options[ $field ] ) ) {
				$sanitized[ $field ] = (bool) $options[ $field ];
			}
		}

		if ( isset( $options['sources'] ) && is_array( $options['sources'] ) ) {
			$sanitized['sources'] = array_values(
				array_filter(
					array_map( 'sanitize_key', $options['sources'] ),
					function ( $s ) {
						return ! empty( $s );
					}
				)
			);
		}

		return $sanitized;
	}

	/**
	 * Sanitizes the results parameter for apply/reject requests.
	 *
	 * @param mixed $results Raw results from request.
	 *
	 * @return array Sanitized results array.
	 */
	public function sanitize_results( $results ) {
		if ( ! is_array( $results ) ) {
			return array();
		}

		$sanitized = array();

		foreach ( $results as $item ) {
			if ( ! is_array( $item ) ) {
				continue;
			}

			$clean_item = array();

			if ( isset( $item['product_id'] ) ) {
				$clean_item['product_id'] = \absint( $item['product_id'] );
			}
			if ( isset( $item['meta_title'] ) && is_string( $item['meta_title'] ) ) {
				$clean_item['meta_title'] = \sanitize_text_field( $item['meta_title'] );
			}
			if ( isset( $item['meta_description'] ) && is_string( $item['meta_description'] ) ) {
				$clean_item['meta_description'] = \sanitize_textarea_field( $item['meta_description'] );
			}
			if ( isset( $item['focus_keyword'] ) && is_string( $item['focus_keyword'] ) ) {
				$clean_item['focus_keyword'] = \sanitize_text_field( $item['focus_keyword'] );
			}
			if ( isset( $item['product_name'] ) && is_string( $item['product_name'] ) ) {
				$clean_item['product_name'] = \sanitize_text_field( $item['product_name'] );
			}
			if ( isset( $item['selected_variant_index'] ) ) {
				$clean_item['selected_variant_index'] = \absint( $item['selected_variant_index'] );
			}

			if ( ! empty( $clean_item ) && isset( $clean_item['product_id'] ) && $clean_item['product_id'] > 0 ) {
				$sanitized[] = $clean_item;
			}
		}

		return $sanitized;
	}

	/**
	 * Apply premium controls to options.
	 *
	 * For WordPress.org Guidelines compliance (Guideline 5 - Trialware):
	 * - Free defaults are ENFORCED first (user options overridden)
	 * - Premium module hooks into filter to RESTORE premium values if licensed
	 *
	 * @param array $options User-provided options from request.
	 * @return array Controlled options with free defaults enforced.
	 */
	private function apply_premium_controls( $options ) {

		$free_defaults = array(
			'tone'                    => 'Professional',
			'titleMaxLength'          => 60,
			'descMaxLength'           => 160,
			'generateFocusKeyword'    => false,
			'optimizeForFocusKeyword' => false,
			'generateOgMeta'          => false,
			'variantCount'            => 2, 
		);

		$controlled_options = array_merge( $options, $free_defaults );

		$controlled_options = \apply_filters( 'aipt_seo_meta_validate_options', $controlled_options, $options );

		$allowed_sources = array(
			'product_name',
			'product_brand',
			'product_description',
			'short_description',
			'product_categories',
			'product_tags',
			'product_attributes',
			'product_sku',
			'product_price',
		);
		if ( isset( $controlled_options['sources'] ) && is_array( $controlled_options['sources'] ) ) {
			$controlled_options['sources'] = array_values( array_intersect( $controlled_options['sources'], $allowed_sources ) );
			if ( empty( $controlled_options['sources'] ) ) {

				$controlled_options['sources'] = array( 'product_name', 'product_description', 'product_categories' );
			}
		} else {

			$controlled_options['sources'] = array( 'product_name', 'product_description', 'product_categories' );
		}

		return $controlled_options;
	}

	public function bulk_generate( WP_REST_Request $request ) {

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

			$products = $request->get_param( 'productIds' );
			$options  = $request->get_param( 'options' );
			$options  = is_array( $options ) ? $options : array();

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

			if ( empty( $products ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'No products provided',
					),
					400
				);
			}

			$detected_plugin = SeoPluginDetector::detect();
			if ( null === $detected_plugin ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'No supported SEO plugin detected. Please install and activate one of: Yoast SEO, Rank Math, All in One SEO, SEOPress, The SEO Framework, or Squirrly.',
					),
					400
				);
			}

			$variant_count = isset( $options['variantCount'] ) ? (int) $options['variantCount'] : 2;
			if ( $variant_count > 1 ) {
				$results = $this->service->bulk_generate_variants( $products, $options );
			} else {
				$results = $this->service->bulk_generate( $products, $options );
			}

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

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

		} catch ( \InvalidArgumentException $e ) {
			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => $e->getMessage(),
				),
				400
			);
		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Generation failed. Please try again or contact support if the issue persists.',
				),
				500
			);
		}
	}

	public function bulk_apply( WP_REST_Request $request ) {
		try {

			$results = $request->get_param( 'results' );
			$results = is_array( $results ) ? $results : array();

			if ( empty( $results ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'No results provided',
					),
					400
				);
			}

			$detected_plugin = SeoPluginDetector::detect();
			if ( null === $detected_plugin ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'No supported SEO plugin detected',
					),
					400
				);
			}

			$plugin_slug    = $detected_plugin['plugin_slug'];
			$applied_count  = 0;
			$failed_count   = 0;
			$apply_results  = array();

			foreach ( $results as $result ) {
				$product_id = isset( $result['product_id'] ) ? absint( $result['product_id'] ) : 0;
				if ( ! $product_id ) {
					$failed_count++;
					continue;
				}

			$write_data = array();
			if ( isset( $result['meta_title'] ) && is_string( $result['meta_title'] ) ) {
				$write_data['title'] = $result['meta_title'];
			}
			if ( isset( $result['meta_description'] ) && is_string( $result['meta_description'] ) ) {
				$write_data['description'] = $result['meta_description'];
			}
			if ( ! empty( $result['focus_keyword'] ) && is_string( $result['focus_keyword'] ) ) {
				$write_data['focus_keyword'] = $result['focus_keyword'];
			}

				if ( empty( $write_data ) ) {
					$failed_count++;
					continue;
				}

				$current_seo = SeoPluginDetector::get_seo_info( $product_id, $detected_plugin );

				$write_results = $this->writer->bulkWrite( $product_id, $write_data, $plugin_slug );

				$field_success_count = 0;
				$field_fail_count    = 0;

				$variant_index = isset( $result['selected_variant_index'] ) ? absint( $result['selected_variant_index'] ) : 0;

				if ( isset( $write_data['title'] ) ) {
					$previous_title = $current_seo['meta_title'] ?? '';
					$field_status   = ! empty( $write_results['title'] ) ? 'approved' : 'rejected';

					\do_action(
						'aipt_seo_meta_record_history',
						$product_id,
						'title',
						$previous_title,
						$write_data['title'],
						$field_status,
						$variant_index,
						$plugin_slug,
						$this->history_manager
					);

					if ( 'approved' === $field_status ) {
						$field_success_count++;
					} else {
						$field_fail_count++;
					}
				}

				if ( isset( $write_data['description'] ) ) {
					$previous_desc = $current_seo['meta_description'] ?? '';
					$field_status  = ! empty( $write_results['description'] ) ? 'approved' : 'rejected';

					\do_action(
						'aipt_seo_meta_record_history',
						$product_id,
						'description',
						$previous_desc,
						$write_data['description'],
						$field_status,
						$variant_index,
						$plugin_slug,
						$this->history_manager
					);

					if ( 'approved' === $field_status ) {
						$field_success_count++;
					} else {
						$field_fail_count++;
					}
				}

				if ( isset( $write_data['focus_keyword'] ) ) {
					$previous_kw  = $current_seo['focus_keyword'] ?? '';
					$field_status = ! empty( $write_results['focus_keyword'] ) ? 'approved' : 'rejected';

					\do_action(
						'aipt_seo_meta_record_history',
						$product_id,
						'focus_keyword',
						$previous_kw,
						$write_data['focus_keyword'],
						$field_status,
						$variant_index,
						$plugin_slug,
						$this->history_manager
					);

					if ( 'approved' === $field_status ) {
						$field_success_count++;
					} else {
						$field_fail_count++;
					}
				}

				$all_success = ( $field_fail_count === 0 && $field_success_count > 0 );
				if ( $all_success ) {
					$applied_count++;
				} else {
					$failed_count++;
				}

				$apply_results[] = array(
					'product_id' => $product_id,
					'success'    => $all_success,
					'details'    => $write_results,
				);
			}

			if ( $applied_count > 0 ) {
				$first_applied_pid = 0;
				foreach ( $apply_results as $apply_row ) {
					if ( ! empty( $apply_row['success'] ) && isset( $apply_row['product_id'] ) ) {
						$first_applied_pid = (int) $apply_row['product_id'];
						break;
					}
				}
				\AIPT\Core\Services\UsageTracker::record_event(
					'seo_meta',
					'approved',
					$applied_count,
					array( 'product_id' => $first_applied_pid )
				);
			}

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

		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Apply failed. Please try again or contact support if the issue persists.',
				),
				500
			);
		}
	}

	public function bulk_reject( WP_REST_Request $request ) {

		$results = $request->get_param( 'results' );
		if ( empty( $results ) || ! is_array( $results ) ) {
			return new WP_REST_Response( array( 'rejected_count' => 0 ), 200 );
		}

		$rejected_count  = 0;
		$detected_plugin = SeoPluginDetector::detect();
		$plugin_slug     = $detected_plugin ? $detected_plugin['plugin_slug'] : '';

		foreach ( $results as $result ) {
			$product_id = isset( $result['product_id'] ) ? absint( $result['product_id'] ) : 0;
			if ( $product_id <= 0 ) {
				continue;
			}

			$variant_index = isset( $result['selected_variant_index'] ) ? absint( $result['selected_variant_index'] ) : 0;

			if ( isset( $result['meta_title'] ) && is_string( $result['meta_title'] ) ) {
				\do_action(
					'aipt_seo_meta_record_history',
					$product_id,
					'title',
					'', 
					$result['meta_title'],
					'rejected',
					$variant_index,
					$plugin_slug,
					$this->history_manager
				);
			}
			if ( isset( $result['meta_description'] ) && is_string( $result['meta_description'] ) ) {
				\do_action(
					'aipt_seo_meta_record_history',
					$product_id,
					'description',
					'',
					$result['meta_description'],
					'rejected',
					$variant_index,
					$plugin_slug,
					$this->history_manager
				);
			}
			if ( isset( $result['focus_keyword'] ) && is_string( $result['focus_keyword'] ) ) {
				\do_action(
					'aipt_seo_meta_record_history',
					$product_id,
					'focus_keyword',
					'',
					$result['focus_keyword'],
					'rejected',
					$variant_index,
					$plugin_slug,
					$this->history_manager
				);
			}

			$rejected_count++;
		}

		if ( $rejected_count > 0 ) {
			$first_rejected_pid = 0;
			foreach ( $results as $row ) {
				if ( isset( $row['product_id'] ) && (int) $row['product_id'] > 0 ) {
					$first_rejected_pid = (int) $row['product_id'];
					break;
				}
			}
			\AIPT\Core\Services\UsageTracker::record_event(
				'seo_meta',
				'rejected',
				$rejected_count,
				array( 'product_id' => $first_rejected_pid )
			);
		}

		return new WP_REST_Response(
			array(
				'success'        => true,
				'rejected_count' => $rejected_count,
				'message'        => 'Results rejected successfully',
			),
			200
		);
	}

	public function detect_plugin( WP_REST_Request $request ) {
		unset( $request ); 
		$detected = SeoPluginDetector::detect();

		return new WP_REST_Response(
			array(
				'success' => true,
				'plugin'  => $detected,
			),
			200
		);
	}

	public function get_products( WP_REST_Request $request ) {
		$params = $request->get_params();

		$sanitized = array();
		if ( isset( $params['search'] ) ) {
			$sanitized['search'] = \sanitize_text_field( $params['search'] );
		}
		if ( isset( $params['category'] ) ) {
			$sanitized['category'] = \sanitize_text_field( $params['category'] );
		}
		if ( isset( $params['page'] ) ) {
			$sanitized['page'] = \absint( $params['page'] );
		}
		if ( isset( $params['per_page'] ) ) {
			$per_page = \absint( $params['per_page'] );
			$sanitized['per_page'] = max( 1, min( 1000, $per_page ) );
		}
		if ( isset( $params['orderby'] ) ) {
			$sanitized['orderby'] = \sanitize_key( $params['orderby'] );
		}
		if ( isset( $params['order'] ) ) {
			$sanitized['order'] = \sanitize_key( $params['order'] );
		}
		if ( isset( $params['status'] ) ) {
			$sanitized['status'] = \sanitize_key( $params['status'] );
		}
		if ( isset( $params['stock_status'] ) ) {
			$sanitized['stock_status'] = \sanitize_key( $params['stock_status'] );
		}
		if ( isset( $params['descriptionFilter'] ) ) {
			$sanitized['descriptionFilter'] = \sanitize_key( $params['descriptionFilter'] );
		}
		if ( isset( $params['hasDescription'] ) ) {
			$sanitized['hasDescription'] = (bool) $params['hasDescription'];
		}
		if ( isset( $params['hasShortDescription'] ) ) {
			$sanitized['hasShortDescription'] = (bool) $params['hasShortDescription'];
		}

		if ( isset( $params['has_image'] ) && '' !== $params['has_image'] ) {
			$sanitized['has_image'] = filter_var( $params['has_image'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
		}

		if ( isset( $params['has_gallery'] ) && '' !== $params['has_gallery'] ) {
			$sanitized['has_gallery'] = filter_var( $params['has_gallery'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
		}

		if ( ! empty( $params['sku_status'] ) ) {
			$sanitized['sku_status'] = \sanitize_key( $params['sku_status'] );
		}

		if ( ! empty( $params['product_type'] ) ) {
			$sanitized['product_type'] = \sanitize_key( $params['product_type'] );
		}

		if ( isset( $params['featured'] ) && '' !== $params['featured'] ) {
			$sanitized['featured'] = filter_var( $params['featured'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
		}

		if ( isset( $params['on_sale'] ) && '' !== $params['on_sale'] ) {
			$sanitized['on_sale'] = filter_var( $params['on_sale'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
		}

		$results = $this->service->get_products( $sanitized );

		$detected_plugin = SeoPluginDetector::detect();
		if ( isset( $results['products'] ) && is_array( $results['products'] ) ) {
			foreach ( $results['products'] as &$product ) {
				if ( isset( $product['id'] ) ) {
					$product['seo_info'] = SeoPluginDetector::get_seo_info( $product['id'], $detected_plugin );
				}
			}
			unset( $product );
		}

		return new WP_REST_Response( $results, 200 );
	}

	public function get_categories( WP_REST_Request $request ) {
		unset( $request ); 
		$categories = $this->service->get_categories();

		return new WP_REST_Response(
			array(
				'success'    => true,
				'categories' => $categories,
			),
			200
		);
	}

	/**
	 * Retrieves SEO meta generation history with pagination and filters.
	 *
	 * For WordPress.org Guidelines compliance (Guideline 5 - Trialware):
	 * History is a premium feature. Free users get a premium-required message.
	 * Premium module hooks in to provide actual data.
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response History items with pagination metadata.
	 */
	public function get_history( WP_REST_Request $request ) {
		try {
			$page       = $request->get_param( 'page' ) ? \absint( $request->get_param( 'page' ) ) : 1;
			$per_page   = $this->sanitize_per_page( $request->get_param( 'per_page' ) ?: 20 );
			$status     = $request->get_param( 'status' ) ? \sanitize_text_field( $request->get_param( 'status' ) ) : null;
			$search     = $request->get_param( 'search' ) ? \sanitize_text_field( $request->get_param( 'search' ) ) : null;
			$product_id = $request->get_param( 'product_id' ) ? \absint( $request->get_param( 'product_id' ) ) : 0;

			$args = array(
				'page'       => $page,
				'per_page'   => $per_page,
				'status'     => $status,
				'search'     => $search,
				'product_id' => $product_id,
			);

			$default_result = array(
				'success'          => false,
				'items'            => array(),
				'total'            => 0,
				'total_pages'      => 0,
				'message'          => __( 'History feature requires a premium license.', 'ai-product-tools' ),
				'premium_required' => true,
			);

			$result = \apply_filters( 'aipt_seo_meta_get_history', $default_result, $args, $this->history_manager );

			if ( ! empty( $result['premium_required'] ) ) {
				return new WP_REST_Response( $result, 403 );
			}

			return new WP_REST_Response(
				array(
					'success'     => true,
					'items'       => $result['items'] ?? array(),
					'total'       => $result['total'] ?? 0,
					'total_pages' => $result['total_pages'] ?? 0,
				),
				200
			);

		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Failed to retrieve history',
				),
				500
			);
		}
	}

	/**
	 * Rolls back a history item to its previous value.
	 *
	 * For WordPress.org Guidelines compliance (Guideline 5 - Trialware):
	 * Rollback is a premium feature. Free users get a premium-required message.
	 * Premium module hooks in to perform actual rollback.
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response Rollback result.
	 */
	public function rollback_history( WP_REST_Request $request ) {
		try {
			$id = $request->get_param( 'id' ) ? \absint( $request->get_param( 'id' ) ) : 0;

			if ( ! $id ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'Invalid history ID',
					),
					400
				);
			}

			$default_result = array(
				'success'          => false,
				'message'          => __( 'History rollback requires a premium license.', 'ai-product-tools' ),
				'premium_required' => true,
			);

			$result = \apply_filters( 'aipt_seo_meta_rollback_history', $default_result, $id, $this->history_manager );

			if ( ! empty( $result['premium_required'] ) ) {
				return new WP_REST_Response( $result, 403 );
			}

			if ( empty( $result['success'] ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => $result['message'] ?? 'Failed to rollback history item',
					),
					400
				);
			}

			return new WP_REST_Response(
				array(
					'success' => true,
					'message' => $result['message'] ?? 'History item rolled back successfully',
				),
				200
			);

		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Rollback operation failed',
				),
				500
			);
		}
	}

	/**
	 * Deletes a history item.
	 *
	 * For WordPress.org Guidelines compliance (Guideline 5 - Trialware):
	 * History deletion is a premium feature. Free users get a premium-required message.
	 * Premium module hooks in to perform actual deletion.
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response Deletion result.
	 */
	public function delete_history( WP_REST_Request $request ) {
		try {
			$id = $request->get_param( 'id' ) ? \absint( $request->get_param( 'id' ) ) : 0;

			if ( ! $id ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'Invalid history ID',
					),
					400
				);
			}

			$default_result = array(
				'success'          => false,
				'message'          => __( 'History management requires a premium license.', 'ai-product-tools' ),
				'premium_required' => true,
			);

			$result = \apply_filters( 'aipt_seo_meta_delete_history', $default_result, $id, $this->history_manager );

			if ( ! empty( $result['premium_required'] ) ) {
				return new WP_REST_Response( $result, 403 );
			}

			if ( empty( $result['success'] ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => $result['message'] ?? 'Failed to delete history item',
					),
					400
				);
			}

			return new WP_REST_Response(
				array(
					'success' => true,
					'message' => $result['message'] ?? 'History item deleted successfully',
				),
				200
			);

		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Delete operation failed',
				),
				500
			);
		}
	}

	/**
	 * Bulk delete history items.
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response Deletion result.
	 */
	public function bulk_delete_history( WP_REST_Request $request ) {
		try {
			$ids = $request->get_param( 'ids' );

			if ( empty( $ids ) || ! is_array( $ids ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'No history IDs provided',
					),
					400
				);
			}

			$default_result = array(
				'success'          => false,
				'message'          => __( 'History management requires a premium license.', 'ai-product-tools' ),
				'premium_required' => true,
			);

			$result = \apply_filters( 'aipt_seo_meta_bulk_delete_history', $default_result, $ids, $this->history_manager );

			if ( ! empty( $result['premium_required'] ) ) {
				return new WP_REST_Response( $result, 403 );
			}

			if ( empty( $result['success'] ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => $result['message'] ?? 'Failed to delete history items',
					),
					400
				);
			}

			return new WP_REST_Response(
				array(
					'success'       => true,
					'message'       => $result['message'] ?? 'History items deleted successfully',
					'deleted_count' => $result['deleted_count'] ?? count( $ids ),
				),
				200
			);

		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Bulk delete operation failed',
				),
				500
			);
		}
	}

	/**
	 * Delete all history items.
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response Deletion result.
	 */
	public function delete_all_history( WP_REST_Request $request ) {
		try {
			$default_result = array(
				'success'          => false,
				'message'          => __( 'History management requires a premium license.', 'ai-product-tools' ),
				'premium_required' => true,
			);

			$result = \apply_filters( 'aipt_seo_meta_delete_all_history', $default_result, $this->history_manager );

			if ( ! empty( $result['premium_required'] ) ) {
				return new WP_REST_Response( $result, 403 );
			}

			if ( empty( $result['success'] ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => $result['message'] ?? 'Failed to delete all history items',
					),
					400
				);
			}

			return new WP_REST_Response(
				array(
					'success'       => true,
					'message'       => $result['message'] ?? 'All history items deleted successfully',
					'deleted_count' => $result['deleted_count'] ?? 0,
				),
				200
			);

		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Delete all operation failed',
				),
				500
			);
		}
	}

	/**
	 * Checks for duplicate or similar SEO meta across products.
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response Similar products with similarity scores.
	 */
	public function check_duplicates( WP_REST_Request $request ) {
		try {
			$title              = $request->get_param( 'title' ) ? \sanitize_text_field( $request->get_param( 'title' ) ) : '';
			$description        = $request->get_param( 'description' ) ? \sanitize_textarea_field( $request->get_param( 'description' ) ) : '';
			$exclude_product_id = $request->get_param( 'exclude_product_id' ) ? \absint( $request->get_param( 'exclude_product_id' ) ) : 0;

			if ( empty( $title ) && empty( $description ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'Title or description is required',
					),
					400
				);
			}

			$duplicates = $this->duplication_checker->check_duplicates( $title, $description, $exclude_product_id );

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

		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Duplication check failed',
				),
				500
			);
		}
	}

	/**
	 * Sets the focus keyword for a single product.
	 *
	 * @param WP_REST_Request $request The REST request object.
	 *
	 * @return WP_REST_Response Success or failure result.
	 */
	public function set_focus_keyword( WP_REST_Request $request ) {
		try {
			$product_id    = $request->get_param( 'product_id' );
			$focus_keyword = $request->get_param( 'focus_keyword' );

			if ( ! $product_id ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'Product ID is required',
					),
					400
				);
			}

			$focus_keyword = trim( $focus_keyword ?? '' );
			if ( empty( $focus_keyword ) ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'Focus keyword cannot be empty',
					),
					400
				);
			}

			$product = \wc_get_product( $product_id );
			if ( ! $product ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'Product not found',
					),
					404
				);
			}

			$detected_plugin = SeoPluginDetector::detect();
			if ( null === $detected_plugin ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'No supported SEO plugin detected',
					),
					400
				);
			}

			$current_seo = SeoPluginDetector::get_seo_info( $product_id, $detected_plugin );
			$current_value = $current_seo['focus_keyword'] ?? '';

			$result = $this->writer->write( $product_id, 'focus_keyword', $focus_keyword, $detected_plugin['plugin_slug'] );

			if ( ! $result ) {
				return new WP_REST_Response(
					array(
						'success' => false,
						'message' => 'Failed to save focus keyword',
					),
					500
				);
			}

			$plugin_slug = $detected_plugin['plugin_slug'];
			\do_action(
				'aipt_seo_meta_record_history',
				$product_id,
				'focus_keyword',
				$current_value,
				$focus_keyword,
				'approved',
				0,
				$plugin_slug,
				$this->history_manager
			);

			return new WP_REST_Response(
				array(
					'success'       => true,
					'message'       => 'Focus keyword saved successfully',
					'focus_keyword' => $focus_keyword,
				),
				200
			);

		} catch ( \Exception $e ) {

			return new WP_REST_Response(
				array(
					'success' => false,
					'message' => 'Failed to save focus keyword',
				),
				500
			);
		}
	}

}
