<?php
/**
 * AI Hotspot REST API Controller.
 *
 * @package Ugcify\Admin\API
 */

namespace Ugcify\Admin\API;

use Ugcify\AI\AISettings;
use Ugcify\AI\HotspotSuggestionService;
use WP_Error;
use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

/**
 * Class AIHotspotAPI
 */
class AIHotspotAPI extends WP_REST_Controller {
	/**
	 * Namespace.
	 *
	 * @var string
	 */
	protected $namespace = 'ugcify/v1';

	/**
	 * Rest base.
	 *
	 * @var string
	 */
	protected $rest_base = 'ai-hotspots';

	/**
	 * Suggestion service.
	 *
	 * @var HotspotSuggestionService
	 */
	private $service;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->service = new HotspotSuggestionService();
	}

	/**
	 * Register routes.
	 *
	 * @return void
	 */
	public function register_routes() {
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/settings',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_settings' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
				array(
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'update_settings' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/jobs',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_job' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/jobs/(?P<id>[\d]+)',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_job' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/jobs/(?P<id>[\d]+)/run',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'run_job' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/jobs/(?P<id>[\d]+)/approve',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'approve_suggestion' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/jobs/(?P<id>[\d]+)/reject',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'reject_suggestion' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);
	}

	/**
	 * Check permission.
	 *
	 * @return bool|WP_Error
	 */
	public function check_permission() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return new WP_Error(
				'rest_forbidden',
				__( 'Sorry, you are not allowed to access this resource.', 'ugcify' ),
				array( 'status' => 403 )
			);
		}

		return true;
	}

	/**
	 * Get settings.
	 *
	 * @return WP_REST_Response
	 */
	public function get_settings(): WP_REST_Response {
		return new WP_REST_Response(
			array(
				'success' => true,
				'data'    => AISettings::get_public_settings(),
			),
			200
		);
	}

	/**
	 * Update settings.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response
	 */
	public function update_settings( $request ): WP_REST_Response {
		$params = $request->get_json_params();
		$params = is_array( $params ) ? $params : array();

		AISettings::save_from_request( $params );

		return $this->get_settings();
	}

	/**
	 * Create job.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response|WP_Error
	 */
	public function create_job( $request ) {
		$params = $request->get_json_params();
		$params = is_array( $params ) ? $params : array();

		$result = $this->service->create_job(
			isset( $params['review_id'] ) ? absint( $params['review_id'] ) : 0,
			isset( $params['media_index'] ) ? max( 0, (int) $params['media_index'] ) : 0,
			isset( $params['image_url'] ) ? esc_url_raw( (string) $params['image_url'] ) : '',
			isset( $params['attachment_id'] ) ? absint( $params['attachment_id'] ) : 0
		);

		if ( is_wp_error( $result ) ) {
			return $this->to_rest_error( $result );
		}

		return $this->success_response( $result, 201 );
	}

	/**
	 * Get job.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response|WP_Error
	 */
	public function get_job( $request ) {
		require_once UGCIFY_PATH . 'includes/AI/AIJobRepository.php';
		$repo = new \Ugcify\AI\AIJobRepository();
		$job  = $repo->find( absint( $request->get_param( 'id' ) ) );

		if ( ! $job ) {
			return new WP_Error( 'job_not_found', __( 'AI hotspot job not found.', 'ugcify' ), array( 'status' => 404 ) );
		}

		return $this->success_response( $job, 200 );
	}

	/**
	 * Run job.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response|WP_Error
	 */
	public function run_job( $request ) {
		$result = $this->service->run_job( absint( $request->get_param( 'id' ) ) );
		if ( is_wp_error( $result ) ) {
			return $this->to_rest_error( $result );
		}

		return $this->success_response( $result, 200 );
	}

	/**
	 * Approve suggestion.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response|WP_Error
	 */
	public function approve_suggestion( $request ) {
		$params = $request->get_json_params();
		$params = is_array( $params ) ? $params : array();

		$result = $this->service->approve_suggestion(
			absint( $request->get_param( 'id' ) ),
			isset( $params['suggestion_index'] ) ? max( 0, (int) $params['suggestion_index'] ) : 0,
			isset( $params['edits'] ) && is_array( $params['edits'] ) ? $params['edits'] : array()
		);

		if ( is_wp_error( $result ) ) {
			return $this->to_rest_error( $result );
		}

		return $this->success_response( $result, 201 );
	}

	/**
	 * Reject suggestion.
	 *
	 * @param WP_REST_Request $request Request.
	 * @return WP_REST_Response|WP_Error
	 */
	public function reject_suggestion( $request ) {
		$params = $request->get_json_params();
		$params = is_array( $params ) ? $params : array();

		$result = $this->service->reject_suggestion(
			absint( $request->get_param( 'id' ) ),
			isset( $params['suggestion_index'] ) ? max( 0, (int) $params['suggestion_index'] ) : 0
		);

		if ( is_wp_error( $result ) ) {
			return $this->to_rest_error( $result );
		}

		return $this->success_response( $result, 200 );
	}

	/**
	 * Build success response.
	 *
	 * @param mixed $data Data.
	 * @param int   $status Status.
	 * @return WP_REST_Response
	 */
	private function success_response( $data, int $status ): WP_REST_Response {
		return new WP_REST_Response(
			array(
				'success' => true,
				'data'    => $data,
			),
			$status
		);
	}

	/**
	 * Convert WP_Error to REST error.
	 *
	 * @param WP_Error $error Error.
	 * @return WP_Error
	 */
	private function to_rest_error( WP_Error $error ): WP_Error {
		$data   = $error->get_error_data();
		$status = is_array( $data ) && isset( $data['status'] ) ? (int) $data['status'] : 400;

		return new WP_Error(
			$error->get_error_code(),
			$error->get_error_message(),
			array( 'status' => $status )
		);
	}
}
