<?php
/**
 * REST API for AI Alt Text Generator.
 *
 * @package AIAltTextGenerator
 * @since 1.4.0
 */

namespace AIAltTextGenerator;

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

/**
 * @since 1.4.0
 */
class RestController {

	public function register(): void {
		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/scan',
			[
				'methods'             => 'GET',
				'callback'            => [ $this, 'scan' ],
				'permission_callback' => [ $this, 'canView' ],
				'args'                => [
					'refresh' => [
						'type'              => 'boolean',
						'default'           => false,
						'sanitize_callback' => 'rest_sanitize_boolean',
					],
				],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/generate',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'generate' ],
				'permission_callback' => [ $this, 'canGenerate' ],
				'args'                => [
					'attachment_id' => [
						'type'              => 'integer',
						'required'          => true,
						'sanitize_callback' => 'absint',
					],
					'force' => [
						'type'              => 'boolean',
						'default'           => false,
						'sanitize_callback' => 'rest_sanitize_boolean',
					],
				],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/save',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'save' ],
				'permission_callback' => [ $this, 'canGenerate' ],
				'args'                => [
					'attachment_id' => [
						'type'              => 'integer',
						'required'          => true,
						'sanitize_callback' => 'absint',
					],
					'alt_text' => [
						'type'              => 'string',
						'required'          => true,
						'sanitize_callback' => 'sanitize_text_field',
					],
				],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/queue',
			[
				'methods'             => 'GET',
				'callback'            => [ $this, 'queueStatus' ],
				'permission_callback' => [ $this, 'canView' ],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/queue/enqueue',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'enqueue' ],
				'permission_callback' => [ $this, 'canGenerate' ],
				'args'                => [
					'attachment_ids' => [
						'type'     => 'array',
						'required' => true,
						'items'    => [ 'type' => 'integer' ],
					],
				],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/test-connection',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'testConnection' ],
				'permission_callback' => [ $this, 'canManage' ],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/content-scan',
			[
				'methods'             => 'GET',
				'callback'            => [ $this, 'contentScan' ],
				'permission_callback' => [ $this, 'canView' ],
				'args'                => [
					'refresh' => [
						'type'              => 'boolean',
						'default'           => false,
						'sanitize_callback' => 'rest_sanitize_boolean',
					],
				],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/generate/bulk',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'generateBulk' ],
				'permission_callback' => [ $this, 'canGenerate' ],
				'args'                => [
					'attachment_ids' => [
						'type'     => 'array',
						'required' => true,
						'items'    => [ 'type' => 'integer' ],
					],
					'force' => [
						'type'              => 'boolean',
						'default'           => false,
						'sanitize_callback' => 'rest_sanitize_boolean',
					],
					'queue' => [
						'type'              => 'boolean',
						'default'           => false,
						'sanitize_callback' => 'rest_sanitize_boolean',
					],
				],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/content-scan/full',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'startFullContentScan' ],
				'permission_callback' => [ $this, 'canManage' ],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/sync-content',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'syncContent' ],
				'permission_callback' => [ $this, 'canManage' ],
				'args'                => [
					'refresh' => [
						'type'              => 'boolean',
						'default'           => false,
						'sanitize_callback' => 'rest_sanitize_boolean',
					],
				],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/regenerate-duplicates',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'regenerateDuplicates' ],
				'permission_callback' => [ $this, 'canGenerate' ],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/settings',
			[
				'methods'             => 'GET',
				'callback'            => [ $this, 'publicSettings' ],
				'permission_callback' => [ $this, 'canView' ],
			]
		);

		register_rest_route(
			'wp-powersuite/v1',
			'/ai-alt-text/performance',
			[
				'methods'             => 'GET',
				'callback'            => [ $this, 'performance' ],
				'permission_callback' => [ $this, 'canManage' ],
			]
		);
	}

	public function canView(): bool {
		return Capabilities::canView();
	}

	public function canGenerate(): bool {
		return Capabilities::canGenerate();
	}

	public function canManage(): bool {
		return Capabilities::canManage();
	}

	public function scan( \WP_REST_Request $request ): \WP_REST_Response {
		$summary = Scanner::getSummary( (bool) $request->get_param( 'refresh' ) );
		$usage   = Usage::getSummary();

		return new \WP_REST_Response(
			[
				'summary' => $summary,
				'usage'   => $usage,
				'queue'   => Queue::getStatus(),
			]
		);
	}

	public function generate( \WP_REST_Request $request ): \WP_REST_Response {
		$id = (int) $request->get_param( 'attachment_id' );
		if ( ! current_user_can( 'edit_post', $id ) ) {
			return new \WP_REST_Response( [ 'message' => __( 'Permission denied.', 'wppowersuite-lite' ) ], 403 );
		}

		if ( ! Module::checkRateLimit() ) {
			return new \WP_REST_Response( [ 'message' => __( 'Rate limit reached. Please wait a moment.', 'wppowersuite-lite' ) ], 429 );
		}

		$result = GenerationService::generateForAttachment( $id, (bool) $request->get_param( 'force' ) );
		$code   = $result['status'] === 'success' ? 200 : ( $result['status'] === 'skipped' ? 200 : 400 );

		return new \WP_REST_Response( $result, $code );
	}

	public function save( \WP_REST_Request $request ): \WP_REST_Response {
		$id       = (int) $request->get_param( 'attachment_id' );
		$alt_text = (string) $request->get_param( 'alt_text' );

		if ( ! current_user_can( 'edit_post', $id ) ) {
			return new \WP_REST_Response( [ 'message' => __( 'Permission denied.', 'wppowersuite-lite' ) ], 403 );
		}

		AttachmentMeta::saveAltText( $id, $alt_text );
		Scanner::invalidateCache();

		return new \WP_REST_Response( [ 'message' => __( 'Saved.', 'wppowersuite-lite' ) ] );
	}

	public function queueStatus(): \WP_REST_Response {
		return new \WP_REST_Response( Queue::getStatus() );
	}

	public function enqueue( \WP_REST_Request $request ): \WP_REST_Response {
		if ( ! Module::checkRateLimit() ) {
			return new \WP_REST_Response( [ 'message' => __( 'Rate limit reached. Please wait a moment.', 'wppowersuite-lite' ) ], 429 );
		}

		$ids = Module::limitBulkIds( array_map( 'intval', (array) $request->get_param( 'attachment_ids' ) ) );
		$ids = array_values( array_filter( $ids, static fn( $id ) => current_user_can( 'edit_post', $id ) ) );

		if ( $ids === [] ) {
			return new \WP_REST_Response( [ 'message' => __( 'Permission denied.', 'wppowersuite-lite' ) ], 403 );
		}

		$added = Queue::enqueue( $ids );

		return new \WP_REST_Response(
			[
				'added'  => $added,
				'queue'  => Queue::getStatus(),
				'message' => sprintf(
					/* translators: %d: number of images */
					_n( '%d image added to queue.', '%d images added to queue.', $added, 'wppowersuite-lite' ),
					$added
				),
			]
		);
	}

	public function testConnection(): \WP_REST_Response {
		if ( ! Settings::hasApiKey() ) {
			return new \WP_REST_Response( [ 'message' => __( 'API key is missing.', 'wppowersuite-lite' ) ], 400 );
		}

		$result = AltTextGenerator::testConnection();
		if ( is_wp_error( $result ) ) {
			return new \WP_REST_Response( [ 'message' => $result->get_error_message() ], 400 );
		}

		return new \WP_REST_Response( [ 'message' => __( 'API connection successful.', 'wppowersuite-lite' ) ] );
	}

	public function contentScan( \WP_REST_Request $request ): \WP_REST_Response {
		return new \WP_REST_Response( ContentScanner::getSummary( (bool) $request->get_param( 'refresh' ) ) );
	}

	public function generateBulk( \WP_REST_Request $request ): \WP_REST_Response {
		$ids   = Module::limitBulkIds( array_map( 'intval', (array) $request->get_param( 'attachment_ids' ) ) );
		$force = (bool) $request->get_param( 'force' );
		$queue = (bool) $request->get_param( 'queue' );

		if ( $ids === [] ) {
			return new \WP_REST_Response( [ 'message' => __( 'No valid attachment IDs.', 'wppowersuite-lite' ) ], 400 );
		}

		$ids = array_values( array_filter( $ids, static fn( $id ) => current_user_can( 'edit_post', $id ) ) );

		if ( $ids === [] ) {
			return new \WP_REST_Response( [ 'message' => __( 'Permission denied.', 'wppowersuite-lite' ) ], 403 );
		}

		if ( $queue || ( ! empty( Settings::get()['queue_enabled'] ) && count( $ids ) > 5 ) ) {
			$added = Queue::enqueue( $ids, $force );
			return new \WP_REST_Response(
				[
					'queued'  => $added,
					'queue'   => Queue::getStatus(),
					'message' => sprintf(
						/* translators: %d: number of images */
						_n( '%d image queued.', '%d images queued.', $added, 'wppowersuite-lite' ),
						$added
					),
				]
			);
		}

		$settings   = Settings::get();
		$batch_size = Settings::clampBatchSize( (int) ( $settings['batch_size'] ?? 5 ) );
		$results = [];
		foreach ( array_slice( $ids, 0, $batch_size ) as $attachment_id ) {
			if ( ! Module::checkRateLimit() ) {
				break;
			}
			$results[ $attachment_id ] = GenerationService::generateForAttachment( $attachment_id, $force );
		}

		return new \WP_REST_Response(
			[
				'processed' => count( $results ),
				'results'   => $results,
				'remaining' => max( 0, count( $ids ) - count( $results ) ),
			]
		);
	}

	public function startFullContentScan(): \WP_REST_Response {
		$result = ContentScanner::startFullScan();
		$code   = ( $result['status'] ?? '' ) === 'failed' ? 400 : 200;

		return new \WP_REST_Response( $result, $code );
	}

	public function syncContent( \WP_REST_Request $request ): \WP_REST_Response {
		return new \WP_REST_Response( BulkActions::syncLibraryAltToContent( (bool) $request->get_param( 'refresh' ) ) );
	}

	public function regenerateDuplicates(): \WP_REST_Response {
		if ( ! Module::checkRateLimit() ) {
			return new \WP_REST_Response( [ 'message' => __( 'Rate limit reached. Please wait a moment.', 'wppowersuite-lite' ) ], 429 );
		}

		$result = BulkActions::regenerateDuplicates();
		$code   = (int) ( $result['queued'] ?? 0 ) === 0 && str_contains( (string) ( $result['message'] ?? '' ), 'Pro' ) ? 403 : 200;

		return new \WP_REST_Response( $result, $code );
	}

	public function publicSettings(): \WP_REST_Response {
		return new \WP_REST_Response( Settings::getPublic() );
	}

	public function performance(): \WP_REST_Response {
		return new \WP_REST_Response( Performance::getSummary() );
	}
}
