<?php
/**
 * SEO optimization REST controller.
 *
 * @package SmartyPress_AI_Engine
 * @since 1.0.0
 */

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

/**
 * Handles SEO optimization REST requests.
 */
class SmartyPress_AI_SEO_Optimization_Controller {

	const PIPELINE_VERSION   = '1.0';
	const ANALYSIS_VERSION   = '1.1';
	const CONTENT_OP_VERSION = '1.0';
	const CONTEXT_TTL        = 1800;

	/** @var array */
	private $providers;

	/** @var array */
	private $settings;

	/** @var SmartyPress_AI_SEO_Provider_Registry */
	private $registry;

	/** @var SmartyPress_AI_SEO_Fix_Prompt_Builder */
	private $prompt_builder;

	/** @var SmartyPress_AI_SEO_Context_Service */
	private $context_service;

	/** @var SmartyPress_AI_SEO_Local_Pre_Checks */
	private $local_pre_checks;

	/** @var SmartyPress_AI_SEO_AI_JSON_Generator */
	private $json_generator;

	/** @var SmartyPress_AI_SEO_Fix_Pipeline_Runner */
	private $pipeline_runner;

	/** @var SmartyPress_AI_SEO_Result_Normalizer */
	private $result_normalizer;

	/**
	 * Constructor.
	 *
	 * @param array                                      $providers      AI providers.
	 * @param array                                      $settings       Plugin settings.
	 * @param SmartyPress_AI_SEO_Provider_Registry       $registry       SEO provider registry.
	 * @param SmartyPress_AI_SEO_Fix_Prompt_Builder|null $prompt_builder Prompt builder.
	 */
	public function __construct( $providers, $settings, $registry, $prompt_builder = null ) {
		$this->providers      = $providers;
		$this->settings       = is_array( $settings ) ? $settings : array();
		$this->registry       = $registry;
		$this->prompt_builder = $prompt_builder ? $prompt_builder : new SmartyPress_AI_SEO_Fix_Prompt_Builder();

		$strategy_registry        = new SmartyPress_AI_SEO_Content_Strategy_Registry();
		$this->context_service    = new SmartyPress_AI_SEO_Context_Service( self::PIPELINE_VERSION, self::CONTEXT_TTL );
		$this->local_pre_checks   = new SmartyPress_AI_SEO_Local_Pre_Checks( $strategy_registry );
		$this->json_generator     = new SmartyPress_AI_SEO_AI_JSON_Generator( $this->settings, $this->prompt_builder );
		$this->result_normalizer  = new SmartyPress_AI_SEO_Result_Normalizer( self::PIPELINE_VERSION, self::ANALYSIS_VERSION, self::CONTENT_OP_VERSION, $strategy_registry );

		$analysis_service  = new SmartyPress_AI_SEO_Analysis_Service( self::ANALYSIS_VERSION, self::CONTEXT_TTL, $this->prompt_builder, $this->json_generator );
		$meta_step_service = new SmartyPress_AI_SEO_Meta_Step_Service( $this->prompt_builder, $this->json_generator );
		$strategy_runner   = new SmartyPress_AI_SEO_Content_Strategy_Runner( $strategy_registry, $this->prompt_builder, $this->json_generator );

		$this->pipeline_runner = new SmartyPress_AI_SEO_Fix_Pipeline_Runner( $analysis_service, $meta_step_service, $strategy_runner, $this->result_normalizer );
	}

	/**
	 * Register REST routes.
	 *
	 * @return void
	 */
	public function register_routes() {
		register_rest_route(
			'smartypress/v1',
			'/seo-optimization/context',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'create_context' ),
				'permission_callback' => array( $this, 'check_permissions' ),
				'args'                => array(
					'post_id' => array(
						'required'          => true,
						'type'              => 'integer',
						'sanitize_callback' => 'absint',
					),
				),
			)
		);

		register_rest_route(
			'smartypress/v1',
			'/seo-optimization/run',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'run_pipeline' ),
				'permission_callback' => array( $this, 'check_permissions' ),
				'args'                => array(
					'post_id' => array(
						'required'          => true,
						'type'              => 'integer',
						'sanitize_callback' => 'absint',
					),
				),
			)
		);

		register_rest_route(
			'smartypress/v1',
			'/seo-optimization/fix',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'fix' ),
				'permission_callback' => array( $this, 'check_permissions' ),
				'args'                => array(
					'post_id' => array(
						'required'          => true,
						'type'              => 'integer',
						'sanitize_callback' => 'absint',
					),
				),
			)
		);
	}

	/**
	 * Check request permissions.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return bool
	 */
	public function check_permissions( $request ) {
		$post_id = absint( $request->get_param( 'post_id' ) );

		return $post_id > 0 && current_user_can( 'edit_post', $post_id );
	}

	/**
	 * Create and cache a normalized SEO fix context.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response|WP_Error
	 */
	public function create_context( $request ) {
		$params = $this->get_request_params( $request );

		$post_id      = absint( $params['post_id'] ?? 0 );
		$post_type    = sanitize_key( $params['post_type'] ?? get_post_type( $post_id ) );
		$seo_provider = $this->get_seo_provider( $post_type, sanitize_key( $params['provider'] ?? '' ) );

		if ( is_wp_error( $seo_provider ) ) {
			return $seo_provider;
		}

		$payload = $this->context_service->sanitize_payload( $params );
		$payload['failed_tests'] = $seo_provider->normalize_failed_tests( $payload['failed_tests'] );

		$local_checks = $this->local_pre_checks->run( $payload );
		$stored       = $this->context_service->store_context( $post_id, $payload, $local_checks );
		$payload      = $stored['payload'];

		return rest_ensure_response(
			array(
				'success'          => true,
				'pipeline_version' => self::PIPELINE_VERSION,
				'context_id'       => $stored['context_id'],
				'context_hash'     => $payload['context_hash'],
				'stats'            => $this->context_service->get_context_stats( $payload ),
				'local_pre_checks' => $local_checks,
			)
		);
	}

	/**
	 * Run the phase 1 SEO fix pipeline for a cached context.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response|WP_Error
	 */
	public function run_pipeline( $request ) {
		$params = $this->get_request_params( $request );

		$post_id    = absint( $params['post_id'] ?? 0 );
		$context_id = sanitize_text_field( $params['context_id'] ?? '' );
		$context    = $this->context_service->load_context( $post_id, $context_id );

		if ( is_wp_error( $context ) ) {
			return $context;
		}

		$provider = $this->get_ai_provider( sanitize_key( $params['ai_provider'] ?? $params['provider_name'] ?? '' ) );
		if ( ! $provider ) {
			return new WP_Error(
				'smartypress_ai_provider_unavailable',
				__( 'AI provider is not configured.', 'smartypress-ai-engine' ),
				array( 'status' => 400 )
			);
		}

		$language    = $this->get_language( $params );
		$model       = sanitize_text_field( $params['model'] ?? '' );
		$temperature = $this->json_generator->get_json_temperature( $params['temperature'] ?? null );
		$merged      = $this->pipeline_runner->run( $context_id, $context, $provider, $language, $model, $temperature );

		if ( is_wp_error( $merged ) ) {
			return $merged;
		}

		return rest_ensure_response( $merged );
	}

	/**
	 * Generate SEO fixes using the legacy single-call endpoint.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response|WP_Error
	 */
	public function fix( $request ) {
		$params = $this->get_request_params( $request );

		$post_id      = absint( $params['post_id'] ?? 0 );
		$post_type    = sanitize_key( $params['post_type'] ?? get_post_type( $post_id ) );
		$seo_provider = $this->get_seo_provider( $post_type, sanitize_key( $params['provider'] ?? '' ) );

		if ( is_wp_error( $seo_provider ) ) {
			return $seo_provider;
		}

		$provider = $this->get_ai_provider( sanitize_key( $params['ai_provider'] ?? $params['provider_name'] ?? '' ) );
		if ( ! $provider ) {
			return new WP_Error(
				'smartypress_ai_provider_unavailable',
				__( 'AI provider is not configured.', 'smartypress-ai-engine' ),
				array( 'status' => 400 )
			);
		}

		$payload = $this->context_service->sanitize_payload( $params );
		$payload['failed_tests'] = $seo_provider->normalize_failed_tests( $payload['failed_tests'] );

		$language    = $this->get_language( $params );
		$model       = sanitize_text_field( $params['model'] ?? '' );
		$user_prompt = $this->prompt_builder->build_user_prompt( $payload );
		$response    = $this->json_generator->generate_json(
			$provider,
			$user_prompt,
			$language,
			$model,
			$this->json_generator->get_json_temperature( $params['temperature'] ?? null ),
			array(),
			'seo_fix_legacy',
			$params
		);

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		return rest_ensure_response( $this->result_normalizer->normalize_fix_response( $response ) );
	}

	/**
	 * Get request params from JSON or fallback params.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return array
	 */
	private function get_request_params( $request ) {
		$params = $request->get_json_params();

		return is_array( $params ) ? $params : $request->get_params();
	}

	/**
	 * Resolve SEO provider for the current post type.
	 *
	 * @param string $post_type   Post type.
	 * @param string $provider_id Provider ID.
	 * @return object|WP_Error
	 */
	private function get_seo_provider( $post_type, $provider_id = '' ) {
		$seo_provider = $provider_id ? $this->registry->get( $provider_id ) : $this->registry->get_active_provider( $post_type );

		if ( ! $seo_provider || ! $seo_provider->is_available() || ! $seo_provider->supports_post_type( $post_type ) ) {
			return new WP_Error(
				'smartypress_ai_seo_provider_unavailable',
				__( 'SEO provider is not available for this post type.', 'smartypress-ai-engine' ),
				array( 'status' => 400 )
			);
		}

		return $seo_provider;
	}

	/**
	 * Get an AI provider.
	 *
	 * @param string $provider_name Provider name.
	 * @return SmartyPress_AI_AI_Provider|null
	 */
	private function get_ai_provider( $provider_name = '' ) {
		if ( '' === $provider_name ) {
			$provider_name = $this->settings['default_provider'] ?? '';
		}

		if ( class_exists( 'SmartyPress_AI_Providers' ) && '' !== $provider_name ) {
			$provider = SmartyPress_AI_Providers::get_provider( $provider_name );
			if ( $provider ) {
				return $provider;
			}
		}

		if ( '' !== $provider_name && isset( $this->providers[ $provider_name ] ) ) {
			return $this->providers[ $provider_name ];
		}

		if ( class_exists( 'SmartyPress_AI_Providers' ) ) {
			$available = SmartyPress_AI_Providers::get_available_providers();
			if ( ! empty( $available ) ) {
				return reset( $available );
			}
		}

		return null;
	}

	/**
	 * Resolve output language.
	 *
	 * @param array $params Request params.
	 * @return string
	 */
	private function get_language( $params ) {
		$language = sanitize_text_field( $params['language'] ?? ( $this->settings['default_language'] ?? '' ) );
		if ( '' === $language && function_exists( 'smartypress_ai_get_language_by_locale' ) ) {
			$language = smartypress_ai_get_language_by_locale();
		}

		return $language;
	}
}
