<?php
/**
 * Project Synapse AJAX controller.
 *
 * @package Noesia_Smart_Waiter
 */

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

if ( ! class_exists( 'Noesia_SWA_Project_Synapse_Ajax' ) ) {
	/**
	 * AJAX owner for Project Synapse.
	 */
	class Noesia_SWA_Project_Synapse_Ajax {

		/**
		 * Service.
		 *
		 * @var Noesia_SWA_Project_Synapse_Service
		 */
		private $service;

		/**
		 * Constructor.
		 *
		 * @param Noesia_SWA_Project_Synapse_Service $service Service.
		 */
		public function __construct( Noesia_SWA_Project_Synapse_Service $service ) {
			$this->service = $service;
		}

		/**
		 * Register hooks.
		 *
		 * @return void
		 */
		public function register_hooks() {
			add_action( 'wp_ajax_noesia_swa_project_synapse_install_pack', array( $this, 'handle_install_pack' ) );
			add_action( 'wp_ajax_noesia_swa_project_synapse_save_settings', array( $this, 'handle_save_settings' ) );
			add_action( 'wp_ajax_noesia_swa_project_synapse_ask', array( $this, 'handle_ask' ) );
		}

		/**
		 * Verify request.
		 *
		 * @return void
		 */
		private function verify_request() {
			if ( ! check_ajax_referer( 'noesia_swa_nonce', 'nonce', false ) ) {
				wp_send_json_error(
					array(
						'message' => __( 'Security check failed. Reload the Noesia admin page and try again.', 'noesia-smart-waiter' ),
					),
					403
				);
			}

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error(
					array(
						'message' => __( 'Unauthorized request.', 'noesia-smart-waiter' ),
					),
					403
				);
			}
		}

		/**
		 * Handle knowledge pack install.
		 *
		 * @return void
		 */
		public function handle_install_pack() {
			$this->verify_request();

			$status = $this->service->install_pack();

			if ( is_wp_error( $status ) ) {
				wp_send_json_error(
					array(
						'message' => $status->get_error_message(),
					),
					400
				);
			}

			wp_send_json_success(
				array(
					'status'  => $status,
					'message' => __( 'Project Synapse knowledge pack installed.', 'noesia-smart-waiter' ),
				)
			);
		}

		/**
		 * Handle Synapse settings save.
		 *
		 * @return void
		 */
		public function handle_save_settings() {
			$this->verify_request();

			$api_key = $this->get_posted_text( 'api_key' );
			$model   = $this->get_posted_text( 'model' );
			$result  = $this->service->save_settings( $api_key, $model );

			if ( is_wp_error( $result ) ) {
				wp_send_json_error(
					array(
						'message' => $result->get_error_message(),
					),
					400
				);
			}

			wp_send_json_success(
				array(
					'settings' => $result,
					'message'  => __( 'Project Synapse settings saved.', 'noesia-smart-waiter' ),
				)
			);
		}

		/**
		 * Handle Synapse ask request.
		 *
		 * @return void
		 */
		public function handle_ask() {
			$this->verify_request();

			$question = $this->get_posted_textarea( 'question' );
			$mode     = $this->get_posted_text( 'mode' );
			$scene    = $this->get_posted_text( 'scene' );
			$history  = $this->get_posted_json( 'history' );
			$answer   = $this->service->answer_question( $question, $mode, $scene, $history );

			if ( is_wp_error( $answer ) ) {
				wp_send_json_error(
					array(
						'message' => $answer->get_error_message(),
					),
					400
				);
			}

			wp_send_json_success( $answer );
		}

		/**
		 * Get posted text.
		 *
		 * @param string $key Field key.
		 * @return string
		 */
		private function get_posted_text( $key ) {
			$key = sanitize_key( (string) $key );

			if ( '' === $key ) {
				return '';
			}

			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce is verified before this helper is used.
			if ( ! isset( $_POST[ $key ] ) ) {
				return '';
			}

			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce is verified before this helper is used.
			return sanitize_text_field( wp_unslash( (string) $_POST[ $key ] ) );
		}

		/**
		 * Get posted textarea.
		 *
		 * @param string $key Field key.
		 * @return string
		 */
		private function get_posted_textarea( $key ) {
			$key = sanitize_key( (string) $key );

			if ( '' === $key ) {
				return '';
			}

			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce is verified before this helper is used.
			if ( ! isset( $_POST[ $key ] ) ) {
				return '';
			}

			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce is verified before this helper is used.
			return sanitize_textarea_field( wp_unslash( (string) $_POST[ $key ] ) );
		}

		/**
		 * Get posted JSON array.
		 *
		 * @param string $key Field key.
		 * @return array<int,array<string,string>>
		 */
		private function get_posted_json( $key ) {
			$key = sanitize_key( (string) $key );

			if ( '' === $key ) {
				return array();
			}

			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce is verified before this helper is used.
			if ( ! isset( $_POST[ $key ] ) ) {
				return array();
			}

			// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- AJAX nonce is verified and the dynamic key is sanitized before this helper is used. JSON is normalized after decoding.
			$raw     = wp_unslash( (string) $_POST[ $key ] );
			$decoded = json_decode( $raw, true );

			return is_array( $decoded ) ? $decoded : array();
		}
	}
}
