<?php
/**
 * API settings class for AgenticWP plugin.
 *
 * @package AgenticWP
 */

namespace Agentic_WP;

defined( 'ABSPATH' ) || exit;

use Agentic_WP\Error_Handler;

/**
 * Handles OpenAI API configuration settings.
 */
class Settings_API extends Settings_Base {

	/**
	 * Registers settings API hooks.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		add_action( 'wp_ajax_agenticwp_delete_api_key', array( $this, 'handle_delete_api_key' ) );
		add_action( 'wp_ajax_agenticwp_save_model_selection', array( $this, 'handle_ajax_save_model' ) );
		add_action( 'wp_ajax_agenticwp_save_reasoning_effort', array( $this, 'handle_ajax_save_reasoning_effort' ) );
		add_action( 'wp_ajax_agenticwp_save_max_output_tokens', array( $this, 'handle_ajax_save_max_output_tokens' ) );
		add_action( 'wp_ajax_agenticwp_save_toast_notifications', array( $this, 'handle_ajax_save_toast_notifications' ) );
		add_action( 'wp_ajax_agenticwp_save_web_search', array( $this, 'handle_ajax_save_web_search' ) );
	}

	/**
	 * Registers API settings fields.
	 *
	 * @since 1.0.0
	 */
	public function register_settings(): void {
		register_setting(
			'agentic_wp',
			'agentic_wp_openai_key',
			array(
				'sanitize_callback' => array( $this, 'sanitize_api_key' ),
			)
		);
		register_setting(
			'agentic_wp',
			'agentic_wp_model',
			array(
				'type'              => 'string',
				'sanitize_callback' => array( $this, 'sanitize_model' ),
				'default'           => 'gpt-5-mini',
			)
		);
		register_setting(
			'agentic_wp',
			'agentic_wp_reasoning_effort',
			array(
				'type'              => 'string',
				'sanitize_callback' => array( $this, 'sanitize_reasoning_effort' ),
				'default'           => 'medium',
			)
		);
		register_setting(
			'agentic_wp',
			'agentic_wp_enable_toast_notifications',
			array(
				'type'              => 'boolean',
				'sanitize_callback' => array( $this, 'sanitize_checkbox' ),
				'default'           => true,
			)
		);
		register_setting(
			'agentic_wp',
			'agentic_wp_max_output_tokens',
			array(
				'type'              => 'integer',
				'sanitize_callback' => array( $this, 'sanitize_max_output_tokens' ),
				'default'           => 32000,
			)
		);
		register_setting(
			'agentic_wp',
			'agentic_wp_enable_web_search',
			array(
				'type'              => 'boolean',
				'sanitize_callback' => array( $this, 'sanitize_checkbox' ),
				'default'           => false,
			)
		);
	}

	/**
	 * Add API-related settings fields.
	 *
	 * @param string $section_id The settings section ID.
	 */
	public function add_settings_fields( string $section_id ): void {
		add_settings_field(
			'openai_api_key',
			'OpenAI API Key',
			array( $this, 'api_key_field' ),
			'agentic_wp',
			$section_id
		);

		add_settings_field(
			'openai_model',
			'Model',
			array( $this, 'model_field' ),
			'agentic_wp',
			$section_id
		);

		add_settings_field(
			'reasoning_effort',
			'Reasoning Effort',
			array( $this, 'reasoning_effort_field' ),
			'agentic_wp',
			$section_id
		);

		add_settings_field(
			'max_output_tokens',
			'Response Length Limit',
			array( $this, 'max_output_tokens_field' ),
			'agentic_wp',
			$section_id
		);

		add_settings_field(
			'enable_toast_notifications',
			'Task Completion Alerts',
			array( $this, 'toast_notifications_field' ),
			'agentic_wp',
			$section_id
		);

		add_settings_field(
			'enable_web_search',
			'Web Search Access',
			array( $this, 'web_search_field' ),
			'agentic_wp',
			$section_id
		);
	}

	/**
	 * Sanitize model selection setting.
	 *
	 * @param string $input The submitted model value.
	 * @return string The sanitized model value.
	 */
	public function sanitize_model( $input ) {
		$valid_models = array( 'gpt-5.2', 'gpt-5-mini' );
		if ( ! in_array( $input, $valid_models, true ) ) {
			return 'gpt-5-mini';
		}
		return sanitize_text_field( $input );
	}

	/**
	 * Sanitize reasoning effort setting.
	 *
	 * @param string $input The submitted reasoning effort value.
	 * @return string The sanitized reasoning effort value.
	 */
	public function sanitize_reasoning_effort( $input ) {
		$valid_efforts = array( 'minimal', 'low', 'medium', 'high' );
		if ( ! in_array( $input, $valid_efforts, true ) ) {
			return 'medium';
		}
		return sanitize_text_field( $input );
	}

	/**
	 * Sanitize API key setting - preserves existing key if no new value provided.
	 *
	 * @param string $input The submitted API key value.
	 * @return string The sanitized API key value.
	 */
	public function sanitize_api_key( $input ) {
		if ( empty( $input ) ) {
			return get_option( 'agentic_wp_openai_key' );
		}
		return sanitize_text_field( $input );
	}

	/**
	 * Sanitize max output tokens value with range validation.
	 *
	 * @param mixed $input The max output tokens input value.
	 * @return int The sanitized value within the allowed range.
	 */
	public function sanitize_max_output_tokens( $input ) {
		$value = intval( $input );

		if ( $value < 1024 ) {
			$value = 1024;
		} elseif ( $value > 128000 ) {
			$value = 128000;
		}

		return $value;
	}

	/**
	 * Renders API key field.
	 *
	 * @since 1.0.0
	 */
	public function api_key_field() {
		$value   = get_option( 'agentic_wp_openai_key' );
		$has_key = ! empty( $value );

		// Define tooltip content.
		$tooltip_content  = '<p><strong>' . esc_html__( 'What is an API Key?', 'agenticwp' ) . '</strong></p>';
		$tooltip_content .= '<p>' . esc_html__( 'An API key is a unique authentication token that allows AgenticWP to securely communicate with OpenAI\'s servers. Think of it like a password that identifies your account and enables the AI features.', 'agenticwp' ) . '</p>';
		$tooltip_content .= '<p><strong>' . esc_html__( 'Why do I need one?', 'agenticwp' ) . '</strong></p>';
		$tooltip_content .= '<ul>';
		$tooltip_content .= '<li>' . esc_html__( 'Required to access OpenAI\'s AI models', 'agenticwp' ) . '</li>';
		$tooltip_content .= '<li>' . esc_html__( 'Links your usage to your OpenAI billing account', 'agenticwp' ) . '</li>';
		$tooltip_content .= '<li>' . esc_html__( 'Keeps your AI assistant secure and private', 'agenticwp' ) . '</li>';
		$tooltip_content .= '</ul>';
		$tooltip_content .= '<p><a href="' . esc_url( 'https://platform.openai.com/api-keys' ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Get your API key from OpenAI →', 'agenticwp' ) . '</a></p>';

		// Define field renderer.
		$render_field = function () use ( $has_key, $value ) {
			echo '<div class="agenticwp-api-key-section">';

			if ( $has_key ) {
				echo '<div class="agenticwp-api-key-status">';
				echo '<span class="agenticwp-key-saved">' . esc_html__( '✓ Connected to OpenAI', 'agenticwp' ) . '</span>';
				echo '<button type="button" class="button button-danger agenticwp-delete-key" data-nonce="' . esc_attr( wp_create_nonce( 'agenticwp_delete_key' ) ) . '">';
				echo '<span class="dashicons dashicons-trash"></span>';
				echo esc_html__( 'Delete Key', 'agenticwp' );
				echo '</button>';
				echo '</div>';
				echo '<p class="description">' . esc_html__( 'Your secure connection key from OpenAI is ready to use. Click "Delete Key" to enter a new one.', 'agenticwp' ) . '</p>';
			} else {
				echo '<label for="agentic_wp_openai_key">' . esc_html__( 'OpenAI API Key', 'agenticwp' ) . '</label>';
				echo '<input type="password" name="agentic_wp_openai_key" id="agentic_wp_openai_key" value="" class="regular-text" placeholder="sk-..." />';
				echo '<p class="description">';
				echo esc_html__( 'Your secure connection key from OpenAI. ', 'agenticwp' );
				echo '<a href="' . esc_url( 'https://platform.openai.com/api-keys' ) . '" target="_blank" rel="noopener noreferrer">';
				echo esc_html__( 'Get your free API key', 'agenticwp' );
				echo '</a>';
				echo '</p>';
			}

			echo '</div>';
		};

		// Render field with tooltip.
		$this->render_field_with_tooltip(
			$render_field,
			$tooltip_content,
			'api-key',
			array(
				'label_text' => __( 'Connect your OpenAI account to enable AI-powered features', 'agenticwp' ),
			)
		);
	}

	/**
	 * Renders model selection field.
	 *
	 * @since 1.0.0
	 */
	public function model_field() {
		$current_model = get_option( 'agentic_wp_model', 'gpt-5-mini' );
		$models        = array(
			'gpt-5.2'    => array(
				'name'        => 'GPT-5.2',
				'description' => 'Latest AI - Most advanced capabilities and reasoning',
				'badge'       => 'Latest',
			),
			'gpt-5-mini' => array(
				'name'        => 'GPT-5 Mini',
				'description' => 'Standard AI - Great for most writing tasks and faster responses',
				'badge'       => 'Standard',
			),
		);

		if ( ! array_key_exists( $current_model, $models ) ) {
			$current_model = 'gpt-5-mini';
		}

		// Define tooltip content.
		$tooltip_content  = '<p><strong>Cost Comparison:</strong></p>';
		$tooltip_content .= '<ul>';
		$tooltip_content .= '<li><strong>GPT-5 Mini</strong> - Much cheaper and faster. Best for blog posts, product descriptions, and routine content.</li>';
		$tooltip_content .= '<li><strong>GPT-5.1</strong> - Premium pricing. Use for in-depth articles, complex analysis, or when quality is critical.</li>';
		$tooltip_content .= '<li><strong>GPT-5.2</strong> - Latest model with most advanced reasoning. Higher cost but best results for complex tasks.</li>';
		$tooltip_content .= '</ul>';
		$tooltip_content .= '<p>Choose Mini to save costs on everyday tasks, or GPT-5.2 for the most demanding work.</p>';
		$tooltip_content .= '<p><a href="https://platform.openai.com/docs/models" target="_blank" rel="noopener noreferrer">View Model Details →</a></p>';

		// Define field rendering callback.
		$render_field = function () use ( $models, $current_model ) {
			echo '<div class="agenticwp-model-selection">';
			echo '<div class="agenticwp-model-cards">';

			foreach ( $models as $value => $model_info ) {
				$is_selected = ( $current_model === $value );
				$card_class  = 'agenticwp-model-card' . ( $is_selected ? ' selected' : '' );

				printf(
					'<div class="%s">',
					esc_attr( $card_class )
				);

				printf( '<span class="agenticwp-model-card-badge">%s</span>', esc_html( $model_info['badge'] ) );

				echo '<div class="agenticwp-model-card-header">';
				printf(
					'<input type="radio" name="agentic_wp_model" value="%s" id="model_%s"%s>',
					esc_attr( $value ),
					esc_attr( $value ),
					checked( $current_model, $value, false )
				);
				printf(
					'<h4 class="agenticwp-model-card-title">%s</h4>',
					esc_html( $model_info['name'] )
				);
				echo '</div>';

				printf(
					'<p class="agenticwp-model-card-description">%s</p>',
					esc_html( $model_info['description'] )
				);

				echo '</div>';
			}

			echo '</div>';
			echo '</div>';
		};

		// Render field with tooltip.
		$this->render_field_with_tooltip(
			$render_field,
			$tooltip_content,
			'model-selection',
			array(
				'label_text' => "Select your AI assistant's intelligence level",
			)
		);
	}

	/**
	 * Renders reasoning effort field.
	 *
	 * @since 1.0.0
	 */
	public function reasoning_effort_field() {
		$current_effort = get_option( 'agentic_wp_reasoning_effort', 'medium' );
		$efforts        = array(
			'minimal' => 'Minimal',
			'low'     => 'Low',
			'medium'  => 'Medium',
			'high'    => 'High',
		);

		echo '<select name="agentic_wp_reasoning_effort" class="regular-text">';
		foreach ( $efforts as $value => $label ) {
			printf(
				'<option value="%s"%s>%s</option>',
				esc_attr( $value ),
				selected( $current_effort, $value, false ),
				esc_html( $label )
			);
		}
		echo '</select>';
		echo '<p class="description">Higher reasoning effort provides more thoughtful analysis but takes longer and costs more</p>';
	}

	/**
	 * Renders reasoning effort tooltip content.
	 *
	 * @since 1.0.0
	 */
	public function reasoning_effort_tooltip() {
		// Define tooltip content.
		$tooltip_content  = '<p><strong>' . esc_html__( 'Performance vs. Quality Trade-offs:', 'agenticwp' ) . '</strong></p>';
		$tooltip_content .= '<ul>';
		$tooltip_content .= '<li><strong>' . esc_html__( 'Minimal/Low', 'agenticwp' ) . '</strong> - ' . esc_html__( 'Faster responses with lower token usage. Best for simple queries or when speed matters more than depth.', 'agenticwp' ) . '</li>';
		$tooltip_content .= '<li><strong>' . esc_html__( 'Medium', 'agenticwp' ) . '</strong> - ' . esc_html__( 'Balanced approach. Good for most use cases with reasonable response times and quality.', 'agenticwp' ) . '</li>';
		$tooltip_content .= '<li><strong>' . esc_html__( 'High', 'agenticwp' ) . '</strong> - ' . esc_html__( 'Most thorough analysis with deeper reasoning. Slower responses and increased costs. Recommended for complex content requiring nuanced understanding.', 'agenticwp' ) . '</li>';
		$tooltip_content .= '</ul>';
		$tooltip_content .= '<p>' . esc_html__( 'Higher reasoning effort can increase response time by 2-3x and token costs by up to 50%. Choose based on your content complexity and budget.', 'agenticwp' ) . '</p>';

		// Render tooltip content.
		printf(
			'<div id="reasoning-effort-tooltip" class="agenticwp-tooltip" role="tooltip" hidden>%s</div>',
			wp_kses_post( $tooltip_content )
		);
	}

	/**
	 * Renders max output tokens tooltip content.
	 *
	 * @since 1.0.0
	 */
	public function max_output_tokens_tooltip() {
		// Define tooltip content.
		$tooltip_content  = '<p><strong>' . esc_html__( 'What are tokens?', 'agenticwp' ) . '</strong> ';
		$tooltip_content .= esc_html__( 'Think of them as word-chunks. On average, 1 token ≈ 0.75 words, so 1,000 tokens ≈ 750 words.', 'agenticwp' ) . '</p>';
		$tooltip_content .= '<p><strong>' . esc_html__( 'Examples:', 'agenticwp' ) . '</strong></p>';
		$tooltip_content .= '<ul>';
		$tooltip_content .= '<li><strong>' . esc_html__( '1,024 tokens', 'agenticwp' ) . '</strong> ' . esc_html__( '(~768 words) - Short blog post or product description', 'agenticwp' ) . '</li>';
		$tooltip_content .= '<li><strong>' . esc_html__( '8,000 tokens', 'agenticwp' ) . '</strong> ' . esc_html__( '(~6,000 words) - Medium article with details', 'agenticwp' ) . '</li>';
		$tooltip_content .= '<li><strong>' . esc_html__( '32,000 tokens', 'agenticwp' ) . '</strong> ' . esc_html__( '(~24,000 words) - Long-form comprehensive content', 'agenticwp' ) . '</li>';
		$tooltip_content .= '</ul>';
		$tooltip_content .= '<p>' . esc_html__( 'Higher limits allow longer responses but increase your OpenAI costs. Set based on your typical content length needs.', 'agenticwp' ) . '</p>';

		// Render tooltip content.
		printf(
			'<div id="max-output-tokens-tooltip" class="agenticwp-tooltip" role="tooltip" hidden>%s</div>',
			wp_kses_post( $tooltip_content )
		);
	}

	/**
	 * Renders max output tokens field.
	 *
	 * @since 1.0.0
	 */
	public function max_output_tokens_field() {
		$value = get_option( 'agentic_wp_max_output_tokens', 32000 );

		// Render field.
		echo '<input type="number" name="agentic_wp_max_output_tokens" value="' . esc_attr( $value ) . '" class="regular-text" min="1024" max="128000" step="256" />';
		echo '<p class="description">' . esc_html__( 'Controls how much content the AI can write in one response. More words means higher cost but more comprehensive content.', 'agenticwp' ) . '</p>';
	}


	/**
	 * Renders toast notifications toggle field.
	 *
	 * @since 1.0.0
	 */
	public function toast_notifications_field() {
		$value = get_option( 'agentic_wp_enable_toast_notifications', true );
		?>
		<div class="agenticwp-checkbox-field">
			<input type="checkbox" id="agentic_wp_enable_toast_notifications" name="agentic_wp_enable_toast_notifications" value="1" <?php checked( 1, $value ); ?> />
			<div class="agenticwp-checkbox-field-content">
				<label for="agentic_wp_enable_toast_notifications"><?php echo esc_html__( 'Task Completion Alerts', 'agenticwp' ); ?></label>
				<p class="description"><?php echo esc_html__( 'Show small popup notifications when background tasks finish. Appears on any admin page where the chat is available.', 'agenticwp' ); ?></p>
			</div>
		</div>
		<?php
	}

	/**
	 * Handles AJAX request for deleting API key.
	 *
	 * @since 1.0.0
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_delete_api_key() {
		$this->verify_ajax_request( 'agenticwp_delete_key' );

		delete_option( 'agentic_wp_openai_key' );

		wp_send_json_success(
			array(
				'message' => __( 'API key deleted successfully.', 'agenticwp' ),
				'html'    => $this->get_api_key_input_html(),
			)
		);
	}

	/**
	 * Handles AJAX request for saving model selection.
	 *
	 * @since 1.0.0
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_ajax_save_model() {
		$this->verify_ajax_request( 'agenticwp_save_model' );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified via verify_ajax_request() above.
		$model = sanitize_text_field( wp_unslash( $_POST['model'] ?? '' ) );
		if ( empty( $model ) ) {
			Error_Handler::log_error(
				'validation',
				'Model selection validation failed',
				array( 'context' => 'ajax_save_model' )
			);
			wp_send_json_error( array( 'message' => __( 'Model selection is required.', 'agenticwp' ) ), 400 );
		}

		update_option( 'agentic_wp_model', $model );

		wp_send_json_success(
			array(
				'message' => __( 'Model updated successfully.', 'agenticwp' ),
				'model'   => $model,
			)
		);
	}

	/**
	 * Handles AJAX request for saving reasoning effort.
	 *
	 * @since 1.0.0
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_ajax_save_reasoning_effort() {
		$this->verify_ajax_request( 'agenticwp_save_reasoning_effort' );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified via verify_ajax_request() above.
		$effort = sanitize_text_field( wp_unslash( $_POST['value'] ?? '' ) );
		if ( empty( $effort ) ) {
			Error_Handler::log_error(
				'validation',
				'Reasoning effort validation failed: empty value',
				array( 'context' => 'ajax_save_reasoning_effort' )
			);
			wp_send_json_error( array( 'message' => __( 'Reasoning effort is required.', 'agenticwp' ) ), 400 );
		}

		$valid_efforts = array( 'minimal', 'low', 'medium', 'high' );
		if ( ! in_array( $effort, $valid_efforts, true ) ) {
			Error_Handler::log_error(
				'validation',
				'Invalid reasoning effort value',
				array(
					'value'   => $effort,
					'context' => 'ajax_save_reasoning_effort',
				)
			);
			wp_send_json_error( array( 'message' => __( 'Invalid reasoning effort value.', 'agenticwp' ) ), 400 );
		}

		update_option( 'agentic_wp_reasoning_effort', $effort );

		wp_send_json_success(
			array(
				'message' => __( 'Reasoning effort updated successfully.', 'agenticwp' ),
				'value'   => $effort,
			)
		);
	}

	/**
	 * Handles AJAX request for saving max output tokens.
	 *
	 * @since 1.0.0
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_ajax_save_max_output_tokens() {
		$this->verify_ajax_request( 'agenticwp_save_max_output_tokens' );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified via verify_ajax_request() above.
		$tokens = intval( $_POST['value'] ?? 0 );
		if ( $tokens <= 0 ) {
			Error_Handler::log_error(
				'validation',
				'Max output tokens validation failed',
				array(
					'value'   => $tokens,
					'context' => 'ajax_save_max_output_tokens',
				)
			);
			wp_send_json_error( array( 'message' => __( 'Max output tokens is required.', 'agenticwp' ) ), 400 );
		}

		$sanitized_tokens = $this->sanitize_max_output_tokens( $tokens );

		update_option( 'agentic_wp_max_output_tokens', $sanitized_tokens );

		wp_send_json_success(
			array(
				'message' => __( 'Response length limit updated successfully.', 'agenticwp' ),
				'value'   => $sanitized_tokens,
			)
		);
	}

	/**
	 * Generates API key input HTML.
	 *
	 * @since 1.0.0
	 * @return string The generated HTML markup.
	 */
	private function get_api_key_input_html() {
		ob_start();
		?>
		<div class="agenticwp-api-key-section">
			<label for="agentic_wp_openai_key"><?php esc_html_e( 'OpenAI API Key', 'agenticwp' ); ?></label>
			<input type="password" name="agentic_wp_openai_key" id="agentic_wp_openai_key" value="" class="regular-text" placeholder="sk-..." />
			<p class="description">
				<?php echo esc_html__( 'Your secure connection key from OpenAI. ', 'agenticwp' ); ?>
				<a href="<?php echo esc_url( 'https://platform.openai.com/api-keys' ); ?>" target="_blank" rel="noopener noreferrer">
					<?php esc_html_e( 'Get your free API key', 'agenticwp' ); ?>
				</a>
			</p>
		</div>
		<?php
		return ob_get_clean();
	}

	/**
	 * Get stored OpenAI API key.
	 *
	 * @return string The API key or empty string if not set.
	 */
	public static function get_api_key(): string {
		return get_option( 'agentic_wp_openai_key', '' );
	}

	/**
	 * Get selected OpenAI model.
	 *
	 * @return string The selected model or default 'gpt-5-mini' if not set.
	 */
	public static function get_model(): string {
		return get_option( 'agentic_wp_model', 'gpt-5-mini' );
	}

	/**
	 * Get selected reasoning effort level.
	 *
	 * @return string The selected effort level or default 'medium' if not set.
	 */
	public static function get_reasoning_effort(): string {
		return get_option( 'agentic_wp_reasoning_effort', 'medium' );
	}

	/**
	 * Get the maximum output tokens setting.
	 *
	 * @return int The maximum output tokens (default 32000).
	 */
	public static function get_max_output_tokens(): int {
		return (int) get_option( 'agentic_wp_max_output_tokens', 32000 );
	}

	/**
	 * Check if toast notifications should be enabled.
	 *
	 * @return bool True if toast notifications should be enabled.
	 */
	public static function should_enable_toast_notifications(): bool {
		return (bool) get_option( 'agentic_wp_enable_toast_notifications', true );
	}

	/**
	 * Check if web search is enabled for agents.
	 *
	 * @return bool True if web search is enabled.
	 */
	public static function is_web_search_enabled(): bool {
		return (bool) get_option( 'agentic_wp_enable_web_search', false );
	}

	/**
	 * Renders web search toggle field.
	 *
	 * @since 1.0.0
	 */
	public function web_search_field() {
		$value = get_option( 'agentic_wp_enable_web_search', false );
		?>
		<div class="agenticwp-checkbox-field">
			<input type="checkbox" id="agentic_wp_enable_web_search" name="agentic_wp_enable_web_search" value="1" <?php checked( 1, $value ); ?> />
			<div class="agenticwp-checkbox-field-content">
				<label for="agentic_wp_enable_web_search"><?php echo esc_html__( 'Web Search Access', 'agenticwp' ); ?></label>
				<p class="description"><?php echo esc_html__( 'Allow agents to search the web for current information. Note: This will increase your OpenAI API usage costs.', 'agenticwp' ); ?></p>
			</div>
		</div>
		<?php
	}

	/**
	 * Handles AJAX request for saving toast notifications.
	 *
	 * @since 1.0.0
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_ajax_save_toast_notifications() {
		$this->verify_ajax_request( 'agenticwp_save_toast_notifications' );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified via verify_ajax_request() above.
		$value           = sanitize_text_field( $_POST['value'] ?? '' );
		$sanitized_value = $this->sanitize_checkbox( $value );
		update_option( 'agentic_wp_enable_toast_notifications', $sanitized_value );

		wp_send_json_success(
			array(
				'message' => __( 'Task completion alerts setting updated successfully.', 'agenticwp' ),
				'value'   => $sanitized_value,
			)
		);
	}

	/**
	 * Handles AJAX request for saving web search setting.
	 *
	 * @since 1.0.0
	 * @return void Outputs JSON response and exits.
	 */
	public function handle_ajax_save_web_search() {
		$this->verify_ajax_request( 'agenticwp_save_web_search' );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified via verify_ajax_request() above.
		$value           = sanitize_text_field( $_POST['value'] ?? '' );
		$sanitized_value = $this->sanitize_checkbox( $value );

		update_option( 'agentic_wp_enable_web_search', $sanitized_value );

		wp_send_json_success(
			array(
				'message' => __( 'Web search access setting updated successfully.', 'agenticwp' ),
				'value'   => $sanitized_value,
			)
		);
	}
}
