<?php
/**
 * Chat AJAX Handler
 * Handles secure AJAX communication for chat functionality
 *
 * @package AgenticWP
 */

namespace Agentic_WP;

defined( 'ABSPATH' ) || exit;

use Agentic_WP\Error_Handler;

/**
 * AJAX handler for chat interface.
 *
 * Handles secure AJAX communication for chat functionality.
 *
 * @since 1.0.0
 */
class Chat_Ajax {

	/**
	 * OpenAI client instance for API communication.
	 *
	 * @since 1.0.0
	 *
	 * @var OpenAI_Client
	 */
	private $openai_client;

	/**
	 * Registers AJAX hooks.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		$this->openai_client = new OpenAI_Client();

		add_action( 'wp_ajax_agenticwp_send_message', array( $this, 'handle_send_message' ) );
		add_action( 'wp_ajax_agenticwp_check_api_key', array( $this, 'handle_check_api_key' ) );
		add_action( 'wp_ajax_agenticwp_get_actions', array( $this, 'handle_get_actions' ) );
	}

	/**
	 * Processes chat messages and streams responses.
	 *
	 * @since 1.0.0
	 *
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_send_message(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_request().
		try {
			if ( ! $this->verify_request() ) {
				wp_send_json_error( array( 'message' => __( 'Security check failed.', 'agenticwp' ) ), 403 );
			}

			// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_request().
			// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized in sanitize_message_input() method.
			$message = $this->sanitize_message_input( wp_unslash( $_POST['message'] ?? '' ) );
			// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			if ( empty( $message ) ) {
				wp_send_json_error( array( 'message' => __( 'Message cannot be empty.', 'agenticwp' ) ), 400 );
			}

			if ( ! class_exists( __NAMESPACE__ . '\\Agents' ) ) {
				require_once plugin_dir_path( __DIR__ ) . 'includes/class-agents.php';
			}

			$tools = Agents::get_main_agent_tools();

			$params = array(
				'input'        => array(
					array(
						'role'    => 'user',
						'content' => $message,
					),
				),
				'tools'        => $tools,
				'instructions' => Agents::get_main_instructions(),
			);

			$conversation_id = sanitize_text_field( wp_unslash( $_POST['conversation_id'] ?? '' ) );
			// phpcs:enable WordPress.Security.NonceVerification.Missing
			if ( ! empty( $conversation_id ) ) {
				$params['previous_response_id'] = $conversation_id;
			}

			$result = $this->openai_client->create_response( $params );

			if ( is_wp_error( $result ) ) {
				Error_Handler::log_error(
					'chat_ajax',
					$result,
					array( 'conversation_id' => $conversation_id )
				);

				wp_send_json_error(
					array(
						'message' => $result->get_error_message(),
						'code'    => $result->get_error_code(),
					),
					500
				);
			}

			wp_send_json_success(
				array(
					'message'         => $result['output_text'] ?? __( 'Sorry, I could not generate a response.', 'agenticwp' ),
					'reasoning'       => $result['reasoning_summary'] ?? '',
					'conversation_id' => $result['id'] ?? null,
				)
			);
		} catch ( \Throwable $e ) {
			Error_Handler::log_error(
				'chat_ajax',
				$e->getMessage(),
				array(
					'trace' => $e->getTraceAsString(),
				)
			);
			wp_send_json_error(
				array(
					'message' => __( 'An unexpected error occurred.', 'agenticwp' ),
				),
				500
			);
		}
	}

	/**
	 * Retrieves available actions list.
	 *
	 * @since 1.0.0
	 *
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_get_actions(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_request().
		try {
			if ( ! $this->verify_request( false ) ) {
				wp_send_json_error( array( 'message' => __( 'Security check failed.', 'agenticwp' ) ), 403 );
			}

			$action_manager = new Action_Manager();
			$actions        = $action_manager->get_actions();

			$formatted_actions = array();
			foreach ( $actions as $category_key => $category_actions ) {
				foreach ( $category_actions as $action_key => $action_data ) {
					$formatted_actions[ $action_key ] = array(
						'name'         => $action_data['name'] ?? '',
						'prompt'       => $action_data['prompt'] ?? '',
						'category_key' => $category_key,
						'category'     => $action_data['category'] ?? ucfirst( str_replace( '_', ' ', $category_key ) ),
						'icon'         => $action_data['icon'] ?? 'admin-generic',
						'description'  => $action_data['description'] ?? '',
						'is_custom'    => array_key_exists( 'is_custom', $action_data ) ? (bool) $action_data['is_custom'] : ( 'custom' === $category_key ),
					);
				}
			}

			wp_send_json_success(
				array(
					'actions' => $formatted_actions,
				)
			);
		} catch ( \Throwable $e ) {
			Error_Handler::log_error(
				'chat_ajax',
				$e->getMessage(),
				array(
					'context' => 'get_actions',
					'trace'   => $e->getTraceAsString(),
				)
			);
			wp_send_json_error(
				array(
					'message' => __( 'Failed to load actions.', 'agenticwp' ),
				),
				500
			);
		}
	}

	/**
	 * Validates nonce and API key.
	 *
	 * @since 1.0.0
	 *
	 * @param bool $check_api_key Whether to verify API key presence.
	 *
	 * @return bool True if request is valid, false otherwise.
	 */
	private function verify_request( bool $check_api_key = true ): bool {
		$nonce_value = sanitize_text_field( wp_unslash( $_POST['_ajax_nonce'] ?? '' ) );

		if ( ! wp_verify_nonce( $nonce_value, 'agenticwp_chat_nonce' ) ) {
			return false;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		if ( $check_api_key && empty( Settings::get_api_key() ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Validates API key status.
	 *
	 * @since 1.0.0
	 *
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_check_api_key(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in verify_request().
		if ( ! $this->verify_request( false ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'agenticwp' ) ), 403 );
		}

		$api_key     = Settings::get_api_key();
		$has_api_key = ! empty( $api_key );

		wp_send_json_success(
			array(
				'has_api_key' => $has_api_key,
				'message'     => $has_api_key
					? __( 'API key is configured.', 'agenticwp' )
					: __( 'Please configure your OpenAI API key.', 'agenticwp' ),
			)
		);
	}

	/**
	 * Sanitizes user message input.
	 *
	 * @since 1.0.0
	 *
	 * @param string $message User message to sanitize.
	 *
	 * @return string Sanitized message or empty string if invalid.
	 */
	private function sanitize_message_input( string $message ): string {
		$message = sanitize_textarea_field( $message );

		if ( strlen( $message ) > 1000 ) {
			return '';
		}

		return trim( $message );
	}
}
