<?php
/**
 * Image Alt Text Generator Controller
 *
 * @package AIPT\Api\BulkGenerator\ImageAlt
 * @since   2.6.0
 */

namespace AIPT\Api\BulkGenerator\ImageAlt;

use AIPT\Api\BulkGenerator\BaseBulkGeneratorController;
use AIPT\Core\ErrorHandler;
use WP_Error;
use WP_REST_Request;

class ImageAltController extends BaseBulkGeneratorController {

	protected const RATE_LIMIT_SCOPE = 'image_alt';

	private $service;

	public function __construct() {
		$this->service = new Service();
	}

	public function register_routes(): void {
		register_rest_route( self::REST_NAMESPACE, '/image-alt-generator/bulk-generate', [
			'methods'             => 'POST',
			'callback'            => [ $this, 'bulk_generate' ],
			'permission_callback' => [ $this, 'check_permissions_write' ],
			'args'                => [
				/*
				 * NEW (v2): image-level selection shape.
				 * [ { productId: 123, attachmentIds: [45, 67] }, ... ]
				 */
				'selections' => [
					'type'     => 'array',
					'required' => false,
					'default'  => [],
				],
				/*
				 * LEGACY (v1): list of product IDs.
				 * Still accepted; backend falls back to collect_image_ids() logic.
				 */
				'productIds' => [
					'type'              => 'array',
					'required'          => false,
					'default'           => [],
					'sanitize_callback' => function ( $param ) {
						return array_map( 'absint', (array) $param );
					},
				],
				'options'    => [
					'type'       => 'object',
					'required'   => false,
					'default'    => [],
					'properties' => [
						'additionalPrompt' => [
							'type'      => 'string',
							'required'  => false,
							'default'   => '',
							'maxLength' => 2000,
						],
					],
				],
			],
		] );

		register_rest_route( self::REST_NAMESPACE, '/image-alt-generator/bulk-apply', [
			'methods'             => 'POST',
			'callback'            => [ $this, 'bulk_apply' ],
			'permission_callback' => [ $this, 'check_permissions_write' ],
			'args'                => [
				'results' => [
					'type'              => 'array',
					'required'          => true,
					'validate_callback' => [ $this, 'validate_bulk_apply_results' ],
				],
			],
		] );

		register_rest_route( self::REST_NAMESPACE, '/image-alt-generator/product-images', [
			'methods'             => 'GET',
			'callback'            => [ $this, 'get_product_images' ],
			'permission_callback' => [ $this, 'check_permissions' ],
			'args'                => [
				'product_id' => [
					'type'              => 'integer',
					'required'          => true,
					'sanitize_callback' => 'absint',
					'validate_callback' => function ( $value ) {
						return is_numeric( $value ) && (int) $value > 0;
					},
				],
			],
		] );
	}

	private function applyPremiumControls( array $options ): array {
		$free_defaults = [
			'includeGallery'       => false,
			'tone'                 => 'descriptive',
			'enrichWithAttributes' => false,
			'additionalPrompt'     => '',
		];

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

		/**
		 * Filter image alt generator validated options.
		 *
		 * Premium module hooks here to preserve includeGallery, tone, attribute
		 * enrichment, and additionalPrompt when a valid license is present.
		 *
		 * @since 2.6.0
		 * @param array $controlled Options with free defaults applied.
		 * @param array $options    Original request options.
		 */
		$controlled = apply_filters( 'aipt_image_alt_validate_options', $controlled, $options );

		return $controlled;
	}

	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(), static::RATE_LIMIT_SCOPE );
			if ( ! $rate_check['allowed'] ) {
				return $this->rateLimitResponse( $rate_check );
			}

			$data = $request->get_json_params();
			if ( ! is_array( $data ) ) {
				return $this->error_response(
					'invalid_payload',
					__( 'Invalid request payload.', 'ai-product-tools' )
				);
			}

			$options = (array) ( $data['options'] ?? [] );

			$premium_params = [];
			if ( ! empty( $options['includeGallery'] ) ) {
				$premium_params[] = 'includeGallery';
			}
			if ( ! empty( $options['tone'] ) && 'descriptive' !== $options['tone'] ) {
				$premium_params[] = 'tone';
			}
			if ( ! empty( $options['enrichWithAttributes'] ) ) {
				$premium_params[] = 'enrichWithAttributes';
			}
			if ( ! empty( $options['additionalPrompt'] ) && '' !== trim( (string) $options['additionalPrompt'] ) ) {
				$premium_params[] = 'additionalPrompt';
			}

			if (
				! empty( $premium_params ) &&
				! \AIPT\Utils\PremiumFeatureManager::getInstance()->canUsePremiumFeatures()
			) {
				return new WP_Error(
					'premium_required',
					sprintf(
						/* translators: %s: comma-separated premium option names */
						__( 'The following options require Pro plan: %s', 'ai-product-tools' ),
						implode( ', ', $premium_params )
					),
					[ 'status' => 403, 'premium_features' => $premium_params ]
				);
			}

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

			/*
			 * NEW shape: { selections: [{productId, attachmentIds}], options }
			 * Detects whether caller sent v2 selections or v1 productIds.
			 */
			$selections = (array) ( $data['selections'] ?? [] );
			$sanitized_selections = [];

			if ( ! empty( $selections ) ) {
				foreach ( $selections as $sel ) {
					if ( ! is_array( $sel ) ) {
						continue;
					}

					$product_id     = absint( $sel['productId'] ?? 0 );
					$attachment_ids = array_filter( array_map( 'absint', (array) ( $sel['attachmentIds'] ?? [] ) ) );

					if ( $product_id > 0 && ! empty( $attachment_ids ) ) {
						$sanitized_selections[] = [
							'productId'     => $product_id,
							'attachmentIds' => array_values( $attachment_ids ),
						];
					}
				}

				if ( empty( $sanitized_selections ) ) {
					return $this->error_response(
						'no_images',
						__( 'No valid image selections provided.', 'ai-product-tools' )
					);
				}

				$results = $this->service->bulk_generate_by_selections( $sanitized_selections, $options );

			} else {

				$product_ids = array_filter( array_map( 'absint', (array) ( $data['productIds'] ?? [] ) ) );

				if ( empty( $product_ids ) ) {
					return $this->error_response(
						'no_products',
						__( 'No products or image selections provided.', 'ai-product-tools' )
					);
				}

				$results = $this->service->bulk_generate( array_values( $product_ids ), $options );
			}

			$first_image_pid = 0;
			if ( ! empty( $sanitized_selections ) && isset( $sanitized_selections[0]['productId'] ) ) {
				$first_image_pid = (int) $sanitized_selections[0]['productId'];
			} elseif ( isset( $product_ids ) && is_array( $product_ids ) && ! empty( $product_ids ) ) {
				$first_image_pid = (int) $product_ids[ array_key_first( $product_ids ) ];
			}

			\AIPT\Core\Services\UsageTracker::record_event(
				'image_alt',
				'generated',
				is_array( $results ) ? count( $results ) : 1,
				array( 'product_id' => $first_image_pid )
			);

			return $this->success_response( [ 'results' => $results ] );

		} catch ( \Exception $e ) {
			$provider = get_option( 'aipt_api_provider', 'openai' );
			return ErrorHandler::create_wp_error(
				ErrorHandler::format_api_error_message( ucfirst( $provider ), $e->getMessage() ),
				'aipt_image_alt_generation_error'
			);
		}
	}

	public function bulk_apply( WP_REST_Request $request ) {
		try {
			$rate_check = $this->checkRateLimit( (int) \get_current_user_id(), 'image_alt_apply' );
			if ( ! $rate_check['allowed'] ) {
				return $this->rateLimitResponse( $rate_check );
			}

			$params = $request->get_json_params();
			if ( ! is_array( $params ) ) {
				return $this->error_response(
					'invalid_payload',
					__( 'Invalid request payload.', 'ai-product-tools' )
				);
			}

			$results = (array) ( $params['results'] ?? [] );

			if ( ! $this->validate_bulk_apply_results( $results ) ) {
				return $this->error_response(
					'invalid_results',
					__( 'Invalid image alt results provided to apply.', 'ai-product-tools' )
				);
			}

			$updated = 0;
			$failed  = 0;

			foreach ( $results as $item ) {
				$attachment_id = absint( $item['attachment_id'] ?? 0 );
				$product_id    = absint( $item['product_id'] ?? 0 );
				$alt_text      = sanitize_text_field( $item['alt_text'] ?? '' );
				$status        = sanitize_text_field( $item['status'] ?? '' );

				if (
					$attachment_id <= 0 ||
					$product_id <= 0 ||
					'error' === $status ||
					'rejected' === $status ||
					! $this->can_update_attachment_alt( $attachment_id, $product_id )
				) {
					$failed++;
					continue;
				}

				$current_alt = (string) get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
				if ( $current_alt === $alt_text ) {
					$updated++;
					continue;
				}

				$result = update_post_meta( $attachment_id, '_wp_attachment_image_alt', $alt_text );

				if ( false === $result ) {
					$failed++;
				} else {
					$updated++;
				}
			}

			if ( $updated > 0 ) {
				\AIPT\Core\Services\UsageTracker::record_event(
					'image_alt',
					'applied',
					$updated,
					array( 'label' => sprintf( '%d image(s)', $updated ) )
				);
			}

			return $this->success_response( [
				'updated' => $updated,
				'failed'  => $failed,
			] );

		} catch ( \Exception $e ) {
			return $this->error_response(
				'apply_error',
				ErrorHandler::sanitize_error_for_display( $e->getMessage() ),
				500
			);
		}
	}

	public function validate_bulk_apply_results( $value ): bool {
		if ( ! is_array( $value ) || empty( $value ) ) {
			return false;
		}

		foreach ( $value as $item ) {
			if ( ! is_array( $item ) ) {
				return false;
			}

			if ( absint( $item['attachment_id'] ?? 0 ) <= 0 || absint( $item['product_id'] ?? 0 ) <= 0 ) {
				return false;
			}

			if ( ! array_key_exists( 'alt_text', $item ) || ! is_scalar( $item['alt_text'] ) ) {
				return false;
			}
		}

		return true;
	}

	private function can_update_attachment_alt( int $attachment_id, int $product_id ): bool {
		if ( ! \wp_get_attachment_image_url( $attachment_id, 'full' ) ) {
			return false;
		}

		if ( ! current_user_can( 'edit_post', $attachment_id ) ) {
			return false;
		}

		$product = wc_get_product( $product_id );
		if ( ! $product ) {
			return false;
		}

		if ( ! current_user_can( 'edit_post', $product_id ) ) {
			return false;
		}

		if ( (int) $product->get_image_id() === $attachment_id ) {
			return true;
		}

		$gallery_ids = array_map( 'absint', (array) $product->get_gallery_image_ids() );
		return in_array( $attachment_id, $gallery_ids, true );
	}

	public function get_product_images( WP_REST_Request $request ) {
		try {
			$product_id = absint( $request->get_param( 'product_id' ) );

			$product = wc_get_product( $product_id );
			if ( ! $product ) {
				return $this->error_response(
					'product_not_found',
					__( 'Product not found.', 'ai-product-tools' ),
					404
				);
			}

			$data = $this->service->get_product_images( $product_id );

			return $this->success_response( $data );

		} catch ( \Exception $e ) {
			return $this->error_response(
				'fetch_images_error',
				ErrorHandler::sanitize_error_for_display( $e->getMessage() ),
				500
			);
		}
	}
}
