<?php
/**
 * AJAX Handler class for managing plugin AJAX operations.
 *
 * This class handles all AJAX operations for the Ask Any plugin,
 * including chat interactions, content indexing, and Q&A management.
 *
 * @package Askany
 * @since 1.0.0
 */
namespace Askany;

use ask\askany\wpnts_nts_fs;

/**
 * AJAX Handler class for managing plugin AJAX operations
 *
 * @package Askany
 * @since 1.0.0
 */
class AjaxHandler {
	/**
	 * API Manager instance for handling AI interactions.
	 *
	 * @var ApiManager
	 */
	private $api_manager;
	/**
	 * Content Indexer instance for managing content indexing.
	 *
	 * @var ContentIndexer
	 */
	private $content_indexer;
	/**
	 * PDF Handler instance for managing PDF processing.
	 *
	 * @var PdfHandler
	 */
	private $pdf_handler;
	/**
	 * Plugin instance.
	 *
	 * @var Plugin
	 */
	private $plugin;
	/**
	 * Database instance for managing database operations.
	 *
	 * @var Database
	 */
	private $database;

	/**
	 * Slack Notifier instance for sending notifications.
	 *
	 * @var SlackNotifier
	 */
	private $slack_notifier;

	/**
	 * Constructor for AjaxHandler.
	 *
	 * Initializes the API Manager, Content Indexer, PDF Handler, Database, and SlackNotifier instances.
	 *
	 * @param Plugin         $plugin          Plugin instance.
	 * @param ApiManager     $api_manager     API Manager instance.
	 * @param ContentIndexer $content_indexer Content Indexer instance.
	 * @param PdfHandler     $pdf_handler     PDF Handler instance.
	 * @param Database       $database        Database instance.
	 * @param SlackNotifier  $slack_notifier  Slack Notifier instance.
	 */
	public function __construct( $plugin, $api_manager, $content_indexer, $pdf_handler, $database, $slack_notifier ) {
		$this->plugin = $plugin;
		$this->api_manager = $api_manager;
		$this->content_indexer = $content_indexer;
		$this->pdf_handler = $pdf_handler;
		$this->database = $database;
		$this->slack_notifier = $slack_notifier;
	}

	/**
	 * Initialize the AjaxHandler.
	 *
	 * This method hooks into WordPress to register AJAX actions and REST API routes.
	 *
	 * @return void
	 */
	public function init() {
		// Chat frontend AJAX handler.
		add_action('wp_ajax_askany_chat_response', array( $this, 'chat_response' ));
		add_action('wp_ajax_nopriv_askany_chat_response', array( $this, 'chat_response' ));

		// Chat with file attachments AJAX handler.
		add_action('wp_ajax_askany_chat_response_with_files', array( $this, 'chat_response_with_files' ));
		add_action('wp_ajax_nopriv_askany_chat_response_with_files', array( $this, 'chat_response_with_files' ));

		// Admin AJAX handlers.
		add_action('wp_ajax_askany_save_settings', array( $this, 'save_settings' ));
		add_action('wp_ajax_askany_test_api_connection', array( $this, 'test_api_connection' ));
		add_action('wp_ajax_askany_test_fcm_connection', array( $this, 'test_fcm_connection' ));
		add_action('wp_ajax_askany_send_test_push', array( $this, 'send_test_push' ));
		add_action('wp_ajax_askany_reindex_content', array( $this, 'reindex_content' ));
		add_action('wp_ajax_askany_process_pdf', array( $this, 'process_pdf' ));
		add_action('wp_ajax_askany_delete_pdf', array( $this, 'delete_pdf' ));
		add_action('wp_ajax_askany_clear_chat_all_history', array( $this, 'clear_chat_all_history' ));

		 // Handler for provider settings.
		add_action('wp_ajax_askany_get_provider_settings', array( $this, 'get_provider_settings' ));
		add_action('wp_ajax_askany_get_provider_models', array( $this, 'get_provider_models' ));

		// Setup REST API endpoint for chat.
		add_action('rest_api_init', array( $this, 'register_rest_routes' ));

		add_action('wp_ajax_askany_test_api_connection', array( $this, 'test_api_connection' ));

		add_action('wp_ajax_askany_add_qa_pair', array( $this, 'add_qa_pair' ));
		add_action('wp_ajax_askany_update_qa_pair', array( $this, 'update_qa_pair' ));
		add_action('wp_ajax_askany_delete_qa_pair', array( $this, 'delete_qa_pair' ));
		add_action('wp_ajax_askany_get_qa_pair', array( $this, 'get_qa_pair' ));
		add_action('wp_ajax_askany_export_qa_pairs', array( $this, 'export_qa_pairs' ));
		add_action('wp_ajax_askany_import_qa_pairs', array( $this, 'import_qa_pairs' ));

		// Chat management AJAX handlers
		add_action('wp_ajax_askany_add_agent', array( $this, 'add_agent' ));
		add_action('wp_ajax_askany_remove_agent', array( $this, 'remove_agent' ));
		add_action('wp_ajax_askany_get_chat_sessions', array( $this, 'get_chat_sessions' ));
		add_action('wp_ajax_askany_get_chat_messages', array( $this, 'get_chat_messages' ));
		add_action('wp_ajax_askany_assign_agent', array( $this, 'assign_agent' ));
		add_action('wp_ajax_askany_release_agent', array( $this, 'release_agent' ));
		add_action('wp_ajax_askany_send_agent_message', array( $this, 'send_agent_message' ));
		add_action('wp_ajax_askany_merge_session', array( $this, 'merge_session' ));
		add_action('wp_ajax_nopriv_askany_merge_session', array( $this, 'merge_session' ));

		// Real-time functionality AJAX handlers
		add_action('wp_ajax_askany_set_typing', array( $this, 'set_typing_indicator' ));
		add_action('wp_ajax_nopriv_askany_set_typing', array( $this, 'set_typing_indicator' ));
		add_action('wp_ajax_askany_get_realtime_updates', array( $this, 'get_realtime_updates' ));
		add_action('wp_ajax_nopriv_askany_get_realtime_updates', array( $this, 'get_realtime_updates' ));
		add_action('wp_ajax_askany_poll_messages', array( $this, 'poll_messages' ));

		// Home page management AJAX handlers
		add_action('wp_ajax_askany_save_home_settings', array( $this, 'save_home_settings' ));
		add_action('wp_ajax_askany_save_home_faq', array( $this, 'save_home_faq' ));
		add_action('wp_ajax_askany_get_home_faq', array( $this, 'get_home_faq' ));
		add_action('wp_ajax_askany_delete_home_faq', array( $this, 'delete_home_faq' ));
		add_action('wp_ajax_askany_toggle_home_faq', array( $this, 'toggle_home_faq' ));
		add_action('wp_ajax_askany_save_home_link', array( $this, 'save_home_link' ));
		add_action('wp_ajax_askany_get_home_link', array( $this, 'get_home_link' ));
		add_action('wp_ajax_askany_delete_home_link', array( $this, 'delete_home_link' ));
		add_action('wp_ajax_askany_toggle_home_link', array( $this, 'toggle_home_link' ));
		
		// Get started page AJAX handler
		add_action('wp_ajax_askany_submit_get_started', array( $this, 'submit_get_started' ));
		add_action('wp_ajax_nopriv_askany_submit_get_started', array( $this, 'submit_get_started' ));

		// Chat management AJAX handlers
		add_action('wp_ajax_askany_clear_chat_history', array( $this, 'clear_chat_history' ));
		add_action('wp_ajax_askany_delete_user_session', array( $this, 'delete_user_session' ));
		
		// Internet search AJAX handler
		add_action('wp_ajax_askany_search_internet', array( $this, 'search_internet' ));
		add_action('wp_ajax_nopriv_askany_search_internet', array( $this, 'search_internet' ));

		// Session info AJAX handler
		add_action('wp_ajax_askany_get_session_info', array( $this, 'get_session_info' ));
		add_action('wp_ajax_nopriv_askany_get_session_info', array( $this, 'get_session_info' ));

		// RAG embeddings batch processing
		add_action('wp_ajax_askany_generate_embeddings_batch', array( $this, 'generate_embeddings_batch' ));
		add_action('wp_ajax_askany_get_embeddings_status', array( $this, 'get_embeddings_status' ));
		add_action('wp_ajax_askany_clear_all_embeddings', array( $this, 'clear_all_embeddings' ));
		add_action('wp_ajax_askany_save_embedding_model', array( $this, 'save_embedding_model' ));
		add_action('wp_ajax_askany_get_embedding_errors', array( $this, 'get_embedding_errors' ));
		add_action('wp_ajax_askany_reset_stuck_embeddings', array( $this, 'reset_stuck_embeddings' ));
		add_action('wp_ajax_askany_dismiss_rag_notice', array( $this, 'dismiss_rag_notice' ));
		add_action('wp_ajax_askany_check_quota_error', array( $this, 'check_quota_error' ));
		add_action('wp_ajax_askany_save_quota_error', array( $this, 'save_quota_error' ));
		add_action('wp_ajax_askany_dismiss_quota_error', array( $this, 'dismiss_quota_error' ));
		add_action('wp_ajax_askany_clear_quota_error', array( $this, 'clear_quota_error' ));

		// News AJAX handlers
		add_action('wp_ajax_askany_get_full_post', array( $this, 'get_full_post' ));
		add_action('wp_ajax_nopriv_askany_get_full_post', array( $this, 'get_full_post' ));
		
		// Content viewing AJAX handlers
		add_action('wp_ajax_askany_get_indexed_content', array( $this, 'get_indexed_content' ));
		add_action('wp_ajax_askany_get_content_details', array( $this, 'get_content_details' ));

		// Get all messages for a session AJAX handler
		add_action('wp_ajax_askany_get_all_messages', array( $this, 'get_all_messages' ));
		
		// Unread message management AJAX handlers
		add_action('wp_ajax_askany_mark_session_read', array( $this, 'mark_session_read' ));
		add_action('wp_ajax_askany_get_unread_count', array( $this, 'get_unread_count' ));
		
		// Integration AJAX handlers
		add_action('wp_ajax_askany_save_integration_settings', array( $this, 'save_integration_settings' ));
		add_action('wp_ajax_askany_save_slack_settings', array( $this, 'save_slack_settings' ));
		add_action('wp_ajax_askany_test_slack_webhook', array( $this, 'test_slack_webhook' ));
		add_action('wp_ajax_askany_save_woocommerce_settings', array( $this, 'save_woocommerce_settings' ));
		add_action('wp_ajax_askany_save_rate_limit_settings', array( $this, 'save_rate_limit_settings' ));
		add_action('wp_ajax_nopriv_askany_get_all_messages', array( $this, 'get_all_messages' ));

		// Save user message only AJAX handler
		add_action('wp_ajax_askany_save_user_message', array( $this, 'save_user_message' ));
		add_action('wp_ajax_nopriv_askany_save_user_message', array( $this, 'save_user_message' ));

		// Product AJAX handlers
		add_action('wp_ajax_askany_get_product_details', array( $this, 'get_product_details' ));
		add_action('wp_ajax_nopriv_askany_get_product_details', array( $this, 'get_product_details' ));
		add_action('wp_ajax_askany_add_to_cart', array( $this, 'add_to_cart' ));
		add_action('wp_ajax_nopriv_askany_add_to_cart', array( $this, 'add_to_cart' ));
		
		// API statistics AJAX handlers
		add_action('wp_ajax_askany_get_api_stats', array( $this, 'get_api_stats' ));
		add_action('wp_ajax_askany_refresh_api_stats', array( $this, 'refresh_api_stats' ));
		add_action('wp_ajax_askany_get_paginated_errors', array( $this, 'get_paginated_errors' ));
		add_action('wp_ajax_askany_clear_api_errors', array( $this, 'clear_api_errors' ));
		add_action('wp_ajax_askany_get_paginated_chat_logs', array( $this, 'get_paginated_chat_logs' ));

		// Database management AJAX handlers
		add_action('wp_ajax_askany_cleanup_old_data', array( $this, 'cleanup_old_data' ));
		
		add_action('wp_ajax_askany_truncate_all_data', array( $this, 'truncate_all_data' ));
		add_action('wp_ajax_askany_optimize_tables', array( $this, 'optimize_tables' ));
		add_action('wp_ajax_askany_delete_date_range', array( $this, 'delete_date_range' ));
		add_action('wp_ajax_askany_export_data', array( $this, 'export_data' ));
		add_action('wp_ajax_askany_import_data', array( $this, 'import_data' ));
		add_action('wp_ajax_askany_filter_data', array( $this, 'filter_data' ));
		add_action('wp_ajax_askany_get_database_stats', array( $this, 'get_database_stats' ));
		add_action('wp_ajax_askany_clear_chat_logs', array( $this, 'clear_chat_logs' ));
		
		// Feature request and bug report AJAX handlers
		add_action('wp_ajax_askany_save_feature_request', array( $this, 'save_feature_request' ));
		add_action('wp_ajax_nopriv_askany_save_feature_request', array( $this, 'save_feature_request' ));
		add_action('wp_ajax_askany_save_bug_report', array( $this, 'save_bug_report' ));
		add_action('wp_ajax_nopriv_askany_save_bug_report', array( $this, 'save_bug_report' ));
		add_action('wp_ajax_askany_get_feature_requests', array( $this, 'get_feature_requests' ));
		add_action('wp_ajax_askany_get_bug_reports', array( $this, 'get_bug_reports' ));
		add_action('wp_ajax_askany_update_feature_request_status', array( $this, 'update_feature_request_status' ));
		add_action('wp_ajax_askany_update_bug_report_status', array( $this, 'update_bug_report_status' ));
		add_action('wp_ajax_askany_get_feature_request_details', array( $this, 'get_feature_request_details' ));
		add_action('wp_ajax_askany_get_bug_report_details', array( $this, 'get_bug_report_details' ));
		add_action('wp_ajax_askany_delete_feature_request', array( $this, 'delete_feature_request' ));
		add_action('wp_ajax_askany_delete_bug_report', array( $this, 'delete_bug_report' ));
		add_action('wp_ajax_askany_check_status', array( $this, 'check_status' ));
		add_action('wp_ajax_nopriv_askany_check_status', array( $this, 'check_status' ));
	}

	/**
	 * Register REST API routes.
	 *
	 * This method registers the REST API endpoint for chat interactions.
	 *
	 * @return void
	 */
	public function register_rest_routes() {
		register_rest_route('askany/v1', '/chat', array(
			'methods' => 'POST',
			'callback' => array( $this, 'rest_chat_response' ),
			'permission_callback' => '__return_true',
		));

		register_rest_route('askany/v1', '/nonce', array(
			'methods' => 'GET',
			'callback' => function() {
				return array('nonce' => wp_create_nonce('askany_chat_nonce'));
			},
			'permission_callback' => '__return_true',
		));

		// ── Mobile App REST endpoints (Application Password auth) ────────────

		// GET /askany/v1/sessions — list all chat sessions
		register_rest_route('askany/v1', '/sessions', array(
			'methods'             => 'GET',
			'callback'            => array( $this, 'rest_get_sessions' ),
			'permission_callback' => array( $this, 'rest_admin_permission' ),
		));

		// GET /askany/v1/sessions/{session_id}/messages
		register_rest_route('askany/v1', '/sessions/(?P<session_id>[^/]+)/messages', array(
			'methods'             => 'GET',
			'callback'            => array( $this, 'rest_get_session_messages' ),
			'permission_callback' => array( $this, 'rest_admin_permission' ),
		));

		// POST /askany/v1/sessions/{session_id}/messages — send agent message
		register_rest_route('askany/v1', '/sessions/(?P<session_id>[^/]+)/messages', array(
			'methods'             => 'POST',
			'callback'            => array( $this, 'rest_send_agent_message' ),
			'permission_callback' => array( $this, 'rest_admin_permission' ),
		));

		// POST /askany/v1/sessions/{session_id}/assign — take over as agent
		register_rest_route('askany/v1', '/sessions/(?P<session_id>[^/]+)/assign', array(
			'methods'             => 'POST',
			'callback'            => array( $this, 'rest_assign_agent' ),
			'permission_callback' => array( $this, 'rest_admin_permission' ),
		));

		// POST /askany/v1/sessions/{session_id}/release — release back to AI
		register_rest_route('askany/v1', '/sessions/(?P<session_id>[^/]+)/release', array(
			'methods'             => 'POST',
			'callback'            => array( $this, 'rest_release_agent' ),
			'permission_callback' => array( $this, 'rest_admin_permission' ),
		));

		// POST /askany/v1/sessions/{session_id}/read — mark session read
		register_rest_route('askany/v1', '/sessions/(?P<session_id>[^/]+)/read', array(
			'methods'             => 'POST',
			'callback'            => array( $this, 'rest_mark_read' ),
			'permission_callback' => array( $this, 'rest_admin_permission' ),
		));

		// GET /askany/v1/chat/history — visitor chat history (no auth)
		register_rest_route('askany/v1', '/chat/history', array(
			'methods'             => 'GET',
			'callback'            => array( $this, 'rest_get_chat_history' ),
			'permission_callback' => '__return_true',
		));

		// GET /askany/v1/chat/poll?session_id=...&since=... — visitor realtime poll (no auth)
		register_rest_route('askany/v1', '/chat/poll', array(
			'methods'             => 'GET',
			'callback'            => array( $this, 'rest_visitor_poll' ),
			'permission_callback' => '__return_true',
		));

		// GET /askany/v1/sessions/{session_id}/poll?since=... — realtime poll (admin auth)
		register_rest_route('askany/v1', '/sessions/(?P<session_id>[^/]+)/poll', array(
			'methods'             => 'GET',
			'callback'            => array( $this, 'rest_poll_session' ),
			'permission_callback' => array( $this, 'rest_admin_permission' ),
		));
	}

	/**
	 * Permission callback: requires manage_options (admin/Application Password).
	 */
	public function rest_admin_permission() {
		return current_user_can('manage_options');
	}

	/**
	 * REST: GET /askany/v1/sessions
	 */
	public function rest_get_sessions( \WP_REST_Request $request ) {
		$sessions = $this->database->get_active_chat_sessions_with_preview();
		if ( ! $sessions ) {
			return rest_ensure_response( array() );
		}
		foreach ( $sessions as &$session ) {
			$session->unread_count = $this->database->get_unread_message_count( $session->session_id, 'user' );
		}
		return rest_ensure_response( array_values( $sessions ) );
	}

	/**
	 * REST: GET /askany/v1/sessions/{session_id}/messages
	 */
	public function rest_get_session_messages( \WP_REST_Request $request ) {
		$session_id = sanitize_text_field( $request->get_param('session_id') );
		$messages   = $this->database->get_chat_messages( $session_id );
		$session    = $this->database->get_chat_session( $session_id );

		if ( $messages ) {
			foreach ( $messages as &$msg ) {
				$msg->message = $this->decrypt_message_for_admin( $msg->message );
			}
		}

		// Mark as read
		$this->database->mark_session_messages_as_read( $session_id );

		return rest_ensure_response( array(
			'messages' => $messages ? array_values( $messages ) : array(),
			'session'  => $session,
		) );
	}

	/**
	 * REST: POST /askany/v1/sessions/{session_id}/messages
	 */
	public function rest_send_agent_message( \WP_REST_Request $request ) {
		$session_id = sanitize_text_field( $request->get_param('session_id') );
		$message    = sanitize_textarea_field( $request->get_param('message') );

		if ( empty( $message ) ) {
			return new \WP_Error( 'missing_message', 'Message is required.', array( 'status' => 400 ) );
		}

		$user_id = get_current_user_id();
		$result  = $this->database->save_chat_message( $session_id, 'agent', $user_id, $message );

		if ( ! $result ) {
			return new \WP_Error( 'save_failed', 'Failed to save message.', array( 'status' => 500 ) );
		}

		do_action( 'askany_after_message_saved', $session_id, 'agent', $message );

		return rest_ensure_response( array( 'success' => true ) );
	}

	/**
	 * REST: POST /askany/v1/sessions/{session_id}/assign
	 */
	public function rest_assign_agent( \WP_REST_Request $request ) {
		$session_id = sanitize_text_field( $request->get_param('session_id') );
		$agent_id   = intval( $request->get_param('agent_id') ) ?: get_current_user_id();

		$result = $this->database->assign_agent_to_session( $session_id, $agent_id );

		if ( $result ) {
			$agent = get_user_by( 'id', $agent_id );
			$name  = $agent ? $agent->display_name : 'An agent';
			$this->database->save_chat_message( $session_id, 'system', null,
				sprintf( '👋 %s has joined the chat and will assist you now.', $name )
			);
		}

		return rest_ensure_response( array( 'success' => (bool) $result ) );
	}

	/**
	 * REST: POST /askany/v1/sessions/{session_id}/release
	 */
	public function rest_release_agent( \WP_REST_Request $request ) {
		$session_id = sanitize_text_field( $request->get_param('session_id') );
		$result     = $this->database->release_agent_from_session( $session_id );

		if ( $result ) {
			$this->database->save_chat_message( $session_id, 'system', null,
				'🤖 You are now chatting with our AI assistant.'
			);
		}

		return rest_ensure_response( array( 'success' => (bool) $result ) );
	}

	/**
	 * REST: POST /askany/v1/sessions/{session_id}/read
	 */
	public function rest_mark_read( \WP_REST_Request $request ) {
		$session_id = sanitize_text_field( $request->get_param('session_id') );
		$this->database->mark_session_messages_as_read( $session_id );
		return rest_ensure_response( array( 'success' => true ) );
	}

	/**
	 * REST: GET /askany/v1/chat/history?session_id=xxx
	 */
	public function rest_get_chat_history( \WP_REST_Request $request ) {
		$session_id = sanitize_text_field( $request->get_param('session_id') );
		if ( empty( $session_id ) ) {
			return new \WP_Error( 'missing_session', 'session_id is required.', array( 'status' => 400 ) );
		}
		$messages = $this->database->get_chat_messages( $session_id );
		return rest_ensure_response( $messages ? array_values( $messages ) : array() );
	}

	/**
	 * REST: GET /askany/v1/sessions/{session_id}/poll?since=...
	 * Returns new messages since the given timestamp. Used by the app for real-time polling.
	 * Uses Application Password auth — no nonce needed.
	 */
	public function rest_poll_session( \WP_REST_Request $request ) {
		$session_id = sanitize_text_field( $request->get_param('session_id') );
		$since      = sanitize_text_field( $request->get_param('since') );

		if ( empty( $session_id ) ) {
			return new \WP_Error( 'missing_session', 'session_id is required.', array( 'status' => 400 ) );
		}

		global $wpdb;
		$messages_table = $this->database->get_messages_table();

		if ( ! empty( $since ) ) {
			$messages = $wpdb->get_results( $wpdb->prepare(
				"SELECT * FROM {$messages_table} WHERE session_id = %s AND created_at > %s ORDER BY created_at ASC",
				$session_id,
				$since
			) );
		} else {
			// No since param — return last 5 minutes
			$five_ago = date( 'Y-m-d H:i:s', strtotime( '-5 minutes' ) );
			$messages = $wpdb->get_results( $wpdb->prepare(
				"SELECT * FROM {$messages_table} WHERE session_id = %s AND created_at > %s ORDER BY created_at ASC",
				$session_id,
				$five_ago
			) );
		}

		if ( $messages ) {
			foreach ( $messages as &$msg ) {
				$msg->message = $this->decrypt_message_for_admin( $msg->message );
			}
		}

		return rest_ensure_response( array(
			'messages' => $messages ? array_values( $messages ) : array(),
			'typing'   => false,
		) );
	}

	/**
	 * REST: GET /askany/v1/chat/poll?session_id=...&since=...
	 * Public visitor poll — no auth needed, session_id is the visitor's own session.
	 */
	public function rest_visitor_poll( \WP_REST_Request $request ) {
		$session_id = sanitize_text_field( $request->get_param('session_id') );
		$since      = sanitize_text_field( $request->get_param('since') );

		if ( empty( $session_id ) ) {
			return new \WP_Error( 'missing_session', 'session_id is required.', array( 'status' => 400 ) );
		}

		global $wpdb;
		$messages_table = $this->database->get_messages_table();

		if ( ! empty( $since ) ) {
			$messages = $wpdb->get_results( $wpdb->prepare(
				"SELECT * FROM {$messages_table} WHERE session_id = %s AND created_at > %s ORDER BY created_at ASC",
				$session_id,
				$since
			) );
		} else {
			$five_ago = date( 'Y-m-d H:i:s', strtotime( '-5 minutes' ) );
			$messages = $wpdb->get_results( $wpdb->prepare(
				"SELECT * FROM {$messages_table} WHERE session_id = %s AND created_at > %s ORDER BY created_at ASC",
				$session_id,
				$five_ago
			) );
		}

		if ( $messages ) {
			foreach ( $messages as &$msg ) {
				$msg->message = $this->decrypt_message_for_admin( $msg->message );
			}
		}

		return rest_ensure_response( array(
			'messages' => $messages ? array_values( $messages ) : array(),
			'typing'   => false,
		) );
	}

	/**
	 * Handle chat response via REST API.
	 *
	 * This method processes the chat request and returns a response.
	 *
	 * @param \WP_REST_Request $request The REST request object.
	 * @return \WP_Error|\WP_REST_Response The response object or error.
	 */
	public function rest_chat_response( $request ) {
		$params = $request->get_json_params();

		// Process encrypted request data
		$request_data = EncryptionHandler::process_encrypted_request($params);
		
		$message = isset($request_data['query']) ? sanitize_text_field($request_data['query']) : '';
		$session_id = isset($request_data['session_id']) ? sanitize_text_field($request_data['session_id']) : '';
		$api_provider = isset($request_data['api_provider']) ? sanitize_text_field($request_data['api_provider']) : '';
		$is_encrypted = isset($params['encrypted']) && $params['encrypted'];

		// Log encryption status for debugging
		if ($is_encrypted) {
			EncryptionHandler::log_encryption_event('REST_REQUEST', 'Received encrypted chat request', array(
				'session_id' => substr($session_id, 0, 10) . '...',
				'message_length' => strlen($message)
			));
		}

		if ( empty($message) ) {
			$error_response = array('message' => __('Please enter a message.', 'askany'));
			
			if ($is_encrypted) {
				$error_response = EncryptionHandler::process_encrypted_response($error_response, $params);
			}
			
			return new \WP_Error('empty_message', $error_response['message'], array( 'status' => 400 ));
		}

		// Get current user info
		$current_user_id = get_current_user_id();

		// Debug: Log what session ID we received
		// error_log('AskAny REST Debug: Received session_id: ' . $session_id);
		// error_log('AskAny REST Debug: Current user ID: ' . $current_user_id);

		// Ensure we have a valid session ID
		if (empty($session_id)) {
			$session_id = 'user_' . $current_user_id . '_' . time();
		}

		// Debug: Log what session ID we're using
		// error_log('AskAny REST Debug: Using session_id: ' . $session_id);

		// Get user data for session creation
		$user_data = array();
		if ( isset($params['user_name']) ) {
			$user_data['name'] = sanitize_text_field($params['user_name']);
		}
		if ( isset($params['user_email']) ) {
			$user_data['email'] = sanitize_email($params['user_email']);
		}

		// Check if session already exists before creating/updating
		$existing_session = $this->database->get_chat_session($session_id);
		
		if (!$existing_session) {
			// Create new session only if it doesn't exist
			$this->database->create_chat_session($session_id, $user_data);
		} else {
			// Update last activity for existing session without changing agent assignment
			global $wpdb;
			$wpdb->update(
				$wpdb->prefix . 'askany_chat_sessions',
				array('last_activity' => current_time('mysql')),
				array('session_id' => $session_id),
				array('%s'),
				array('%s')
			);
		}

		// Log the message state for debugging (REST API)
		if ($is_encrypted) {
			EncryptionHandler::log_encryption_event('REST_MESSAGE_SAVE', 'Saving decrypted user message', array(
				'original_encrypted' => isset($request_data['_original_query_encrypted']),
				'message_length' => strlen($message),
				'session_id' => substr($session_id, 0, 10) . '...'
			));
		}

		// Save user message (should be decrypted at this point)
		$this->database->save_chat_message($session_id, 'user', $current_user_id, $message);

		// Notify admin devices that a user sent a message
		do_action( 'askany_after_message_saved', $session_id, 'user', $message );

		// ── Rate limiting check ──────────────────────────────────────────────
		$rate_check = \Askany\RateLimiter::check( $current_user_id );
		if ( ! $rate_check['allowed'] ) {
			if ( ! empty( $rate_check['use_fallback'] ) && get_option( 'askany_fallback_enabled', false ) ) {
				$fallback         = $this->api_manager->get_fallback_response_public( $message );
				$fallback_message = is_array( $fallback ) ? $fallback['text'] : $fallback;
				$this->database->save_chat_message( $session_id, 'ai', null, $fallback_message );
				return array( 'message' => $fallback_message, 'session_id' => $session_id );
			}
			return new \WP_Error( 'rate_limited', $rate_check['message'], array( 'status' => 429 ) );
		}
		// ────────────────────────────────────────────────────────────────────

		// Check if session is handled by an agent
		$session = $this->database->get_chat_session($session_id);

		if ( $session && ! $session->is_ai_handled && $session->agent_id ) {
			// Session is handled by an agent, don't send AI response
			return array(
				'message' => __('Your message has been received. An agent will respond shortly.', 'askany'),
				'session_id' => $session_id,
				'agent_handled' => true,
			);
		}

		// Get settings
		$settings = $this->api_manager->get_settings();

		// Override API provider if specified in request.
		if ( ! empty($api_provider) ) {
			$settings['api_provider'] = $api_provider;
		}

		// Check if API is enabled.
		if ( ! $settings['api_enabled'] ) {
			return new \WP_Error('api_disabled', __('Chat API is currently disabled.', 'askany'), array( 'status' => 403 ));
		}

		// Get response from API.
		$response = $this->api_manager->get_response($message, $session_id);

		// If API fails and fallback is enabled, use fallback response.
		if ( ! $response && $settings['fallback_enabled'] ) {
			$response = array(
				'message' => __('I apologize, but I am currently unable to process your request. Please try again later.', 'askany'),
				'related_products' => array(),
				'session_id' => $session_id,
			);
		} elseif ( ! $response ) {
			return new \WP_Error('api_error', __('Sorry, I could not process your request.', 'askany'), array( 'status' => 500 ));
		}

		// Save AI response
		$this->database->save_chat_message($session_id, 'ai', null, $response['message']);

		// Notify visitor device that AI replied
		do_action( 'askany_after_message_saved', $session_id, 'ai', $response['message'] );

		// Send Slack notification for AI response if enabled
		if ( $this->slack_notifier ) {
			$this->slack_notifier->handle_ai_message( $session_id, $response['message'], array() );
		}

		// Store chat history in old format for backward compatibility
		$this->log_chat_history($message, $response['message']);

		// Process response for encryption if needed
		if ($is_encrypted) {
			$response = EncryptionHandler::process_encrypted_response($response, $params);
			EncryptionHandler::log_encryption_event('REST_RESPONSE', 'Sending encrypted chat response', array(
				'session_id' => substr($session_id, 0, 10) . '...',
				'response_length' => strlen($response['message'])
			));
		}

		return $response;
	}

	/**
	 * Handle report issue or feature request conversation.
	 *
	 * @param string $message The user's message.
	 * @param string $context The conversation context (report_issue or feature_request).
	 * @param array  $state The current conversation state.
	 * @param string $session_id The session ID.
	 *
	 * @return array Response data with message and submission status.
	 */
	private function handle_report_feature_conversation( $message, $context, $state, $session_id ) {
		// ('=== handle_report_feature_conversation ===');
		// ('Message: ' . $message);
		// ('Context: ' . $context);
		// ('State: ' . print_r($state, true));
		// ('Session ID: ' . $session_id);
		
		// Check if user is confirming submission
		$message_lower = strtolower(trim($message));
		// ('Message lower: ' . $message_lower);
		// ('State step: ' . (isset($state['step']) ? $state['step'] : 'NOT SET'));
		
		if ( in_array($message_lower, array('confirm', 'submit', 'yes')) && isset($state['step']) && $state['step'] === 'confirmed' ) {
			// ('User is confirming submission!');
			
			// User has confirmed, submit to database
			$user_name = isset($state['userName']) ? sanitize_text_field($state['userName']) : '';
			$user_email = isset($state['userEmail']) ? sanitize_email($state['userEmail']) : '';
			$details = isset($state['details']) ? sanitize_textarea_field($state['details']) : '';
			
			// ('Extracted data - Name: ' . $user_name . ', Email: ' . $user_email . ', Details: ' . $details);
			
			// Validate data
			if ( empty($user_name) || empty($user_email) || empty($details) ) {
				// ('Validation failed - missing fields');
				return array(
					'message' => __('Please fill out all required fields in the form before confirming.', 'askany'),
					'submitted' => false
				);
			}
			
			// Validate email
			if ( ! is_email($user_email) ) {
				// ('Validation failed - invalid email');
				return array(
					'message' => __('Please enter a valid email address.', 'askany'),
					'submitted' => false
				);
			}
			
			// Submit to database
			if ( $context === 'report_issue' ) {
				// ('Saving bug report to database...');
				$result = $this->database->save_bug_report(
					$session_id,
					$user_name,
					$user_email,
					'Bug Report', // Default title
					$details,
					'open',
					'medium'
				);
				
				// ('Bug report save result: ' . ($result ? 'SUCCESS' : 'FAILED'));
				
				if ( $result ) {
					return array(
						'message' => sprintf(
							__('✅ Thank you, %s! Your bug report has been submitted successfully. We\'ll review it and get back to you at %s.', 'askany'),
							$user_name,
							$user_email
						),
						'submitted' => true
					);
				} else {
					return array(
						'message' => __('❌ Sorry, there was an error submitting your report. Please try again later.', 'askany'),
						'submitted' => false
					);
				}
			} else if ( $context === 'feature_request' ) {
				// ('Saving feature request to database...');
				$result = $this->database->save_feature_request(
					$session_id,
					$user_name,
					$user_email,
					'Feature Request', // Default title
					$details,
					'open',
					'medium'
				);
				
				// ('Feature request save result: ' . ($result ? 'SUCCESS' : 'FAILED'));
				
				if ( $result ) {
					return array(
						'message' => sprintf(
							__('✅ Thank you, %s! Your feature request has been submitted successfully. We\'ll consider it for future updates and contact you at %s.', 'askany'),
							$user_name,
							$user_email
						),
						'submitted' => true
					);
				} else {
					return array(
						'message' => __('❌ Sorry, there was an error submitting your request. Please try again later.', 'askany'),
						'submitted' => false
					);
				}
			}
		}
		
		// ('Not confirming - returning instruction message');
		// If not confirming, just acknowledge the message
		return array(
			'message' => __('Please fill out the form above and type "confirm" or "submit" to send your report.', 'askany'),
			'submitted' => false
		);
	}

	/**
	 * Extract user information from message.
	 *
	 * @param string $message The user's message.
	 *
	 * @return array Extracted information.
	 */
	private function extract_user_info( $message ) {
		$info = array(
			'name' => null,
			'email' => null,
			'details' => $message,
		);

		// Extract email using regex
		if ( preg_match('/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/', $message, $email_match) ) {
			$info['email'] = $email_match[0];
			// Remove email from details
			$info['details'] = trim(str_replace($email_match[0], '', $message));
		}

		// Extract name (capitalized words, typically 2-4 words)
		if ( preg_match('/\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+){0,3})\b/', $message, $name_match) ) {
			// Verify it's not a common word
			$common_words = array('Please', 'Thanks', 'Hello', 'Issue', 'Feature', 'Request', 'Report', 'Bug');
			if ( ! in_array($name_match[1], $common_words) ) {
				$info['name'] = $name_match[1];
				// Remove name from details
				$info['details'] = trim(str_replace($name_match[1], '', $info['details']));
			}
		}

		// Clean up details
		$info['details'] = preg_replace('/\s+/', ' ', $info['details']);
		$info['details'] = trim($info['details'], ' ,-');

		return $info;
	}

	/**
	 * Generate response for collecting missing information.
	 *
	 * @param array  $missing Missing information fields.
	 * @param array  $state Current conversation state.
	 * @param string $context Conversation context.
	 *
	 * @return string Response message.
	 */
	private function generate_collection_response( $missing, $state, $context ) {
		$responses = array();

		// Acknowledge what we received
		if ( ! empty($state['userName']) ) {
			$responses[] = sprintf(__('Thanks %s! 👍', 'askany'), $state['userName']);
		} elseif ( ! empty($state['userEmail']) ) {
			$responses[] = __('Got your email! 📧', 'askany');
		} elseif ( ! empty($state['details']) ) {
			$responses[] = __('Thanks for sharing that! 📝', 'askany');
		}

		// Ask for missing information
		if ( count($missing) === 3 ) {
			// Nothing received yet, ask for everything
			if ( $context === 'report_issue' ) {
				$responses[] = __('To help us track and fix this issue, please share:', 'askany');
			} else {
				$responses[] = __('To consider your feature request, please share:', 'askany');
			}
			$responses[] = __('1️⃣ Your name', 'askany');
			$responses[] = __('2️⃣ Your email address', 'askany');
			if ( $context === 'report_issue' ) {
				$responses[] = __('3️⃣ Details about the bug/issue', 'askany');
			} else {
				$responses[] = __('3️⃣ Details about the feature you\'d like', 'askany');
			}
		} elseif ( in_array('name', $missing) && in_array('email', $missing) ) {
			// Missing name and email
			$responses[] = __('Could you please share your name and email address?', 'askany');
		} elseif ( in_array('name', $missing) ) {
			// Missing only name
			$responses[] = __('What\'s your name?', 'askany');
		} elseif ( in_array('email', $missing) ) {
			// Missing only email
			$responses[] = __('What\'s your email address?', 'askany');
		} elseif ( in_array('details', $missing) ) {
			// Missing only details
			if ( $context === 'report_issue' ) {
				$responses[] = __('Please describe the issue you\'re experiencing.', 'askany');
			} else {
				$responses[] = __('Please describe the feature you\'d like to see.', 'askany');
			}
		}

		return implode("\n\n", $responses);
	}

	/**
	 * Generate confirmation response.
	 *
	 * @param array  $state Current conversation state.
	 * @param string $context Conversation context.
	 *
	 * @return string Response message.
	 */
	private function generate_confirmation_response( $state, $context ) {
		$type = $context === 'report_issue' ? __('bug report', 'askany') : __('feature request', 'askany');

		$response = sprintf(
			__('Perfect! Let me confirm your %s:', 'askany'),
			$type
		);
		$response .= "\n\n";
		$response .= sprintf(__('👤 Name: %s', 'askany'), $state['userName']) . "\n";
		$response .= sprintf(__('📧 Email: %s', 'askany'), $state['userEmail']) . "\n";
		if ( $context === 'report_issue' ) {
			$response .= sprintf(__('🐛 Issue: %s', 'askany'), $state['details']) . "\n";
		} else {
			$response .= sprintf(__('✨ Feature: %s', 'askany'), $state['details']) . "\n";
		}
		$response .= "\n";
		$response .= __('Is this correct? Reply with "yes" or "confirm" to submit, or provide any corrections.', 'askany');

		return $response;
	}


	/**
	 * Handle chat response via AJAX.
	 *
	 * This method processes the chat request and returns a response.
	 *
	 * @return void
	 */
	public function chat_response() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		// Process encrypted request data
		$request_data = EncryptionHandler::process_encrypted_request($_POST);

		$message = isset($request_data['message']) ? sanitize_text_field( wp_unslash( $request_data['message']) ) : '';
		$session_id = isset($request_data['session_id']) ? sanitize_text_field( wp_unslash( $request_data['session_id']) ) : '';
		$api_provider = isset($request_data['api_provider']) ? sanitize_text_field( wp_unslash( $request_data['api_provider']) ) : '';
		$is_encrypted = isset($_POST['encrypted']) && $_POST['encrypted'];

		// Log encryption status for debugging
		if ($is_encrypted) {
			EncryptionHandler::log_encryption_event('AJAX_REQUEST', 'Received encrypted chat request', array(
				'session_id' => substr($session_id, 0, 10) . '...',
				'message_length' => strlen($message)
			));
		}

		if ( empty($message) ) {
			$error_response = array('message' => __('Please enter a message.', 'askany'));

			if ($is_encrypted) {
				$error_response = EncryptionHandler::process_encrypted_response($error_response, $_POST);
			}

			wp_send_json_error($error_response);
		}

		// Get current user info
		$current_user_id = get_current_user_id();

		// Debug: Log what session ID we received
		// error_log('AskAny Debug: Received session_id: ' . $session_id);
		// error_log('AskAny Debug: Current user ID: ' . $current_user_id);

		// Ensure we have a valid session ID
		if (empty($session_id)) {
			$session_id = 'user_' . $current_user_id . '_' . time();
		}

		// Debug: Log what session ID we're using
		// error_log('AskAny Debug: Using session_id: ' . $session_id);

		// Get user data for session creation
		$user_data = array();
		if ( isset($_POST['user_name']) ) {
			$user_data['name'] = sanitize_text_field( wp_unslash( $_POST['user_name'] ) );
		}
		if ( isset($_POST['user_email']) ) {
			$user_data['email'] = sanitize_email( wp_unslash( $_POST['user_email'] ) );
		}

		// Check if session already exists before creating/updating
		$existing_session = $this->database->get_chat_session($session_id);

		if (!$existing_session) {
			// Create new session only if it doesn't exist
			$this->database->create_chat_session($session_id, $user_data);
		} else {
			// Update last activity for existing session without changing agent assignment
			global $wpdb;
			$wpdb->update(
				$wpdb->prefix . 'askany_chat_sessions',
				array('last_activity' => current_time('mysql')),
				array('session_id' => $session_id),
				array('%s'),
				array('%s')
			);
		}

		// Save user message
		$this->database->save_chat_message($session_id, 'user', $current_user_id, $message);

		// Fire hook for push notifications
		do_action('askany_after_message_saved', $session_id, 'user', $message);

		// ── Rate limiting check ──────────────────────────────────────────────
		$rate_check = \Askany\RateLimiter::check( $current_user_id );
		if ( ! $rate_check['allowed'] ) {
			if ( ! empty( $rate_check['use_fallback'] ) && get_option( 'askany_fallback_enabled', false ) ) {
				// Use fallback response instead of showing error
				$fallback = $this->api_manager->get_fallback_response_public( $message );
				$fallback_message = is_array( $fallback ) ? $fallback['text'] : $fallback;
				$this->database->save_chat_message( $session_id, 'ai', null, $fallback_message );
				wp_send_json_success( array(
					'message'    => $fallback_message,
					'session_id' => $session_id,
				) );
				return;
			}
			wp_send_json_error( array(
				'message'    => $rate_check['message'],
				'rate_limit' => true,
			) );
			return;
		}
		// ────────────────────────────────────────────────────────────────────

		// Check if session is handled by an agent (use existing session or newly created one)
		$session = $existing_session ?: $this->database->get_chat_session($session_id);

		if ( $session && ! $session->is_ai_handled && $session->agent_id ) {
			// Session is handled by an agent, don't send AI response
			wp_send_json_success(array(
				'message' => __('Your message has been received. An agent will respond shortly.', 'askany'),
				'session_id' => $session_id,
				'agent_handled' => true,
			));
			return;
		}

		// Check if user is in report_issue or feature_request mode
		$conversation_context = isset($_POST['conversation_context']) ? sanitize_text_field( wp_unslash( $_POST['conversation_context'] ) ) : '';
		$conversation_state = isset($_POST['conversation_state']) ? json_decode( wp_unslash( $_POST['conversation_state'] ), true ) : array();

		// Debug logging - ENHANCED
		// ('=== AskAny Debug - Conversation Mode Check ===');
		// ('Conversation Context: ' . $conversation_context);
		// ('Conversation State (raw): ' . (isset($_POST['conversation_state']) ? $_POST['conversation_state'] : 'NOT SET'));
		// ('Conversation State (decoded): ' . print_r($conversation_state, true));
		// ('Message: ' . $message);
		// ('Is in conversation mode: ' . (in_array($conversation_context, array('report_issue', 'feature_request')) ? 'YES' : 'NO'));
		// ('===========================================');

		if ( in_array($conversation_context, array('report_issue', 'feature_request')) ) {
			// Handle report issue or feature request conversation
			// ('Entering conversation handler...');
			$response_data = $this->handle_report_feature_conversation($message, $conversation_context, $conversation_state, $session_id);

			// Extract message and submitted status
			$response_message = is_array($response_data) ? $response_data['message'] : $response_data;
			$submitted = is_array($response_data) && isset($response_data['submitted']) ? $response_data['submitted'] : false;

			// ('Response message: ' . $response_message);
			// ('Submitted: ' . ($submitted ? 'YES' : 'NO'));

			// Save AI response
			$this->database->save_chat_message($session_id, 'ai', null, $response_message);

			// Fire hook for push notifications
			do_action('askany_after_message_saved', $session_id, 'ai', $response_message);

			wp_send_json_success(array(
				'message' => $response_message,
				'session_id' => $session_id,
				'conversation_mode' => true,
				'submitted' => $submitted,
			));
			return;
		}

		// Get settings.
		$settings = $this->api_manager->get_settings();

		// Override API provider if specified in request.
		if ( ! empty($api_provider) ) {
			$settings['api_provider'] = $api_provider;
		}

		// Check if API is enabled.
		if ( ! $settings['api_enabled'] ) {
			wp_send_json_error(array(
				'message' => __('Chat API is currently disabled. Please contact the administrator.', 'askany'),
			));
		}

		// Get response from API.
		$response = $this->api_manager->get_response($message, $session_id);

		// If API fails and fallback is enabled, use fallback response.
		if ( ! $response && $settings['fallback_enabled'] ) {
			$response = array(
				'message' => __('I apologize, but I am currently unable to process your request. Please try again later.', 'askany'),
				'related_products' => array(),
				'session_id' => $session_id,
			);
		} elseif ( ! $response ) {
			wp_send_json_error(array(
				'message' => __('Sorry, I could not process your request at this time.', 'askany'),
			));
		}

		// Save AI response
		$this->database->save_chat_message($session_id, 'ai', null, $response['message']);

		// Fire hook for push notifications
		do_action('askany_after_message_saved', $session_id, 'ai', $response['message']);

		// Send Slack notification for AI response if enabled
		if ( $this->slack_notifier ) {
			$this->slack_notifier->handle_ai_message( $session_id, $response['message'], array() );
		}

		// Store chat history in old format for backward compatibility
		$this->log_chat_history($message, $response['message']);

		// Process response for encryption if needed
		if ($is_encrypted) {
			$response = EncryptionHandler::process_encrypted_response($response, $_POST);
			EncryptionHandler::log_encryption_event('AJAX_RESPONSE', 'Sending encrypted chat response', array(
				'session_id' => substr($session_id, 0, 10) . '...',
				'response_length' => strlen($response['message'])
			));
		}

		wp_send_json_success($response);
	}

	/**
	 * Handle chat response with file attachments via AJAX.
	 *
	 * This method processes the chat request with file attachments and returns a response.
	 *
	 * @return void
	 */
	public function chat_response_with_files() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		// Process encrypted request data
		$request_data = EncryptionHandler::process_encrypted_request($_POST);
		
		$message = isset($request_data['message']) ? sanitize_text_field( wp_unslash( $request_data['message']) ) : '';
		$session_id = isset($request_data['session_id']) ? sanitize_text_field( wp_unslash( $request_data['session_id']) ) : '';
		$api_provider = isset($request_data['api_provider']) ? sanitize_text_field( wp_unslash( $request_data['api_provider']) ) : '';
		$is_encrypted = isset($_POST['encrypted']) && $_POST['encrypted'];

		// Log encryption status for debugging
		if ($is_encrypted) {
			EncryptionHandler::log_encryption_event('AJAX_FILE_REQUEST', 'Received encrypted chat request with files', array(
				'session_id' => substr($session_id, 0, 10) . '...',
				'message_length' => strlen($message),
				'files_count' => isset($_FILES['attachments']) ? count($_FILES['attachments']['name']) : 0
			));
		}

		// Validate message or files
		$has_files = isset($_FILES['attachments']) && !empty($_FILES['attachments']['name'][0]);
		if (empty($message) && !$has_files) {
			$error_response = array('message' => __('Please enter a message or attach a file.', 'askany'));
			
			if ($is_encrypted) {
				$error_response = EncryptionHandler::process_encrypted_response($error_response, $_POST);
			}
			
			wp_send_json_error($error_response);
		}

		// Get current user info
		$current_user_id = get_current_user_id();

		// Ensure we have a valid session ID
		if (empty($session_id)) {
			$session_id = 'user_' . $current_user_id . '_' . time();
		}

		// Get user data for session creation
		$user_data = array();
		if ( isset($_POST['user_name']) ) {
			$user_data['name'] = sanitize_text_field( wp_unslash( $_POST['user_name'] ) );
		}
		if ( isset($_POST['user_email']) ) {
			$user_data['email'] = sanitize_email( wp_unslash( $_POST['user_email'] ) );
		}

		// Check if session already exists before creating/updating
		$existing_session = $this->database->get_chat_session($session_id);
		
		if (!$existing_session) {
			// Create new session only if it doesn't exist
			$this->database->create_chat_session($session_id, $user_data);
		} else {
			// Update last activity for existing session without changing agent assignment
			global $wpdb;
			$wpdb->update(
				$wpdb->prefix . 'askany_chat_sessions',
				array('last_activity' => current_time('mysql')),
				array('session_id' => $session_id),
				array('%s'),
				array('%s')
			);
		}

		// Process file attachments
		$processed_files = array();
		$file_analysis = '';
		
		if ($has_files) {
			$processed_files = $this->process_file_attachments($_FILES['attachments']);
			
			if (!empty($processed_files['errors'])) {
				wp_send_json_error(array(
					'message' => 'File processing errors: ' . implode(', ', $processed_files['errors'])
				));
			}
			
			// Generate file analysis for AI context
			$file_analysis = $this->generate_file_analysis($processed_files['files']);
		}

		// Combine message with file analysis
		$full_message = $message;
		if (!empty($file_analysis)) {
			$full_message .= "\n\n[ATTACHED FILES ANALYSIS]\n" . $file_analysis;
		}

		// Save user message with file info
		$message_to_save = $message;
		if (!empty($processed_files['files'])) {
			$message_to_save .= "\n📎 " . count($processed_files['files']) . " file(s) attached: " . 
				implode(', ', array_column($processed_files['files'], 'name'));
		}
		
		$this->database->save_chat_message($session_id, 'user', $current_user_id, $message_to_save);

		// Check if session is handled by an agent
		$session = $this->database->get_chat_session($session_id);

		if ( $session && ! $session->is_ai_handled && $session->agent_id ) {
			// Session is handled by an agent, don't send AI response
			wp_send_json_success(array(
				'message' => __('Your message and files have been received. An agent will respond shortly.', 'askany'),
				'session_id' => $session_id,
				'agent_handled' => true,
			));
			return;
		}

		// Get settings
		$settings = $this->api_manager->get_settings();

		// Override API provider if specified in request
		if ( ! empty($api_provider) ) {
			$settings['api_provider'] = $api_provider;
		}

		// Check if API is enabled
		if ( ! $settings['api_enabled'] ) {
			wp_send_json_error(array(
				'message' => __('Chat API is currently disabled. Please contact the administrator.', 'askany'),
			));
		}

		// Get response from API with file context
		$response = $this->api_manager->get_response($full_message, $session_id);

		// If API fails and fallback is enabled, use fallback response
		if ( ! $response && $settings['fallback_enabled'] ) {
			$fallback_message = __('I apologize, but I am currently unable to process your request. Please try again later.', 'askany');
			if (!empty($processed_files['files'])) {
				$fallback_message = __('I received your files but am currently unable to analyze them. Please try again later.', 'askany');
			}
			
			$response = array(
				'message' => $fallback_message,
				'related_products' => array(),
				'session_id' => $session_id,
			);
		} elseif ( ! $response ) {
			wp_send_json_error(array(
				'message' => __('Sorry, I could not process your request at this time.', 'askany'),
			));
		}

		// Save AI response
		$this->database->save_chat_message($session_id, 'ai', null, $response['message']);

		// Send Slack notification for AI response if enabled
		if ( $this->slack_notifier ) {
			$this->slack_notifier->handle_ai_message( $session_id, $response['message'], array() );
		}

		// Store chat history in old format for backward compatibility
		$this->log_chat_history($message_to_save, $response['message']);

		// Add file information to response
		if (!empty($processed_files['files'])) {
			$response['attached_files'] = $processed_files['files'];
		}

		// Process response for encryption if needed
		if ($is_encrypted) {
			$response = EncryptionHandler::process_encrypted_response($response, $_POST);
			EncryptionHandler::log_encryption_event('AJAX_FILE_RESPONSE', 'Sending encrypted chat response with files', array(
				'session_id' => substr($session_id, 0, 10) . '...',
				'response_length' => strlen($response['message']),
				'files_processed' => count($processed_files['files'])
			));
		}

		wp_send_json_success($response);
	}

	/**
	 * Process file attachments and extract content.
	 *
	 * @param array $files The uploaded files array.
	 * @return array Array containing processed files and any errors.
	 */
	private function process_file_attachments($files) {
		$processed_files = array();
		$errors = array();
		$max_file_size = 10 * 1024 * 1024; // 10MB
		$supported_image_types = array('image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp');
		$supported_pdf_types = array('application/pdf');
		$supported_types = array_merge($supported_image_types, $supported_pdf_types);

		// Handle multiple files
		$file_count = count($files['name']);
		
		for ($i = 0; $i < $file_count; $i++) {
			// Skip empty files
			if (empty($files['name'][$i]) || $files['error'][$i] !== UPLOAD_ERR_OK) {
				continue;
			}

			$file_name = sanitize_file_name($files['name'][$i]);
			$file_type = $files['type'][$i];
			$file_size = $files['size'][$i];
			$file_tmp = $files['tmp_name'][$i];

			// Validate file type
			if (!in_array($file_type, $supported_types)) {
				$errors[] = $file_name . ' - Unsupported file type. Only images (JPEG, PNG, GIF, WebP) and PDF files are supported.';
				continue;
			}

			// Validate file size
			if ($file_size > $max_file_size) {
				$errors[] = $file_name . ' - File too large. Maximum size is 10MB.';
				continue;
			}

			// Process the file based on type
			$file_content = '';
			$file_info = array(
				'name' => $file_name,
				'type' => $file_type,
				'size' => $file_size,
				'content' => '',
				'analysis' => ''
			);

			if (in_array($file_type, $supported_image_types)) {
				// Process image file
				$file_info['analysis'] = $this->analyze_image($file_tmp, $file_name);
			} elseif (in_array($file_type, $supported_pdf_types)) {
				// Process PDF file
				$file_info['content'] = $this->extract_pdf_text($file_tmp);
				$file_info['analysis'] = $this->analyze_pdf_content($file_info['content'], $file_name);
			}

			$processed_files[] = $file_info;
		}

		return array(
			'files' => $processed_files,
			'errors' => $errors
		);
	}

	/**
	 * Analyze image file and return description.
	 *
	 * @param string $file_path Path to the image file.
	 * @param string $file_name Name of the file.
	 * @return string Image analysis.
	 */
	private function analyze_image($file_path, $file_name) {
		// Get image info
		$image_info = getimagesize($file_path);
		
		if ($image_info === false) {
			return "Image file: {$file_name} (unable to analyze image properties)";
		}

		$width = $image_info[0];
		$height = $image_info[1];
		$mime_type = $image_info['mime'];

		$analysis = "Image file: {$file_name}\n";
		$analysis .= "- Dimensions: {$width} x {$height} pixels\n";
		$analysis .= "- Format: " . str_replace('image/', '', $mime_type) . "\n";
		$analysis .= "- File size: " . $this->format_file_size(filesize($file_path)) . "\n";
		$analysis .= "Note: This is an image file. I can see the technical details but cannot analyze the visual content without additional image processing capabilities.";

		return $analysis;
	}

	/**
	 * Extract text content from PDF file.
	 *
	 * @param string $file_path Path to the PDF file.
	 * @return string Extracted text content.
	 */
	private function extract_pdf_text($file_path) {
		// Try to use existing PDF handler if available
		if ($this->pdf_handler) {
			try {
				// Create a temporary file array structure
				$temp_file = array(
					'tmp_name' => $file_path,
					'name' => basename($file_path),
					'type' => 'application/pdf',
					'size' => filesize($file_path),
					'error' => UPLOAD_ERR_OK
				);
				
				$result = $this->pdf_handler->extract_text_from_pdf($file_path);
				return $result ? $result : 'Unable to extract text from PDF file.';
			} catch (Exception $e) {
				return 'Error processing PDF: ' . $e->getMessage();
			}
		}

		// Fallback: Basic PDF text extraction using shell command if available
		if (function_exists('shell_exec') && !empty(shell_exec('which pdftotext'))) {
			$output = shell_exec('pdftotext "' . escapeshellarg($file_path) . '" -');
			return !empty($output) ? $output : 'Unable to extract text from PDF file.';
		}

		return 'PDF text extraction not available. Please install PDF processing tools.';
	}

	/**
	 * Analyze PDF content and return summary.
	 *
	 * @param string $content The extracted PDF text content.
	 * @param string $file_name Name of the file.
	 * @return string PDF analysis.
	 */
	private function analyze_pdf_content($content, $file_name) {
		$analysis = "PDF file: {$file_name}\n";
		
		if (empty($content) || $content === 'Unable to extract text from PDF file.') {
			$analysis .= "- Status: Text extraction failed or PDF contains no readable text\n";
			$analysis .= "- Note: This might be a scanned PDF or contain only images";
			return $analysis;
		}

		$word_count = str_word_count($content);
		$char_count = strlen($content);
		$line_count = substr_count($content, "\n") + 1;

		$analysis .= "- Content length: {$word_count} words, {$char_count} characters\n";
		$analysis .= "- Lines: {$line_count}\n";
		
		// Extract first few sentences as preview
		$sentences = preg_split('/[.!?]+/', $content, -1, PREG_SPLIT_NO_EMPTY);
		if (!empty($sentences)) {
			$preview = trim($sentences[0]);
			if (strlen($preview) > 200) {
				$preview = substr($preview, 0, 200) . '...';
			}
			$analysis .= "- Content preview: {$preview}\n";
		}

		$analysis .= "\nFull content:\n" . $content;

		return $analysis;
	}

	/**
	 * Generate comprehensive file analysis for AI context.
	 *
	 * @param array $files Array of processed files.
	 * @return string Combined file analysis.
	 */
	private function generate_file_analysis($files) {
		if (empty($files)) {
			return '';
		}

		$analysis = "The user has attached " . count($files) . " file(s):\n\n";
		
		foreach ($files as $index => $file) {
			$analysis .= "File " . ($index + 1) . ":\n";
			$analysis .= $file['analysis'] . "\n\n";
		}

		$analysis .= "Please analyze these files and provide helpful insights based on their content. ";
		$analysis .= "If the files contain questions, please answer them. ";
		$analysis .= "If they contain data or information, please summarize and explain the key points.";

		return $analysis;
	}

	/**
	 * Format file size in human readable format.
	 *
	 * @param int $bytes File size in bytes.
	 * @return string Formatted file size.
	 */
	private function format_file_size($bytes) {
		if ($bytes === 0) return '0 Bytes';
		$k = 1024;
		$sizes = array('Bytes', 'KB', 'MB', 'GB');
		$i = floor(log($bytes) / log($k));
		return round($bytes / pow($k, $i), 2) . ' ' . $sizes[$i];
	}

	/**
	 * Log chat history in the database.
	 *
	 * @param string $message The user message.
	 * @param string $response The AI response.
	 * @return void
	 */
	private function log_chat_history( $message, $response ) {
		global $wpdb;
		$table_name = $wpdb->prefix . 'askany_chat_history';

		$wpdb->insert(
			$table_name,
			array(
				'message' => $message,
				'response' => $response,
				'created_at' => current_time('mysql'),
			),
			array( '%s', '%s', '%s' )
		);
	}

	/**
	 * Save plugin settings via AJAX.
	 *
	 * This method processes the settings and updates them in the database.
	 *
	 * @return void
	 */
	public function save_settings() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$settings_json = isset( $_POST['settings'] ) ? sanitize_text_field( wp_unslash( $_POST['settings'] ) ) : '';

		$settings = json_decode( $settings_json, true );

		if ( ! is_array($settings) ) {
			wp_send_json_error(array( 'message' => __('Invalid settings format.', 'askany') ));
			return;
		}

		$api_key = isset( $settings['api_key'] ) ? sanitize_text_field( wp_unslash( $settings['api_key'] ) ) : '';
		$api_provider = isset( $settings['api_provider'] ) ? sanitize_text_field( wp_unslash( $settings['api_provider'] ) ) : 'deepseek';
		$api_model = isset( $settings['api_model'] ) ? sanitize_text_field( wp_unslash( $settings['api_model'] ) ) : '';
		// API URL is no longer user-configurable - providers use their defaults
		$api_enabled = isset( $settings['api_enabled'] ) ? (bool) $settings['api_enabled'] : false;
		$fallback_enabled = isset( $settings['fallback_enabled'] ) ? (bool) $settings['fallback_enabled'] : false;
		$floating_widget_enabled = isset( $settings['floating_widget_enabled'] ) ? (bool) $settings['floating_widget_enabled'] : false;
		$widget_position = isset( $settings['widget_position'] ) ? sanitize_text_field( wp_unslash( $settings['widget_position'] ) ) : 'bottom-right';
		$chat_header_text = isset( $settings['chat_header_text'] ) ? sanitize_text_field( wp_unslash( $settings['chat_header_text'] ) ) : 'Ask Me Anything';
		$assistant_avatar = isset( $settings['assistant_avatar'] ) ? esc_url_raw( wp_unslash( $settings['assistant_avatar'] ) ) : '';
		$contact_form_enabled = isset( $settings['contact_form_enabled'] ) ? (bool) $settings['contact_form_enabled'] : false;
		$contact_form_shortcode = isset( $settings['contact_form_shortcode'] ) ? sanitize_text_field( wp_unslash( $settings['contact_form_shortcode'] ) ) : '';
		$response_language = isset( $settings['response_language'] ) ? sanitize_text_field( wp_unslash( $settings['response_language'] ) ) : 'auto';
		$typing_animation_enabled = isset( $settings['typing_animation_enabled'] ) ? (bool) $settings['typing_animation_enabled'] : false;
		$rag_enabled = isset( $settings['rag_enabled'] ) ? (bool) $settings['rag_enabled'] : false;
		$hybrid_search_enabled = isset( $settings['hybrid_search_enabled'] ) ? (bool) $settings['hybrid_search_enabled'] : false;
		$rag_optimization_enabled = isset( $settings['rag_optimization_enabled'] ) ? (bool) $settings['rag_optimization_enabled'] : false;
		$realtime_enabled = isset( $settings['realtime_enabled'] ) ? (bool) $settings['realtime_enabled'] : true;
		$mobile_bridge_enabled = isset( $settings['mobile_bridge_enabled'] ) ? (bool) $settings['mobile_bridge_enabled'] : false;
		$push_modify_credentials = isset( $settings['push_modify_credentials'] ) ? (bool) $settings['push_modify_credentials'] : false;
		$push_project_id    = isset( $settings['push_project_id'] ) ? sanitize_text_field( wp_unslash( $settings['push_project_id'] ) ) : '';
		$push_client_email  = isset( $settings['push_client_email'] ) ? sanitize_email( wp_unslash( $settings['push_client_email'] ) ) : '';
		$push_sender_id     = isset( $settings['push_sender_id'] ) ? sanitize_text_field( wp_unslash( $settings['push_sender_id'] ) ) : '';
		$push_private_key   = isset( $settings['push_private_key'] ) ? wp_unslash( $settings['push_private_key'] ) : '';

		// Web Search settings
		$web_search_enabled = isset( $settings['web_search_enabled'] ) ? (bool) $settings['web_search_enabled'] : false;
		$web_search_mode    = isset( $settings['web_search_mode'] ) ? sanitize_text_field( wp_unslash( $settings['web_search_mode'] ) ) : 'fallback';
		if ( ! in_array( $web_search_mode, array( 'fallback', 'always' ), true ) ) {
			$web_search_mode = 'fallback';
		}

		// Response Tone
		$response_tone = isset( $settings['response_tone'] ) ? sanitize_text_field( wp_unslash( $settings['response_tone'] ) ) : 'human';
		if ( ! in_array( $response_tone, array( 'human', 'professional', 'friendly', 'robotic' ), true ) ) {
			$response_tone = 'human';
		}

		// Typing Speed
		$typing_speed = isset( $settings['typing_speed'] ) ? sanitize_text_field( wp_unslash( $settings['typing_speed'] ) ) : 'regular';
		if ( ! in_array( $typing_speed, array( 'regular', 'fast', 'faster', 'instant' ), true ) ) {
			$typing_speed = 'regular';
		}

		// Validate Pro features and language selection based on Pro status
		$plugin = \Askany\Plugin::get_instance();
		$is_pro = $plugin->is_pro_active();
		
		// Force disable pro features for free users
		if ( ! $is_pro ) {
			$hybrid_search_enabled = false;
			$rag_optimization_enabled = false;
			$typing_animation_enabled = false;
			$mobile_bridge_enabled = false;
			$push_modify_credentials = false;
			$push_project_id = '';
			$push_client_email = '';
			$push_sender_id = '';
			$push_private_key = '';
		}
		$free_languages = array( 'auto', 'en', 'bn' );
		
		if ( ! $is_pro && ! in_array( $response_language, $free_languages ) ) {
			// User tried to select a Pro language without Pro - revert to auto
			$response_language = 'auto';
		}

		$settings_to_update = array(
			'api_key' => $api_key,
			'api_provider' => $api_provider,
			'api_model' => $api_model,
			// api_url removed - providers use their defaults
			'api_enabled' => $api_enabled,
			'fallback_enabled' => $fallback_enabled,
			'floating_widget_enabled' => $floating_widget_enabled,
			'widget_position' => $widget_position,
			'chat_header_text' => $chat_header_text,
			'assistant_avatar' => $assistant_avatar,
			'contact_form_enabled' => $contact_form_enabled,
			'contact_form_shortcode' => $contact_form_shortcode,
			'response_language' => $response_language,
			'typing_animation_enabled' => $typing_animation_enabled,
			'rag_enabled' => $rag_enabled,
			'hybrid_search_enabled' => $hybrid_search_enabled,
			'rag_optimization_enabled' => $rag_optimization_enabled,
			'realtime_enabled' => $realtime_enabled,
			'mobile_bridge_enabled' => $mobile_bridge_enabled,
			'push_modify_credentials' => $push_modify_credentials,
			'push_project_id'       => $push_project_id,
			'push_client_email'     => $push_client_email,
			'push_sender_id'        => $push_sender_id,
			'push_private_key'      => $push_private_key,
			'web_search_enabled'    => $web_search_enabled,
			'web_search_mode'       => $web_search_mode,
			'response_tone'         => $response_tone,
			'typing_speed'          => $typing_speed,
		);

		$updated = $this->api_manager->update_settings($settings_to_update);

		if ( $updated ) {
			wp_send_json_success(array( 'message' => __('Settings saved successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to save settings.', 'askany') ));
		}
	}


	/**
	 * Save plugin settings via AJAX.
	 *
	 * This method processes the settings and updates them in the database.
	 *
	 * @return void
	 */
	public function reindex_content() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$result = $this->content_indexer->index_content();

		if ( $result ) {
			wp_send_json_success(array(
				'message' => __('Content reindexed successfully.', 'askany'),
				'stats' => $this->content_indexer->get_content_stats(),
			));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to reindex content.', 'askany') ));
		}
	}


	/**
	 * Add, update, delete, and get Q&A pairs via AJAX.
	 *
	 * This method processes the Q&A requests and updates them in the database.
	 *
	 * @return void
	 */
	public function add_qa_pair() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array(
				'message' => __('You do not have permission to perform this action.', 'askany'),
			));
		}

		$question = isset( $_POST['question'] ) ? sanitize_text_field( wp_unslash( $_POST['question'] ) ) : '';
		$answer = isset( $_POST['answer'] ) ? wp_kses_post( wp_unslash( $_POST['answer'] ) ) : '';

		if ( empty($question) || empty($answer) ) {
			wp_send_json_error(array(
				'message' => __('Question and answer are required.', 'askany'),
			));
		}

		// Check Pro limits
		$plugin = \Askany\Plugin::get_instance();
		$is_pro = $plugin->is_pro_active();
		$free_limit = 10;
		
		if ( ! $is_pro ) {
			// Count current Q&A pairs
			$current_qa_pairs = $this->database->get_qa_pairs();
			$qa_count = is_array( $current_qa_pairs ) ? count( $current_qa_pairs ) : 0;
			
			if ( $qa_count >= $free_limit ) {
				wp_send_json_error(array( 
					'message' => sprintf(
						__('Free plan allows up to %d Q&A pairs. Upgrade to Pro for unlimited Q&A pairs.', 'askany'),
						$free_limit
					),
					'is_pro_limit' => true
				));
			}
		}

		$result = $this->database->add_qa_pair($question, $answer);

		if ( $result ) {
			wp_send_json_success(array(
				'message' => __('Q&A pair added successfully.', 'askany'),
			));
		} else {
			wp_send_json_error(array(
				'message' => __('Failed to add Q&A pair.', 'askany'),
			));
		}
	}

	/**
	 * Update Q&A pair via AJAX.
	 *
	 * This method processes the Q&A update request and updates it in the database.
	 *
	 * @return void
	 */
	public function update_qa_pair() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array(
				'message' => __('You do not have permission to perform this action.', 'askany'),
			));
		}

		$id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : 0;
		$question = isset( $_POST['question'] ) ? sanitize_text_field( wp_unslash( $_POST['question'] ) ) : '';
		$answer = isset( $_POST['answer'] ) ? wp_kses_post( wp_unslash( $_POST['answer'] ) ) : '';

		if ( empty($id) || empty($question) || empty($answer) ) {
			wp_send_json_error(array(
				'message' => __('ID, question and answer are required.', 'askany'),
			));
		}

		$result = $this->database->update_qa_pair($id, $question, $answer);

		if ( $result !== false ) {
			wp_send_json_success(array(
				'message' => __('Q&A pair updated successfully.', 'askany'),
			));
		} else {
			wp_send_json_error(array(
				'message' => __('Failed to update Q&A pair.', 'askany'),
			));
		}
	}

	/**
	 * Delete Q&A pair via AJAX.
	 *
	 * This method processes the Q&A delete request and deletes it from the database.
	 *
	 * @return void
	 */
	public function delete_qa_pair() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array(
				'message' => __('You do not have permission to perform this action.', 'askany'),
			));
		}

		$id = isset($_POST['id']) ? intval($_POST['id']) : 0;

		if ( empty($id) ) {
			wp_send_json_error(array(
				'message' => __('Q&A pair ID is required.', 'askany'),
			));
		}

		$result = $this->database->delete_qa_pair($id);

		if ( $result ) {
			wp_send_json_success(array(
				'message' => __('Q&A pair deleted successfully.', 'askany'),
			));
		} else {
			wp_send_json_error(array(
				'message' => __('Failed to delete Q&A pair.', 'askany'),
			));
		}
	}

	/**
	 * Get Q&A pair via AJAX.
	 *
	 * This method processes the Q&A get request and retrieves it from the database.
	 *
	 * @return void
	 */
	public function get_qa_pair() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array(
				'message' => __('You do not have permission to perform this action.', 'askany'),
			));
		}

		$id = isset($_POST['id']) ? intval($_POST['id']) : 0;

		if ( empty($id) ) {
			wp_send_json_error(array(
				'message' => __('Q&A pair ID is required.', 'askany'),
			));
		}

		$qa_pair = $this->database->get_qa_pair($id);

		if ( $qa_pair ) {
			wp_send_json_success(array(
				'qa_pair' => $qa_pair,
			));
		} else {
			wp_send_json_error(array(
				'message' => __('Q&A pair not found.', 'askany'),
			));
		}
	}

	/**
	 * Export Q&A pairs via AJAX.
	 *
	 * @return void
	 */
	public function export_qa_pairs() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array(
				'message' => __('You do not have permission to export Q&A pairs.', 'askany'),
			));
		}

		$format = isset($_POST['format']) ? sanitize_text_field($_POST['format']) : 'json';

		// Get all Q&A pairs
		$qa_pairs = $this->database->get_qa_pairs();

		if ( empty($qa_pairs) ) {
			wp_send_json_error(array(
				'message' => __('No Q&A pairs found to export.', 'askany'),
			));
		}

		// Prepare data for export
		$export_data = array();
		foreach ( $qa_pairs as $qa_pair ) {
			$export_data[] = array(
				'question' => $qa_pair->question,
				'answer' => $qa_pair->answer,
				'created_at' => $qa_pair->created_at,
			);
		}

		$filename = 'askany-qa-pairs-' . date('Y-m-d-H-i-s');
		$content = '';

		if ( $format === 'csv' ) {
			$filename .= '.csv';
			
			// Create CSV content
			$output = fopen('php://temp', 'r+');
			
			// Add CSV headers
			fputcsv($output, array('Question', 'Answer', 'Created At'));
			
			// Add data rows
			foreach ( $export_data as $row ) {
				fputcsv($output, array(
					$row['question'],
					$row['answer'],
					$row['created_at']
				));
			}
			
			rewind($output);
			$content = stream_get_contents($output);
			fclose($output);
		} else {
			$filename .= '.json';
			$content = wp_json_encode($export_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
		}

		wp_send_json_success(array(
			'content' => $content,
			'filename' => $filename,
			'count' => count($export_data),
		));
	}

	/**
	 * Import Q&A pairs via AJAX.
	 *
	 * @return void
	 */
	public function import_qa_pairs() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array(
				'message' => __('You do not have permission to import Q&A pairs.', 'askany'),
			));
		}

		if ( ! isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK ) {
			wp_send_json_error(array(
				'message' => __('No file uploaded or upload error occurred.', 'askany'),
			));
		}

		$file = $_FILES['file'];
		$file_extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));

		if ( ! in_array($file_extension, array('json', 'csv')) ) {
			wp_send_json_error(array(
				'message' => __('Invalid file format. Only JSON and CSV files are supported.', 'askany'),
			));
		}

		$file_content = file_get_contents($file['tmp_name']);
		if ( $file_content === false ) {
			wp_send_json_error(array(
				'message' => __('Failed to read uploaded file.', 'askany'),
			));
		}

		$import_data = array();

		if ( $file_extension === 'json' ) {
			$decoded_data = json_decode($file_content, true);
			
			if ( json_last_error() !== JSON_ERROR_NONE ) {
				wp_send_json_error(array(
					'message' => __('Invalid JSON file format.', 'askany'),
				));
			}

			if ( ! is_array($decoded_data) ) {
				wp_send_json_error(array(
					'message' => __('JSON file must contain an array of Q&A pairs.', 'askany'),
				));
			}

			$import_data = $decoded_data;
		} else {
			// Parse CSV
			$lines = str_getcsv($file_content, "\n");
			$header = null;
			
			foreach ( $lines as $line ) {
				$row = str_getcsv($line);
				
				if ( $header === null ) {
					$header = $row;
					continue;
				}
				
				if ( count($row) >= 2 ) {
					$import_data[] = array(
						'question' => $row[0],
						'answer' => $row[1],
						'created_at' => isset($row[2]) ? $row[2] : current_time('mysql'),
					);
				}
			}
		}

		if ( empty($import_data) ) {
			wp_send_json_error(array(
				'message' => __('No valid Q&A pairs found in the file.', 'askany'),
			));
		}

		// Check Pro limits for free users
		$plugin = \Askany\Plugin::get_instance();
		$is_pro = $plugin->is_pro_active();
		$free_limit = 10;

		if ( ! $is_pro ) {
			$current_qa_pairs = $this->database->get_qa_pairs();
			$current_count = is_array($current_qa_pairs) ? count($current_qa_pairs) : 0;
			$new_count = count($import_data);
			
			if ( ($current_count + $new_count) > $free_limit ) {
				wp_send_json_error(array(
					'message' => sprintf(
						__('Import would exceed the free limit of %d Q&A pairs. You currently have %d pairs and are trying to import %d pairs. Please upgrade to Pro for unlimited Q&A pairs.', 'askany'),
						$free_limit,
						$current_count,
						$new_count
					),
				));
			}
		}

		// Import Q&A pairs
		$imported_count = 0;
		$updated_count = 0;
		$errors = array();

		foreach ( $import_data as $index => $qa_data ) {
			if ( ! isset($qa_data['question']) || ! isset($qa_data['answer']) ) {
				$errors[] = sprintf(__('Row %d: Missing question or answer.', 'askany'), $index + 1);
				continue;
			}

			$question = sanitize_text_field($qa_data['question']);
			$answer = wp_kses_post($qa_data['answer']);

			if ( empty($question) || empty($answer) ) {
				$errors[] = sprintf(__('Row %d: Question and answer cannot be empty.', 'askany'), $index + 1);
				continue;
			}

			// Check if Q&A pair with same question already exists
			$existing_qa = $this->database->find_qa_match($question);
			
			if ( $existing_qa ) {
				// Update existing Q&A pair
				$result = $this->database->update_qa_pair($existing_qa->id, $question, $answer);
				if ( $result !== false ) {
					$updated_count++;
				} else {
					$errors[] = sprintf(__('Row %d: Failed to update existing Q&A pair.', 'askany'), $index + 1);
				}
			} else {
				// Add new Q&A pair
				$result = $this->database->add_qa_pair($question, $answer);
				if ( $result ) {
					$imported_count++;
				} else {
					$errors[] = sprintf(__('Row %d: Failed to add new Q&A pair.', 'askany'), $index + 1);
				}
			}
		}

		$message = '';
		if ( $imported_count > 0 ) {
			$message .= sprintf(__('%d Q&A pairs imported successfully. ', 'askany'), $imported_count);
		}
		if ( $updated_count > 0 ) {
			$message .= sprintf(__('%d existing Q&A pairs updated. ', 'askany'), $updated_count);
		}
		if ( ! empty($errors) ) {
			$message .= sprintf(__('%d errors occurred during import.', 'askany'), count($errors));
		}

		if ( $imported_count > 0 || $updated_count > 0 ) {
			wp_send_json_success(array(
				'message' => $message,
				'imported' => $imported_count,
				'updated' => $updated_count,
				'errors' => $errors,
			));
		} else {
			wp_send_json_error(array(
				'message' => $message ?: __('Import failed. No Q&A pairs were processed.', 'askany'),
				'errors' => $errors,
			));
		}
	}

	/**
	 * Process uploaded PDF file via AJAX.
	 *
	 * @return void
	 */
	public function process_pdf() {
		check_ajax_referer( 'askany_chat_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to perform this action.', 'askany' ) ) );
		}

		if ( ! isset( $_FILES['pdf_file'] ) ) {
			wp_send_json_error( array( 'message' => __( 'No PDF file uploaded.', 'askany' ) ) );
		}

		// Sanitize and validate file data.
		// Note: For file uploads, we can't directly sanitize the file content,
		// but we validate it through proper checks.
		$file = array(
			'name'     => isset( $_FILES['pdf_file']['name'] ) ? sanitize_file_name( wp_unslash( $_FILES['pdf_file']['name'] ) ) : '',
			'type'     => isset( $_FILES['pdf_file']['type'] ) ? sanitize_text_field( wp_unslash( $_FILES['pdf_file']['type'] ) ) : '',
			'tmp_name' => isset( $_FILES['pdf_file']['tmp_name'] ) ? $_FILES['pdf_file']['tmp_name'] : '', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- No appropriate direct sanitization function for file paths
			'error'    => isset( $_FILES['pdf_file']['error'] ) ? (int) $_FILES['pdf_file']['error'] : UPLOAD_ERR_NO_FILE,
			'size'     => isset( $_FILES['pdf_file']['size'] ) ? (int) $_FILES['pdf_file']['size'] : 0,
		);

		// Using Yoda condition
		if ( UPLOAD_ERR_OK !== $file['error'] ) {
			wp_send_json_error( array( 'message' => __( 'Error uploading file.', 'askany' ) ) );
		}

		// Check file type and use Yoda condition
		$file_type = wp_check_filetype( basename( $file['name'] ), array( 'pdf' => 'application/pdf' ) );
		if ( 'application/pdf' !== $file_type['type'] ) {
			wp_send_json_error( array( 'message' => __( 'Invalid file type. Please upload a PDF file.', 'askany' ) ) );
		}

		// Process PDF file.
		$result = $this->pdf_handler->process_pdf( $file );

		if ( $result ) {
			wp_send_json_success( array(
				'message'  => __( 'PDF processed successfully.', 'askany' ),
				'pdf_info' => $result,
				'stats'    => $this->pdf_handler->get_pdf_stats(),
			) );
		} else {
			wp_send_json_error( array( 'message' => __( 'Failed to process PDF file.', 'askany' ) ) );
		}
	}

	/**
	 * Process PDF file upload via AJAX.
	 *
	 * This method processes the PDF file upload and updates it in the database.
	 *
	 * @return void
	 */
	public function delete_pdf() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$pdf_id = isset($_POST['pdf_id']) ? intval($_POST['pdf_id']) : 0;

		if ( ! $pdf_id ) {
			wp_send_json_error(array( 'message' => __('Invalid PDF ID.', 'askany') ));
		}

		$result = $this->pdf_handler->delete_pdf($pdf_id);

		if ( $result ) {
			wp_send_json_success(array(
				'message' => __('PDF deleted successfully.', 'askany'),
				'stats' => $this->pdf_handler->get_pdf_stats(),
			));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to delete PDF.', 'askany') ));
		}
	}

	/**
	 * Clear chat history via AJAX.
	 *
	 * This method clears the chat history from the database.
	 *
	 * @return void
	 */
	public function clear_chat_all_history() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		global $wpdb;
		$table_name = $wpdb->prefix . 'askany_chat_history';

		$result = $wpdb->query("TRUNCATE TABLE {$table_name}");

		if ( $result !== false ) {
			wp_send_json_success(array( 'message' => __('Chat history cleared.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to clear chat history.', 'askany') ));
		}
	}

	/**
	 * Get available models for a provider via AJAX.
	 *
	 * @return void
	 */
	public function get_provider_models() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$provider = isset($_POST['provider']) ? sanitize_text_field( wp_unslash( $_POST['provider']) ) : 'deepseek';

		// Create provider instance to get models
		$provider_instance = \Askany\Providers\ProviderFactory::create( $provider, 'dummy_key', '' );

		if ( ! $provider_instance ) {
			wp_send_json_error(array( 'message' => __('Invalid provider.', 'askany') ));
		}

		$models = $provider_instance->get_available_models();
		$default_model = $provider_instance->get_default_model();

		wp_send_json_success(array(
			'models' => $models,
			'default_model' => $default_model,
		));
	}

	/**
	 * Get provider settings via AJAX.
	 *
	 * This method retrieves the API key and URL based on the selected provider.
	 *
	 * @return void
	 */
	public function get_provider_settings() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$provider = isset($_POST['provider']) ? sanitize_text_field( wp_unslash( $_POST['provider']) ) : 'deepseek';

		// Get the appropriate API key and URL based on provider.
		$api_key = '';
		$api_url = '';

		switch ( $provider ) {
			case 'openai':
				$api_key = get_option('askany_api_key_openai', '');
				$api_url = get_option('askany_api_url_openai', '');
				// Use default if empty
				if ( empty( $api_url ) ) {
					$api_url = 'https://api.openai.com/v1/chat/completions';
				}
				break;
			case 'claude':
				$api_key = get_option('askany_api_key_claude', '');
				$api_url = get_option('askany_api_url_claude', '');
				// Use default if empty
				if ( empty( $api_url ) ) {
					$api_url = 'https://api.anthropic.com/v1/messages';
				}
				break;
			case 'gemini':
				$api_key = get_option('askany_api_key_gemini', '');
				$api_url = get_option('askany_api_url_gemini', '');
				// Use default if empty
				if ( empty( $api_url ) ) {
					$api_url = 'https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent';
				}
				break;
			case 'grok':
				$api_key = get_option('askany_api_key_grok', '');
				$api_url = get_option('askany_api_url_grok', '');
				// Use default if empty
				if ( empty( $api_url ) ) {
					$api_url = 'https://api.x.ai/v1/chat/completions';
				}
				break;
			case 'openrouter':
				$api_key = get_option('askany_api_key_openrouter', '');
				$api_url = get_option('askany_api_url_openrouter', '');
				// Use default if empty
				if ( empty( $api_url ) ) {
					$api_url = 'https://openrouter.ai/api/v1/chat/completions';
				}
				break;
			case 'deepseek':
			default:
				$api_key = get_option('askany_api_key_deepseek', '');
				$api_url = get_option('askany_api_url_deepseek', '');
				// Use default if empty
				if ( empty( $api_url ) ) {
					$api_url = 'https://api.deepseek.com/v1/chat/completions';
				}
				break;
		}

		// Get selected model
		$api_model = get_option('askany_api_model', '');

		wp_send_json_success(array(
			'api_key' => $api_key,
			'api_url' => $api_url,
			'api_model' => $api_model,
		));
	}

	/**
	 * Get provider settings via AJAX.
	 *
	 * This method retrieves the API key and URL based on the selected provider.
	 *
	 * @return void
	 */
	public function test_api_connection() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$provider = isset( $_POST['provider'] ) ? sanitize_text_field( wp_unslash( $_POST['provider'] ) ) : 'deepseek';
		$api_key = isset( $_POST['api_key'] ) ? sanitize_text_field( wp_unslash( $_POST['api_key'] ) ) : '';
		$api_model = isset( $_POST['api_model'] ) ? sanitize_text_field( wp_unslash( $_POST['api_model'] ) ) : '';

		if ( empty( $api_key ) ) {
			wp_send_json_error( array( 'message' => __( 'API key is required.', 'askany' ) ) );
		}

		// Always use empty URL - let provider use its default
		$api_url = '';

		// Create provider instance for testing without modifying saved settings
		$provider_instance = \Askany\Providers\ProviderFactory::create( $provider, $api_key, $api_url );

		if ( ! $provider_instance ) {
			wp_send_json_error( array( 'message' => __( 'Invalid provider selected.', 'askany' ) ) );
		}

		// Pass model to test connection
		$test_options = array();
		if ( ! empty( $api_model ) ) {
			$test_options['model'] = $api_model;
		}

		$result = $provider_instance->test_connection( $test_options );

		if ( 'success' === $result['status'] ) {
			wp_send_json_success( $result );
		} else {
			wp_send_json_error( $result );
		}
	}

	/**
	 * Test Firebase FCM V1 connection by attempting to get an OAuth2 access token.
	 *
	 * @return void
	 */
	public function test_fcm_connection() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error( array( 'message' => __('You do not have permission to perform this action.', 'askany') ) );
		}

		$project_id   = isset( $_POST['project_id'] )   ? sanitize_text_field( wp_unslash( $_POST['project_id'] ) )   : '';
		$client_email = isset( $_POST['client_email'] ) ? sanitize_email( wp_unslash( $_POST['client_email'] ) )       : '';
		$sender_id    = isset( $_POST['sender_id'] )    ? sanitize_text_field( wp_unslash( $_POST['sender_id'] ) )     : '';
		$private_key  = isset( $_POST['private_key'] )  ? wp_unslash( $_POST['private_key'] )                         : '';

		// Normalize private key: replace literal \n strings with real newlines (common when copying from JSON)
		$private_key = str_replace( '\\n', "\n", $private_key );
		$private_key = trim( $private_key );

		// Validate all fields are present
		$missing = array();
		if ( empty( $project_id ) )   $missing[] = 'Project ID';
		if ( empty( $client_email ) ) $missing[] = 'Client Email';
		if ( empty( $sender_id ) )    $missing[] = 'Sender ID';
		if ( empty( $private_key ) )  $missing[] = 'Private Key';

		if ( ! empty( $missing ) ) {
			wp_send_json_error( array(
				'message' => sprintf( __('Missing required fields: %s', 'askany'), implode(', ', $missing) ),
			) );
		}

		// Attempt to get an OAuth2 access token using the service account credentials
		$now = time();
		$exp = $now + 3600;

		$header = rtrim( strtr( base64_encode( wp_json_encode( array( 'alg' => 'RS256', 'typ' => 'JWT' ) ) ), '+/', '-_' ), '=' );
		$claims = rtrim( strtr( base64_encode( wp_json_encode( array(
			'iss'   => $client_email,
			'scope' => 'https://www.googleapis.com/auth/firebase.messaging',
			'aud'   => 'https://oauth2.googleapis.com/token',
			'iat'   => $now,
			'exp'   => $exp,
		) ) ), '+/', '-_' ), '=' );

		$signing_input        = $header . '.' . $claims;
		$private_key_resource = openssl_pkey_get_private( $private_key );

		if ( ! $private_key_resource ) {
			wp_send_json_error( array(
				'message' => __('Invalid Private Key. Make sure you pasted the full key including the -----BEGIN RSA PRIVATE KEY----- header and footer.', 'askany'),
				'checks'  => array(
					'project_id'   => ! empty( $project_id ),
					'client_email' => ! empty( $client_email ),
					'sender_id'    => ! empty( $sender_id ),
					'private_key'  => false,
				),
			) );
		}

		$signature = '';
		if ( ! openssl_sign( $signing_input, $signature, $private_key_resource, OPENSSL_ALGO_SHA256 ) ) {
			wp_send_json_error( array( 'message' => __('Failed to sign JWT with the provided private key.', 'askany') ) );
		}

		$jwt = $signing_input . '.' . rtrim( strtr( base64_encode( $signature ), '+/', '-_' ), '=' );

		$response = wp_remote_post( 'https://oauth2.googleapis.com/token', array(
			'body'    => array(
				'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
				'assertion'  => $jwt,
			),
			'timeout' => 15,
		) );

		if ( is_wp_error( $response ) ) {
			wp_send_json_error( array(
				'message' => __('Network error connecting to Google OAuth2: ', 'askany') . $response->get_error_message(),
			) );
		}

		$body = json_decode( wp_remote_retrieve_body( $response ), true );
		$code = wp_remote_retrieve_response_code( $response );

		if ( ! empty( $body['access_token'] ) ) {
			wp_send_json_success( array(
				'message'      => __('Firebase FCM connection successful! All credentials are valid.', 'askany'),
				'checks'       => array(
					'project_id'   => true,
					'client_email' => true,
					'sender_id'    => true,
					'private_key'  => true,
				),
				'project_id'   => $project_id,
				'client_email' => $client_email,
				'sender_id'    => $sender_id,
			) );
		} else {
			$error_desc = isset( $body['error_description'] ) ? $body['error_description'] : ( isset( $body['error'] ) ? $body['error'] : __('Unknown error', 'askany') );
			wp_send_json_error( array(
				'message' => sprintf( __('Google OAuth2 rejected the credentials (HTTP %d): %s', 'askany'), $code, $error_desc ),
				'checks'  => array(
					'project_id'   => ! empty( $project_id ),
					'client_email' => ! empty( $client_email ),
					'sender_id'    => ! empty( $sender_id ),
					'private_key'  => ! empty( $private_key ),
				),
			) );
		}
	}

	/**
	 * Send a test push notification to a specific FCM device token.
	 *
	 * @return void
	 */
	public function send_test_push() {
		check_ajax_referer( 'askany_chat_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Permission denied.', 'askany' ) ) );
		}

		$device_token = isset( $_POST['device_token'] ) ? sanitize_text_field( wp_unslash( $_POST['device_token'] ) ) : '';

		if ( empty( $device_token ) ) {
			wp_send_json_error( array( 'message' => __( 'Device token is required.', 'askany' ) ) );
		}

		// Load credentials from saved options
		$project_id   = get_option( 'askany_push_project_id', '' );
		$client_email = get_option( 'askany_push_client_email', '' );
		$private_key  = str_replace( '\\n', "\n", get_option( 'askany_push_private_key', '' ) );

		if ( empty( $project_id ) || empty( $client_email ) || empty( $private_key ) ) {
			wp_send_json_error( array( 'message' => __( 'Firebase credentials are not configured. Please save your credentials first.', 'askany' ) ) );
		}

		// Get OAuth2 access token
		$now    = time();
		$header = rtrim( strtr( base64_encode( wp_json_encode( array( 'alg' => 'RS256', 'typ' => 'JWT' ) ) ), '+/', '-_' ), '=' );
		$claims = rtrim( strtr( base64_encode( wp_json_encode( array(
			'iss'   => $client_email,
			'scope' => 'https://www.googleapis.com/auth/firebase.messaging',
			'aud'   => 'https://oauth2.googleapis.com/token',
			'iat'   => $now,
			'exp'   => $now + 3600,
		) ) ), '+/', '-_' ), '=' );

		$signing_input        = $header . '.' . $claims;
		$private_key_resource = openssl_pkey_get_private( $private_key );

		if ( ! $private_key_resource ) {
			wp_send_json_error( array( 'message' => __( 'Invalid private key. Please re-save your credentials.', 'askany' ) ) );
		}

		$signature = '';
		openssl_sign( $signing_input, $signature, $private_key_resource, OPENSSL_ALGO_SHA256 );
		$jwt = $signing_input . '.' . rtrim( strtr( base64_encode( $signature ), '+/', '-_' ), '=' );

		$token_response = wp_remote_post( 'https://oauth2.googleapis.com/token', array(
			'body'    => array(
				'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
				'assertion'  => $jwt,
			),
			'timeout' => 15,
		) );

		if ( is_wp_error( $token_response ) ) {
			wp_send_json_error( array( 'message' => __( 'Failed to get access token: ', 'askany' ) . $token_response->get_error_message() ) );
		}

		$token_body   = json_decode( wp_remote_retrieve_body( $token_response ), true );
		$access_token = $token_body['access_token'] ?? '';

		if ( empty( $access_token ) ) {
			wp_send_json_error( array( 'message' => __( 'Could not obtain access token from Google.', 'askany' ) ) );
		}

		// Send the test notification via FCM V1
		$payload = array(
			'message' => array(
				'token'        => $device_token,
				'notification' => array(
					'title' => '🔔 AskAny Test Notification',
					'body'  => 'Push notifications are working correctly from ' . get_bloginfo( 'name' ) . '!',
				),
				'data' => array(
					'type'     => 'test',
					'site_url' => get_site_url(),
					'sent_at'  => (string) $now,
				),
				'android' => array( 'priority' => 'high' ),
				'apns'    => array( 'headers' => array( 'apns-priority' => '10' ) ),
			),
		);

		$fcm_url      = 'https://fcm.googleapis.com/v1/projects/' . rawurlencode( $project_id ) . '/messages:send';
		$fcm_response = wp_remote_post( $fcm_url, array(
			'headers' => array(
				'Authorization' => 'Bearer ' . $access_token,
				'Content-Type'  => 'application/json',
			),
			'body'    => wp_json_encode( $payload ),
			'timeout' => 15,
		) );

		if ( is_wp_error( $fcm_response ) ) {
			wp_send_json_error( array( 'message' => __( 'FCM request failed: ', 'askany' ) . $fcm_response->get_error_message() ) );
		}

		$fcm_body = json_decode( wp_remote_retrieve_body( $fcm_response ), true );
		$fcm_code = wp_remote_retrieve_response_code( $fcm_response );

		if ( $fcm_code === 200 && ! empty( $fcm_body['name'] ) ) {
			wp_send_json_success( array(
				'message'    => __( 'Test notification sent successfully!', 'askany' ),
				'message_id' => $fcm_body['name'],
			) );
		} else {
			$error = $fcm_body['error']['message'] ?? __( 'Unknown FCM error', 'askany' );
			$status = $fcm_body['error']['status'] ?? '';
			wp_send_json_error( array(
				'message' => sprintf( __( 'FCM rejected the request (HTTP %d): %s', 'askany' ), $fcm_code, $error ),
				'status'  => $status,
				'hint'    => $status === 'INVALID_ARGUMENT' ? __( 'The device token may be invalid or expired. Get a fresh token from the mobile app.', 'askany' ) : '',
			) );
		}
	}


	/**
	 * Add user as agent via AJAX.
	 *
	 * @return void
	 */
	public function add_agent() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;

		if ( ! $user_id ) {
			wp_send_json_error(array( 'message' => __('Invalid user ID.', 'askany') ));
		}

		// Check Pro limits
		$plugin = \Askany\Plugin::get_instance();
		$is_pro = $plugin->is_pro_active();
		$free_limit = 2;
		
		if ( ! $is_pro ) {
			// Count current agents
			$current_agents = $this->database->get_agents();
			$agent_count = is_array( $current_agents ) ? count( $current_agents ) : 0;
			
			if ( $agent_count >= $free_limit ) {
				wp_send_json_error(array( 
					'message' => sprintf(
						__('Free plan allows up to %d agents. Upgrade to Pro for unlimited agents.', 'askany'),
						$free_limit
					),
					'is_pro_limit' => true
				));
			}
		}

		$result = $this->database->add_user_agent($user_id);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('User added as agent successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to add user as agent.', 'askany') ));
		}
	}

	/**
	 * Remove user as agent via AJAX.
	 *
	 * @return void
	 */
	public function remove_agent() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;

		if ( ! $user_id ) {
			wp_send_json_error(array( 'message' => __('Invalid user ID.', 'askany') ));
		}

		$result = $this->database->remove_user_agent($user_id);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('Agent removed successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to remove agent.', 'askany') ));
		}
	}

	/**
	 * Get chat sessions via AJAX.
	 *
	 * @return void
	 */
	public function get_chat_sessions() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$sessions = $this->database->get_active_chat_sessions();

		// Add unread count for each session
		if ( $sessions ) {
			foreach ( $sessions as &$session ) {
				$session->unread_count = $this->database->get_unread_message_count( $session->session_id, 'user' );
			}
		}

		wp_send_json_success(array( 'sessions' => $sessions ));
	}

	/**
	 * Get chat messages via AJAX.
	 *
	 * @return void
	 */
	public function get_chat_messages() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		$messages = $this->database->get_chat_messages($session_id);
		$session = $this->database->get_chat_session($session_id);

		// Decrypt encrypted messages for admin display and add avatar URLs
		if ( $messages ) {
			foreach ( $messages as &$message ) {
				$message->message = $this->decrypt_message_for_admin($message->message);
				
				// Add avatar URL based on sender type
				if ( $message->sender_type === 'user' ) {
					if ( ! empty( $message->user_id ) && $message->user_id > 0 ) {
						// Logged-in user - get WordPress avatar URL
						$message->avatar_url = get_avatar_url( $message->user_id, array( 'size' => 32 ) );
					} else {
						// Guest user - no avatar URL (will use default icon)
						$message->avatar_url = '';
					}
				} elseif ( $message->sender_type === 'agent' ) {
					if ( ! empty( $message->sender_id ) ) {
						// Agent - get WordPress avatar URL
						$message->avatar_url = get_avatar_url( $message->sender_id, array( 'size' => 32 ) );
					} else {
						// No sender ID - use default icon
						$message->avatar_url = '';
					}
				} else {
					// AI assistant - get custom avatar or use default
					$assistant_avatar = get_option( 'askany_assistant_avatar', '' );
					$message->avatar_url = ! empty( $assistant_avatar ) ? esc_url( $assistant_avatar ) : '';
				}
			}
		}

		wp_send_json_success(array(
			'messages' => $messages,
			'session' => $session,
		));
	}

	/**
	 * Decrypt message for admin display
	 *
	 * @param string $message The potentially encrypted message
	 * @return string The decrypted message or original if not encrypted
	 */
	private function decrypt_message_for_admin($message) {
		// With the new system, messages are decoded during processing and stored as readable text
		// in the database, so admins can read them directly.
		
		// Check if this is a legacy encrypted message that needs special handling
		if (EncryptionHandler::is_encrypted_data($message) && strlen($message) > 50) {
			// This might be a legacy encrypted message from the old system
			try {
				// Try to deobfuscate legacy encrypted messages
				$deobfuscated = EncryptionHandler::deobfuscate_data($message);
				if ($deobfuscated !== $message && strlen($deobfuscated) < strlen($message)) {
					// Successfully deobfuscated, but still might be encrypted
					if (EncryptionHandler::is_base64_encoded($deobfuscated)) {
						// Try to decode as base64
						$decoded = EncryptionHandler::decode_base64_message($deobfuscated);
						if ($decoded !== $deobfuscated && !EncryptionHandler::is_base64_encoded($decoded)) {
							return $decoded; // Successfully decoded
						}
					}
					return '🔒 [LEGACY ENCRYPTED MESSAGE - Content secured]';
				}
			} catch (Exception $e) {
				EncryptionHandler::log_encryption_event('ADMIN_LEGACY_DECRYPT', 'Found legacy encrypted message', array(
					'message_length' => strlen($message)
				));
			}
			
			return '🔒 [LEGACY ENCRYPTED MESSAGE - Content secured]';
		}
		
		// Return message as-is (should be readable text from new system)
		return $message;
	}

	/**
	 * Get session info via AJAX for frontend.
	 *
	 * @return void
	 */
	public function get_session_info() {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		
		if ( ! wp_verify_nonce($nonce, 'askany_chat_nonce') ) {
			wp_send_json_error(array( 'message' => __('Security check failed.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		$session = $this->database->get_chat_session($session_id);

		if ( ! $session ) {
			wp_send_json_error(array( 'message' => __('Session not found.', 'askany') ));
		}

		// Return session info including agent status
		wp_send_json_success(array(
			'session_id' => $session->session_id,
			'is_ai_handled' => (bool) $session->is_ai_handled,
			'agent_id' => $session->agent_id,
			'has_agent' => ! empty($session->agent_id),
		));
	}

	/**
	 * Get all messages for a session via AJAX.
	 *
	 * @return void
	 */
	public function get_all_messages() {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		
		if ( ! wp_verify_nonce($nonce, 'askany_chat_nonce') ) {
			wp_send_json_error(array( 'message' => __('Security check failed.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		// Get all messages for this session ordered by timestamp
		$messages = $this->database->get_chat_messages($session_id);

		if ( ! $messages ) {
			wp_send_json_success(array( 'messages' => array() ));
		}

		// Return messages in chronological order
		wp_send_json_success(array( 'messages' => $messages ));
	}

	/**
	 * Save user message only (without AI processing) via AJAX.
	 *
	 * @return void
	 */
	public function save_user_message() {
		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		
		if ( ! wp_verify_nonce($nonce, 'askany_chat_nonce') ) {
			wp_send_json_error(array( 'message' => __('Security check failed.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
		$message = isset($_POST['message']) ? sanitize_text_field( wp_unslash( $_POST['message'] ) ) : '';

		if ( empty($session_id) || empty($message) ) {
			wp_send_json_error(array( 'message' => __('Session ID and message are required.', 'askany') ));
		}

		$current_user_id = get_current_user_id();

		// Ensure we have a valid session ID
		if (empty($session_id)) {
			$session_id = 'user_' . $current_user_id . '_' . time();
		}

		// Get user data for session creation
		$user_data = array();
		if ( isset($_POST['user_name']) ) {
			$user_data['name'] = sanitize_text_field( wp_unslash( $_POST['user_name'] ) );
		}
		if ( isset($_POST['user_email']) ) {
			$user_data['email'] = sanitize_email( wp_unslash( $_POST['user_email'] ) );
		}

		// Check if session already exists before creating/updating
		$existing_session = $this->database->get_chat_session($session_id);
		
		if (!$existing_session) {
			// Create new session only if it doesn't exist
			$this->database->create_chat_session($session_id, $user_data);
		} else {
			// Update last activity for existing session without changing agent assignment
			global $wpdb;
			$wpdb->update(
				$wpdb->prefix . 'askany_chat_sessions',
				array('last_activity' => current_time('mysql')),
				array('session_id' => $session_id),
				array('%s'),
				array('%s')
			);
		}

		// Save user message only
		$result = $this->database->save_chat_message($session_id, 'user', $current_user_id, $message);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('Message saved successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to save message.', 'askany') ));
		}
	}

	/**
	 * Assign agent to chat session via AJAX.
	 *
	 * @return void
	 */
	public function assign_agent() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
		$agent_id = isset($_POST['agent_id']) ? intval($_POST['agent_id']) : 0;

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		if ( $agent_id ) {
			$result = $this->database->assign_agent_to_session($session_id, $agent_id);
			$message = __('Agent assigned successfully.', 'askany');
			
			// Send notification message to user about agent assignment
			if ( $result ) {
				$agent = get_user_by('id', $agent_id);
				$agent_name = $agent ? $agent->display_name : __('An agent', 'askany');
				$notification_message = sprintf(
					__('👋 %s has joined the chat and will assist you now. Your messages will be handled by our live support team.', 'askany'),
					$agent_name
				);
				
				// Save the notification message
				$this->database->save_chat_message($session_id, 'system', null, $notification_message);
				
				// Small delay to ensure message is saved before response
				usleep(100000); // 0.1 seconds
			}
		} else {
			$result = $this->database->release_agent_from_session($session_id);
			$message = __('Session released to AI successfully.', 'askany');
			
			// Send notification message to user about AI takeover
			if ( $result ) {
				$notification_message = __('🤖 You are now chatting with our AI assistant. Your messages will be handled automatically.', 'askany');
				
				// Save the notification message
				$this->database->save_chat_message($session_id, 'system', null, $notification_message);
				
				// Small delay to ensure message is saved before response
				usleep(100000); // 0.1 seconds
			}
		}

		if ( $result ) {
			wp_send_json_success(array( 'message' => $message ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to update session.', 'askany') ));
		}
	}

	/**
	 * Release agent from chat session via AJAX.
	 *
	 * @return void
	 */
	public function release_agent() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		$result = $this->database->release_agent_from_session($session_id);

		if ( $result ) {
			// Send notification message to user about AI takeover
			$notification_message = __('🤖 You are now chatting with our AI assistant. Your messages will be handled automatically.', 'askany');
			$this->database->save_chat_message($session_id, 'system', null, $notification_message);
			
			// Small delay to ensure message is saved before response
			usleep(100000); // 0.1 seconds
			
			wp_send_json_success(array( 'message' => __('Session released to AI successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to release session.', 'askany') ));
		}
	}

	/**
	 * Send agent message via AJAX.
	 *
	 * @return void
	 */
	public function send_agent_message() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
		$message = isset($_POST['message']) ? wp_kses_post( wp_unslash( $_POST['message'] ) ) : '';

		if ( empty($session_id) || empty($message) ) {
			wp_send_json_error(array( 'message' => __('Session ID and message are required.', 'askany') ));
		}

		$current_user_id = get_current_user_id();
		$result = $this->database->save_chat_message($session_id, 'agent', $current_user_id, $message);

		if ( $result ) {
			// Fire hook for push notifications
			do_action('askany_after_message_saved', $session_id, 'agent', $message);

			wp_send_json_success(array( 'message' => __('Message sent successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to send message.', 'askany') ));
		}
	}

	/**
	 * Merge anonymous session with user account via AJAX.
	 *
	 * @return void
	 */
	public function merge_session() {

		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		if (!wp_verify_nonce($nonce, 'askany_chat_nonce')) {
			wp_send_json_error(array('message' => __('Security check failed.', 'askany')));
			return;
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
		$old_session_id = isset($_POST['old_session_id']) ? sanitize_text_field( wp_unslash( $_POST['old_session_id'] ) ) : '';

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		$current_user_id = get_current_user_id();
		if ( ! $current_user_id ) {
			wp_send_json_error(array( 'message' => __('User must be logged in.', 'askany') ));
		}

		// Get current user info for session name update
		$current_user = wp_get_current_user();
		$user_name = $current_user->display_name ?: $current_user->user_login;

		$result = $this->database->merge_session_with_user($session_id, $current_user_id);

		// Also update the session name from anonymous to logged-in user name
		if ( $result && $user_name ) {
			$this->database->update_session_user_name($session_id, $user_name);
		}

		if ( $result ) {
			wp_send_json_success(array( 
				'message' => __('Session merged successfully.', 'askany'),
				'user_name' => $user_name
			));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to merge session.', 'askany') ));
		}
	}



	/**
	 * Set typing indicator via AJAX.
	 *
	 * @return void
	 */
	public function set_typing_indicator() {

		$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
		$is_admin_request = current_user_can('manage_options');
		
		$nonce_valid = false;
		if ($is_admin_request) {
			// For admin requests, check admin nonce
			$nonce_valid = wp_verify_nonce($nonce, 'askany_chat_nonce');
		} else {
			// For frontend requests, check chat nonce
			$nonce_valid = wp_verify_nonce($nonce, 'askany_chat_nonce');
		}
		
		if (!$nonce_valid) {
			wp_send_json_error(array('message' => __('Security check failed.', 'askany')));
			return;
		}
		
		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
		$is_typing = isset($_POST['is_typing']) ? (bool) $_POST['is_typing'] : false;
		$user_type = isset($_POST['user_type']) ? sanitize_text_field( wp_unslash( $_POST['user_type'] ) ) : 'user';
		$user_name = isset($_POST['user_name']) ? sanitize_text_field( wp_unslash( $_POST['user_name'] ) ) : '';

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		$current_user_id = get_current_user_id();
		
		// For anonymous users, use session-based user ID (0) and store user name
		if ( $current_user_id === 0 && !empty($user_name) ) {
			// Update session with user name if provided
			$this->database->update_session_user_name($session_id, $user_name);
		}
		
		$result = $this->database->set_typing_indicator($session_id, $current_user_id, $user_type, $is_typing);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('Typing indicator updated.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to update typing indicator.', 'askany') ));
		}
	}

	/**
	 * Get real-time updates via AJAX.
	 *
	 * @return void
	 */
	public function get_realtime_updates() {
		try {
			// Verify nonce for security - accept both chat and admin nonces
			$nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
			$is_admin_request = current_user_can('manage_options');
			
			$nonce_valid = false;
			if ($is_admin_request) {
				// For admin requests, check admin nonce
				$nonce_valid = wp_verify_nonce($nonce, 'askany_chat_nonce');
			} else {
				// For frontend requests, check chat nonce
				$nonce_valid = wp_verify_nonce($nonce, 'askany_chat_nonce');
			}
			
			if (!$nonce_valid) {
				wp_send_json_error(array('message' => __('Security check failed.', 'askany')));
				return;
			}

			$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
			$last_message_time = isset($_POST['last_message_time']) ? sanitize_text_field( wp_unslash( $_POST['last_message_time'] ) ) : null;

			// Debug: Log what we received
			// error_log('AJAX get_realtime_updates - session_id: ' . $session_id . ', last_message_time: ' . $last_message_time);

			if ( empty($session_id) ) {
				wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
				return;
			}

			$updates = $this->database->get_realtime_updates($session_id, $last_message_time);

			// Debug: Log what we're returning
			// error_log('AJAX get_realtime_updates - Returning ' . count($updates['messages']) . ' messages');

			wp_send_json_success($updates);
		} catch ( Exception $e ) {
			// error_log('AJAX get_realtime_updates - Error: ' . $e->getMessage());
			wp_send_json_error(array(
				'message' => __('Error getting real-time updates.', 'askany'),
				'error' => $e->getMessage(),
			));
		}
	}

	/**
	 * Poll for new messages via AJAX (for admin interface).
	 *
	 * @return void
	 */
	public function poll_messages() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
		$last_message_time = isset($_POST['last_message_time']) ? sanitize_text_field( wp_unslash( $_POST['last_message_time'] ) ) : null;

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		$updates = $this->database->get_realtime_updates($session_id, $last_message_time);

		// Also get updated session list for admin
		$sessions = $this->database->get_active_chat_sessions();
		$updates['sessions'] = $sessions;

		wp_send_json_success($updates);
	}

	// ===== HOME PAGE MANAGEMENT AJAX HANDLERS =====

	/**
	 * Save home page settings via AJAX.
	 *
	 * @return void
	 */
	public function save_home_settings() {
		// Different nonce verification based on request type
		$type = isset($_POST['type']) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : 'general';

		if ( $type === 'toggle' ) {
			// For toggle operations, use the admin nonce
			check_ajax_referer('askany_chat_nonce', 'nonce');
		} else {
			// For form submissions, use the home settings nonce
			check_ajax_referer('askany_save_home_settings', 'askany_home_nonce');
		}

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$settings_to_update = array();

		switch ( $type ) {
			case 'general':
				$settings_to_update = array(
					'home_page_enabled' => isset($_POST['home_page_enabled']) ? 1 : 0,
					'home_logo' => isset($_POST['home_logo']) ? esc_url_raw( wp_unslash( $_POST['home_logo'] ) ) : '',
					'home_welcome_message' => isset($_POST['home_welcome_message']) ? sanitize_text_field( wp_unslash( $_POST['home_welcome_message'] ) ) : '',
					'show_agents' => isset($_POST['show_agents']) ? 1 : 0,
				);
				break;

			case 'getstarted':
				$settings_to_update = array(
					'get_started_enabled' => isset($_POST['get_started_enabled']) ? 1 : 0,
					'get_started_title' => isset($_POST['get_started_title']) ? sanitize_text_field( wp_unslash( $_POST['get_started_title'] ) ) : '',
					'get_started_description' => isset($_POST['get_started_description']) ? sanitize_textarea_field( wp_unslash( $_POST['get_started_description'] ) ) : '',
					'get_started_name_label' => isset($_POST['get_started_name_label']) ? sanitize_text_field( wp_unslash( $_POST['get_started_name_label'] ) ) : '',
					'get_started_email_label' => isset($_POST['get_started_email_label']) ? sanitize_text_field( wp_unslash( $_POST['get_started_email_label'] ) ) : '',
					'get_started_button_text' => isset($_POST['get_started_button_text']) ? sanitize_text_field( wp_unslash( $_POST['get_started_button_text'] ) ) : '',
					'get_started_name_required' => isset($_POST['get_started_name_required']) ? 1 : 0,
					'get_started_email_required' => isset($_POST['get_started_email_required']) ? 1 : 0,
				);
				break;

			case 'documentation':
				$settings_to_update = array(
					'show_documentation' => isset($_POST['show_documentation']) ? 1 : 0,
					'documentation_url' => isset($_POST['documentation_url']) ? esc_url_raw( wp_unslash( $_POST['documentation_url'] ) ) : '',
					'documentation_description' => isset($_POST['documentation_description']) ? sanitize_text_field( wp_unslash( $_POST['documentation_description'] ) ) : '',
				);
				break;

			case 'news':
				$selected_posts = isset($_POST['news_selected_posts']) && is_array($_POST['news_selected_posts']) 
					? array_map('intval', $_POST['news_selected_posts']) 
					: array();
				
				$settings_to_update = array(
					'news_enabled' => isset($_POST['news_enabled']) ? 1 : 0,
					'news_label' => isset($_POST['news_label']) ? sanitize_text_field( wp_unslash( $_POST['news_label'] ) ) : __('News', 'askany'),
					'news_mode' => isset($_POST['news_mode']) && in_array($_POST['news_mode'], array('latest', 'selected')) ? sanitize_text_field( wp_unslash( $_POST['news_mode'] ) ) : 'latest',
					'news_timeframe' => isset($_POST['news_timeframe']) ? intval($_POST['news_timeframe']) : 7,
					'news_count' => isset($_POST['news_count']) ? max(1, min(20, intval($_POST['news_count']))) : 5,
					'news_excerpt_length' => isset($_POST['news_excerpt_length']) ? max(50, min(500, intval($_POST['news_excerpt_length']))) : 150,
					'news_selected_posts' => $selected_posts,
				);
				break;

			case 'report_issue':
				$settings_to_update = array(
					'report_issue_enabled' => isset($_POST['report_issue_enabled']) ? 1 : 0,
					'report_issue_title' => isset($_POST['report_issue_title']) ? sanitize_text_field( wp_unslash( $_POST['report_issue_title'] ) ) : __('Report an issue?', 'askany'),
					'report_issue_description' => isset($_POST['report_issue_description']) ? sanitize_text_field( wp_unslash( $_POST['report_issue_description'] ) ) : __('Found a bug? Let us know.', 'askany'),
					'report_issue_message' => isset($_POST['report_issue_message']) ? sanitize_textarea_field( wp_unslash( $_POST['report_issue_message'] ) ) : __('Hey 👋 Found a bug? Please describe the issue below. Also, please share your name and email so we can follow up with you.', 'askany'),
				);
				break;

			case 'feature_request':
				$settings_to_update = array(
					'feature_request_enabled' => isset($_POST['feature_request_enabled']) ? 1 : 0,
					'feature_request_title' => isset($_POST['feature_request_title']) ? sanitize_text_field( wp_unslash( $_POST['feature_request_title'] ) ) : __('Request a feature', 'askany'),
					'feature_request_description' => isset($_POST['feature_request_description']) ? sanitize_text_field( wp_unslash( $_POST['feature_request_description'] ) ) : __('What would you like to see next?', 'askany'),
					'feature_request_message' => isset($_POST['feature_request_message']) ? sanitize_textarea_field( wp_unslash( $_POST['feature_request_message'] ) ) : __('What feature would you like to see next? Share your name, email and feature details so we can consider it for future updates.', 'askany'),
				);
				break;

			case 'toggle':
				$setting = isset($_POST['setting']) ? sanitize_text_field( wp_unslash( $_POST['setting'] ) ) : '';
				$value = isset($_POST['value']) ? intval($_POST['value']) : 0;

				if ( in_array($setting, array( 'show_faq', 'show_custom_links' )) ) {
					$settings_to_update = array( $setting => $value );
				}
				break;
		}

		if ( ! empty($settings_to_update) ) {
			$updated = $this->api_manager->update_settings($settings_to_update);

			if ( $updated ) {
				wp_send_json_success(array( 'message' => __('Settings saved successfully.', 'askany') ));
			} else {
				wp_send_json_error(array( 'message' => __('Failed to save settings.', 'askany') ));
			}
		} else {
			wp_send_json_error(array( 'message' => __('No valid settings to update.', 'askany') ));
		}
	}

	/**
	 * Save home page FAQ via AJAX.
	 *
	 * @return void
	 */
	public function save_home_faq() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$faq_id = isset($_POST['faq_id']) ? intval($_POST['faq_id']) : 0;
		$question = isset($_POST['question']) ? sanitize_text_field( wp_unslash( $_POST['question'] ) ) : '';
		$answer = isset($_POST['answer']) ? wp_kses_post( wp_unslash( $_POST['answer'] ) ) : '';
		$display_order = isset($_POST['display_order']) ? intval($_POST['display_order']) : 0;

		if ( empty($question) || empty($answer) ) {
			wp_send_json_error(array( 'message' => __('Question and answer are required.', 'askany') ));
		}

		if ( $faq_id > 0 ) {
			// Update existing FAQ
			$result = $this->database->update_home_faq($faq_id, $question, $answer, $display_order);
		} else {
			// Add new FAQ
			$result = $this->database->add_home_faq($question, $answer, $display_order);
		}

		if ( $result !== false ) {
			wp_send_json_success(array( 'message' => __('FAQ saved successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to save FAQ.', 'askany') ));
		}
	}

	/**
	 * Get home page FAQ via AJAX.
	 *
	 * @return void
	 */
	public function get_home_faq() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$faq_id = isset($_POST['faq_id']) ? intval($_POST['faq_id']) : 0;

		if ( ! $faq_id ) {
			wp_send_json_error(array( 'message' => __('Invalid FAQ ID.', 'askany') ));
		}

		$faq = $this->database->get_home_faq($faq_id);

		if ( $faq ) {
			wp_send_json_success($faq);
		} else {
			wp_send_json_error(array( 'message' => __('FAQ not found.', 'askany') ));
		}
	}

	/**
	 * Delete home page FAQ via AJAX.
	 *
	 * @return void
	 */
	public function delete_home_faq() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$faq_id = isset($_POST['faq_id']) ? intval($_POST['faq_id']) : 0;

		if ( ! $faq_id ) {
			wp_send_json_error(array( 'message' => __('Invalid FAQ ID.', 'askany') ));
		}

		$result = $this->database->delete_home_faq($faq_id);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('FAQ deleted successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to delete FAQ.', 'askany') ));
		}
	}

	/**
	 * Toggle home page FAQ status via AJAX.
	 *
	 * @return void
	 */
	public function toggle_home_faq() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$faq_id = isset($_POST['faq_id']) ? intval($_POST['faq_id']) : 0;
		$is_active = isset($_POST['is_active']) ? intval($_POST['is_active']) : 0;

		if ( ! $faq_id ) {
			wp_send_json_error(array( 'message' => __('Invalid FAQ ID.', 'askany') ));
		}

		$result = $this->database->toggle_home_faq_status($faq_id, $is_active);

		if ( $result !== false ) {
			wp_send_json_success(array( 'message' => __('FAQ status updated successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to update FAQ status.', 'askany') ));
		}
	}

	/**
	 * Save home page custom link via AJAX.
	 *
	 * @return void
	 */
	public function save_home_link() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$link_id = isset($_POST['link_id']) ? intval($_POST['link_id']) : 0;
		$title = isset($_POST['title']) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';
		$description = isset($_POST['description']) ? sanitize_text_field( wp_unslash( $_POST['description'] ) ) : '';
		$url = isset($_POST['url']) ? esc_url_raw( wp_unslash( $_POST['url'] ) ) : '';
		$display_order = isset($_POST['display_order']) ? intval($_POST['display_order']) : 0;

		if ( empty($title) || empty($url) ) {
			wp_send_json_error(array( 'message' => __('Title and URL are required.', 'askany') ));
		}

		if ( $link_id > 0 ) {
			// Update existing link
			$result = $this->database->update_home_link($link_id, $title, $description, $url, '', $display_order);
		} else {
			// Add new link
			$result = $this->database->add_home_link($title, $description, $url, '', $display_order);
		}

		if ( $result !== false ) {
			wp_send_json_success(array( 'message' => __('Link saved successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to save link.', 'askany') ));
		}
	}

	/**
	 * Get home page custom link via AJAX.
	 *
	 * @return void
	 */
	public function get_home_link() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$link_id = isset($_POST['link_id']) ? intval($_POST['link_id']) : 0;

		if ( ! $link_id ) {
			wp_send_json_error(array( 'message' => __('Invalid link ID.', 'askany') ));
		}

		$link = $this->database->get_home_link($link_id);

		if ( $link ) {
			wp_send_json_success($link);
		} else {
			wp_send_json_error(array( 'message' => __('Link not found.', 'askany') ));
		}
	}

	/**
	 * Delete home page custom link via AJAX.
	 *
	 * @return void
	 */
	public function delete_home_link() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$link_id = isset($_POST['link_id']) ? intval($_POST['link_id']) : 0;

		if ( ! $link_id ) {
			wp_send_json_error(array( 'message' => __('Invalid link ID.', 'askany') ));
		}

		$result = $this->database->delete_home_link($link_id);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('Link deleted successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to delete link.', 'askany') ));
		}
	}

	/**
	 * Toggle home page custom link status via AJAX.
	 *
	 * @return void
	 */
	public function toggle_home_link() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$link_id = isset($_POST['link_id']) ? intval($_POST['link_id']) : 0;
		$is_active = isset($_POST['is_active']) ? intval($_POST['is_active']) : 0;

		if ( ! $link_id ) {
			wp_send_json_error(array( 'message' => __('Invalid link ID.', 'askany') ));
		}

		$result = $this->database->toggle_home_link_status($link_id, $is_active);

		if ( $result !== false ) {
			wp_send_json_success(array( 'message' => __('Link status updated successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to update link status.', 'askany') ));
		}
	}

	/**
	 * Clear chat history for a specific session via AJAX.
	 *
	 * @return void
	 */
	public function clear_chat_history() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		$result = $this->database->clear_session_messages($session_id);

		if ( $result !== false ) {
			wp_send_json_success(array( 'message' => __('Chat history cleared successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to clear chat history.', 'askany') ));
		}
	}

	/**
	 * Delete user session and all messages via AJAX.
	 *
	 * @return void
	 */
	public function delete_user_session() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';

		if ( empty($session_id) ) {
			wp_send_json_error(array( 'message' => __('Session ID is required.', 'askany') ));
		}

		$result = $this->database->delete_chat_session($session_id);

		if ( $result !== false ) {
			wp_send_json_success(array( 'message' => __('User session deleted successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to delete user session.', 'askany') ));
		}
	}

	/**
	 * Handle internet search via AJAX.
	 *
	 * This method performs internet search when AI needs additional information.
	 *
	 * @return void
	 */
	public function search_internet() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		$query = isset($_POST['query']) ? sanitize_text_field( wp_unslash( $_POST['query']) ) : '';
		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id']) ) : '';

		if ( empty($query) ) {
			wp_send_json_error(array(
				'message' => __('Search query is required.', 'askany'),
			));
		}

		// Get internet search response
		$search_response = $this->api_manager->get_internet_search_response($query, $session_id);

		if ( $search_response ) {
			wp_send_json_success(array(
				'message' => $search_response['text'],
				'search_results' => isset($search_response['search_results']) ? $search_response['search_results'] : array(),
				'session_id' => $session_id,
				'source' => 'internet_search'
			));
		} else {
			wp_send_json_error(array(
				'message' => __('Unable to search the internet at this time. Please try again later.', 'askany'),
			));
		}
	}

	/**
	 * Get API statistics via AJAX.
	 *
	 * This method retrieves API statistics for the dashboard.
	 *
	 * @return void
	 */
	public function get_api_stats() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$period = isset($_POST['period']) ? sanitize_text_field( wp_unslash( $_POST['period']) ) : 'week';
		$days = isset($_POST['days']) ? intval($_POST['days']) : 30;

		$stats = array(
			'overview' => $this->database->get_api_performance_metrics($period),
			'detailed' => $this->database->get_api_stats($days),
		);

		wp_send_json_success($stats);
	}

	/**
	 * Refresh API statistics via AJAX.
	 *
	 * This method refreshes and returns updated API statistics.
	 *
	 * @return void
	 */
	public function refresh_api_stats() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		// Get fresh statistics
		$stats = array(
			'performance_today' => $this->database->get_api_performance_metrics('today'),
			'performance_week' => $this->database->get_api_performance_metrics('week'),
			'performance_month' => $this->database->get_api_performance_metrics('month'),
			'stats_30_days' => $this->database->get_api_stats(30),
			'stats_7_days' => $this->database->get_api_stats(7),
		);

		wp_send_json_success(array(
			'message' => __('Statistics refreshed successfully.', 'askany'),
			'data' => $stats,
		));
	}

	/**
	 * Get paginated API errors via AJAX.
	 *
	 * This method retrieves paginated API error logs.
	 *
	 * @return void
	 */
	public function get_paginated_errors() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$page = isset($_POST['page']) ? intval($_POST['page']) : 1;
		$per_page = isset($_POST['per_page']) ? intval($_POST['per_page']) : 10;
		$days = isset($_POST['days']) ? intval($_POST['days']) : 30;

		$result = $this->database->get_paginated_api_errors($page, $per_page, $days);

		wp_send_json_success($result);
	}

	/**
	 * Clear API errors via AJAX.
	 *
	 * This method clears API error logs.
	 *
	 * @return void
	 */
	public function clear_api_errors() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$days = isset($_POST['days']) ? intval($_POST['days']) : 0;

		$result = $this->database->clear_api_errors($days);

		if ( $result !== false ) {
			$message = $days > 0 
				? sprintf(__('Cleared errors older than %d days. %d errors removed.', 'askany'), $days, $result)
				: sprintf(__('All API errors cleared. %d errors removed.', 'askany'), $result);
			
			wp_send_json_success(array( 
				'message' => $message,
				'cleared_count' => $result
			));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to clear API errors.', 'askany') ));
		}
	}

	/**
	 * Get paginated chat logs via AJAX.
	 *
	 * This method retrieves paginated chat logs.
	 *
	 * @return void
	 */
	public function get_paginated_chat_logs() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$page = isset($_POST['page']) ? intval($_POST['page']) : 1;
		$per_page = isset($_POST['per_page']) ? intval($_POST['per_page']) : 20;
		$search = isset($_POST['search']) ? sanitize_text_field( wp_unslash( $_POST['search'] ) ) : '';

		$result = $this->database->get_paginated_chat_logs($page, $per_page, $search);

		wp_send_json_success($result);
	}

	/**
	 * Clear chat logs via AJAX.
	 *
	 * This method clears chat logs.
	 *
	 * @return void
	 */
	public function clear_chat_logs() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$days = isset($_POST['days']) ? intval($_POST['days']) : 0;

		$result = $this->database->clear_chat_logs($days);

		if ( $result !== false ) {
			$message = $days > 0 
				? sprintf(__('Cleared chat logs older than %d days. %d logs removed.', 'askany'), $days, $result)
				: sprintf(__('All chat logs cleared. %d logs removed.', 'askany'), $result);
			
			wp_send_json_success(array( 
				'message' => $message,
				'cleared_count' => $result
			));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to clear chat logs.', 'askany') ));
		}
	}


	/*
	*
	 * Get product details via AJAX.
	 *
	 * This method retrieves detailed product information for the modal popup.
	 *
	 * @return void
	 */
	public function get_product_details() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		$product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;

		if (!$product_id) {
			wp_send_json_error(array(
				'message' => __('Invalid product ID.', 'askany')
			));
		}

		// Check if WooCommerce is active
		if (!class_exists('WooCommerce')) {
			wp_send_json_error(array(
				'message' => __('WooCommerce is not active.', 'askany')
			));
		}

		// Get product
		$product = wc_get_product($product_id);

		if (!$product || !$product->exists()) {
			wp_send_json_error(array(
				'message' => __('Product not found.', 'askany')
			));
		}

		// Prepare product data
		$product_data = array(
			'id' => $product->get_id(),
			'name' => $product->get_name(),
			'description' => $product->get_description(),
			'short_description' => $product->get_short_description(),
			'price' => $product->get_price(),
			'regular_price' => $product->get_regular_price(),
			'sale_price' => $product->get_sale_price(),
			'price_html' => $product->get_price_html(),
			'on_sale' => $product->is_on_sale(),
			'sku' => $product->get_sku(),
			'stock_status' => $product->get_stock_status(),
			'stock_quantity' => $product->get_stock_quantity(),
			'manage_stock' => $product->get_manage_stock(),
			'url' => get_permalink($product->get_id()),
			'image_url' => wp_get_attachment_image_url($product->get_image_id(), 'full'),
			'gallery_images' => array(),
			'categories' => array(),
			'tags' => array(),
			'attributes' => array(),
			'average_rating' => $product->get_average_rating(),
			'reviews_count' => $product->get_review_count(),
			'weight' => $product->get_weight(),
			'dimensions' => array(
				'length' => $product->get_length(),
				'width' => $product->get_width(),
				'height' => $product->get_height()
			)
		);

		// Get gallery images
		$gallery_ids = $product->get_gallery_image_ids();
		foreach ($gallery_ids as $gallery_id) {
			$product_data['gallery_images'][] = wp_get_attachment_image_url($gallery_id, 'full');
		}

		// Get categories
		$categories = get_the_terms($product->get_id(), 'product_cat');
		if ($categories && !is_wp_error($categories)) {
			foreach ($categories as $category) {
				$product_data['categories'][] = $category->name;
			}
		}

		// Get tags
		$tags = get_the_terms($product->get_id(), 'product_tag');
		if ($tags && !is_wp_error($tags)) {
			foreach ($tags as $tag) {
				$product_data['tags'][] = $tag->name;
			}
		}

		// Get attributes
		$attributes = $product->get_attributes();
		foreach ($attributes as $attribute) {
			if ($attribute->is_taxonomy()) {
				$terms = wp_get_post_terms($product->get_id(), $attribute->get_name());
				$values = array();
				foreach ($terms as $term) {
					$values[] = $term->name;
				}
				$product_data['attributes'][wc_attribute_label($attribute->get_name())] = implode(', ', $values);
			} else {
				$product_data['attributes'][$attribute->get_name()] = $attribute->get_options();
			}
		}

		// Get variations if it's a variable product
		if ($product->is_type('variable')) {
			$variations = $product->get_available_variations();
			$product_data['variations'] = $variations;
			$product_data['variation_attributes'] = $product->get_variation_attributes();
		}

		wp_send_json_success($product_data);
	}

	/**
	 * Add product to cart via AJAX.
	 *
	 * This method adds a product to the WooCommerce cart.
	 *
	 * @return void
	 */
	public function add_to_cart() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		$product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
		$quantity = isset($_POST['quantity']) ? intval($_POST['quantity']) : 1;
		$variation_id = isset($_POST['variation_id']) ? intval($_POST['variation_id']) : 0;
		$variation = isset($_POST['variation']) ? (array) $_POST['variation'] : array();

		if (!$product_id) {
			wp_send_json_error(array(
				'message' => __('Invalid product ID.', 'askany')
			));
		}

		// Check if WooCommerce is active
		if (!class_exists('WooCommerce')) {
			wp_send_json_error(array(
				'message' => __('WooCommerce is not active.', 'askany')
			));
		}

		// Sanitize quantity
		if ($quantity <= 0) {
			$quantity = 1;
		}

		// Get product
		$product = wc_get_product($product_id);

		if (!$product || !$product->exists()) {
			wp_send_json_error(array(
				'message' => __('Product not found.', 'askany')
			));
		}

		// Check if product is purchasable
		if (!$product->is_purchasable()) {
			wp_send_json_error(array(
				'message' => __('This product cannot be purchased.', 'askany')
			));
		}

		// Check stock
		if (!$product->is_in_stock()) {
			wp_send_json_error(array(
				'message' => __('This product is out of stock.', 'askany')
			));
		}

		// Check stock quantity
		if ($product->managing_stock() && $product->get_stock_quantity() < $quantity) {
			wp_send_json_error(array(
				'message' => sprintf(__('Only %d items available in stock.', 'askany'), $product->get_stock_quantity())
			));
		}

		// Handle variable products
		if ($product->is_type('variable') && !$variation_id) {
			wp_send_json_error(array(
				'message' => __('Please select product options before adding to cart.', 'askany')
			));
		}

		// Sanitize variation data
		if (!empty($variation)) {
			$variation = array_map('sanitize_text_field', $variation);
		}

		try {
			// Add to cart
			$cart_item_key = WC()->cart->add_to_cart(
				$product_id,
				$quantity,
				$variation_id,
				$variation
			);

			if ($cart_item_key) {
				// Get cart count
				$cart_count = WC()->cart->get_cart_contents_count();
				
				// Get product name for success message
				$product_name = $product->get_name();
				
				// Prepare success message
				$message = sprintf(
					__('%s has been added to your cart.', 'askany'),
					$product_name
				);

				if ($quantity > 1) {
					$message = sprintf(
						__('%d × %s have been added to your cart.', 'askany'),
						$quantity,
						$product_name
					);
				}

				// Get cart fragments for updating cart UI
				$fragments = array();
				if (function_exists('wc_get_template')) {
					ob_start();
					wc_get_template('cart/mini-cart.php');
					$mini_cart = ob_get_clean();
					$fragments['div.widget_shopping_cart_content'] = '<div class="widget_shopping_cart_content">' . $mini_cart . '</div>';
				}

				wp_send_json_success(array(
					'message' => $message,
					'cart_count' => $cart_count,
					'cart_total' => WC()->cart->get_cart_total(),
					'cart_subtotal' => WC()->cart->get_cart_subtotal(),
					'cart_url' => wc_get_cart_url(),
					'checkout_url' => wc_get_checkout_url(),
					'fragments' => $fragments,
					'cart_hash' => WC()->cart->get_cart_hash()
				));
			} else {
				wp_send_json_error(array(
					'message' => __('Failed to add product to cart. Please try again.', 'askany')
				));
			}
		} catch (Exception $e) {
			wp_send_json_error(array(
				'message' => $e->getMessage()
			));
		}
	}

	/**
	 * Cleanup old data via AJAX.
	 *
	 * @return void
	 */
	public function cleanup_old_data() {
		// Verify nonce and capabilities
		if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'askany_db_management' ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'askany' ) ) );
		}

		// Check PRO status
		$plugin = \Askany\Plugin::get_instance();
		if ( ! $plugin->is_pro_active() ) {
			wp_send_json_error( array( 'message' => __( 'This feature requires AskAny Pro. Please upgrade to access advanced database management.', 'askany' ) ) );
		}

		$days = intval( $_POST['days'] ?? 0 );
		
		if ( $days <= 0 ) {
			wp_send_json_error( array( 'message' => __( 'Invalid number of days.', 'askany' ) ) );
		}

		$database_manager = new \Askany\DatabaseManager( $this->database );
		$result = $database_manager->delete_old_data( $days );

		if ( $result['success'] ) {
			wp_send_json_success( $result );
		} else {
			wp_send_json_error( $result );
		}
	}

	/**
	 * Truncate all data via AJAX.
	 *
	 * @return void
	 */
	public function truncate_all_data() {
		// Verify nonce and capabilities
		if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'askany_db_management' ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'askany' ) ) );
		}

		// Check PRO status
		$plugin = \Askany\Plugin::get_instance();
		if ( ! $plugin->is_pro_active() ) {
			wp_send_json_error( array( 'message' => __( 'This feature requires AskAny Pro. Please upgrade to access advanced database management.', 'askany' ) ) );
		}

		$database_manager = new \Askany\DatabaseManager( $this->database );
		$result = $database_manager->truncate_all_data();

		if ( $result['success'] ) {
			wp_send_json_success( $result );
		} else {
			wp_send_json_error( $result );
		}
	}

	/**
	 * Optimize database tables via AJAX.
	 *
	 * @return void
	 */
	public function optimize_tables() {
		// Verify nonce and capabilities
		if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'askany_db_management' ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'askany' ) ) );
		}

		// Check PRO status
		$plugin = \Askany\Plugin::get_instance();
		if ( ! $plugin->is_pro_active() ) {
			wp_send_json_error( array( 'message' => __( 'This feature requires AskAny Pro. Please upgrade to access advanced database management.', 'askany' ) ) );
		}

		$database_manager = new \Askany\DatabaseManager( $this->database );
		$result = $database_manager->optimize_tables();

		if ( $result['success'] ) {
			wp_send_json_success( $result );
		} else {
			wp_send_json_error( $result );
		}
	}

	/**
	 * Delete data by date range via AJAX.
	 *
	 * @return void
	 */
	public function delete_date_range() {
		// Verify nonce and capabilities
		if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'askany_db_management' ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'askany' ) ) );
		}

		// Check PRO status
		$plugin = \Askany\Plugin::get_instance();
		if ( ! $plugin->is_pro_active() ) {
			wp_send_json_error( array( 'message' => __( 'This feature requires AskAny Pro. Please upgrade to access advanced database management.', 'askany' ) ) );
		}

		$start_date = sanitize_text_field( wp_unslash( $_POST['start_date'] ?? '' ) );
		$end_date = sanitize_text_field( wp_unslash( $_POST['end_date'] ?? '' ) );

		if ( empty( $start_date ) || empty( $end_date ) ) {
			wp_send_json_error( array( 'message' => __( 'Start date and end date are required.', 'askany' ) ) );
		}

		$database_manager = new \Askany\DatabaseManager( $this->database );
		$result = $database_manager->delete_data_by_date_range( $start_date, $end_date );

		if ( $result['success'] ) {
			wp_send_json_success( $result );
		} else {
			wp_send_json_error( $result );
		}
	}

	/**
	 * Export data via AJAX.
	 *
	 * @return void
	 */
	public function export_data() {
		// Verify nonce and capabilities
		if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'askany_db_management' ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'askany' ) ) );
		}

		// Check PRO status
		$plugin = \Askany\Plugin::get_instance();
		if ( ! $plugin->is_pro_active() ) {
			wp_send_json_error( array( 'message' => __( 'This feature requires AskAny Pro. Please upgrade to access advanced database management.', 'askany' ) ) );
		}

		// Sanitize and unslash input data
		$format = sanitize_text_field( wp_unslash( $_POST['format'] ?? 'csv' ) );
		$export_type = sanitize_text_field( wp_unslash( $_POST['export_type'] ?? 'all' ) );
		$start_date = sanitize_text_field( wp_unslash( $_POST['start_date'] ?? '' ) );
		$end_date = sanitize_text_field( wp_unslash( $_POST['end_date'] ?? '' ) );

		// Validate format
		if ( ! in_array( $format, array( 'csv', 'json' ), true ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid export format.', 'askany' ) ) );
		}

		// Validate export type
		if ( ! in_array( $export_type, array( 'all', 'filtered' ), true ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid export type.', 'askany' ) ) );
		}

		try {
			global $wpdb;
			
			// Get all table data
			$export_data = array();
			
			// Define all tables to export
			$tables_to_export = array(
				'chat_sessions' => $this->database->get_sessions_table(),
				'chat_messages' => $this->database->get_messages_table(),
				'qa_pairs' => $this->database->get_qa_pairs_table(),
				'external_sources' => $this->database->get_external_sources_table(),
				'content_index' => $this->database->get_content_index_table(),
				'pdf_index' => $this->database->get_pdf_index_table(),
				'chat_history' => $this->database->get_chat_history_table(),
				'user_agents' => $this->database->get_user_agents_table(),
				'typing_indicators' => $this->database->get_typing_indicators_table(),
				'home_faqs' => $this->database->get_home_faqs_table(),
				'home_links' => $this->database->get_home_links_table(),
				'api_stats' => $this->database->get_api_stats_table(),
				'feature_requests' => $this->database->get_feature_requests_table(),
				'bug_reports' => $this->database->get_bug_reports_table(),
				'embeddings' => $this->database->get_embeddings_table(),
			);
			
			// Export each table
			foreach ( $tables_to_export as $table_key => $table_name ) {
				$query = "SELECT * FROM {$table_name}";
				
				// Apply date filtering for tables with created_at field
				$date_tables = array( 'chat_sessions', 'chat_messages', 'qa_pairs', 'chat_history', 'user_agents', 'typing_indicators', 'home_faqs', 'api_stats', 'feature_requests', 'bug_reports' );
				
				if ( $export_type === 'filtered' && ! empty( $start_date ) && ! empty( $end_date ) && in_array( $table_key, $date_tables ) ) {
					$start_datetime = $start_date . ' 00:00:00';
					$end_datetime = $end_date . ' 23:59:59';
					$query .= $wpdb->prepare( " WHERE created_at BETWEEN %s AND %s", $start_datetime, $end_datetime );
				}
				
				$query .= " ORDER BY id DESC";
				$table_data = $wpdb->get_results( $query );
				
				if ( ! empty( $table_data ) ) {
					$export_data[$table_key] = $table_data;
				}
			}
			
			// Flatten data for CSV export or keep structured for JSON
			if ( $format === 'csv' ) {
				$results = array();
				foreach ( $export_data as $table_name => $table_data ) {
					foreach ( $table_data as $row ) {
						$row_array = (array) $row;
						$row_array['table_name'] = $table_name; // Add table identifier
						$results[] = (object) $row_array;
					}
				}
			} else {
				$results = $export_data;
			}

			if ( empty( $results ) ) {
				wp_send_json_error( array( 'message' => __( 'No data found to export.', 'askany' ) ) );
			}

			// Create export file
			$filename = 'askany_export_' . date( 'Y-m-d_H-i-s' ) . '.' . $format;
			$upload_dir = wp_upload_dir();
			$file_path = $upload_dir['path'] . '/' . $filename;

			if ( $format === 'csv' ) {
				$this->create_csv_export( $results, $file_path );
			} else {
				$this->create_json_export( $results, $file_path );
			}

			// Create download URL
			$download_url = $upload_dir['url'] . '/' . $filename;

			wp_send_json_success( array(
				'message' => sprintf( 
					__( 'Export completed! %d records exported.', 'askany' ),
					count( $results )
				),
				'download_url' => $download_url,
				'filename' => $filename
			) );

		} catch ( Exception $e ) {
			wp_send_json_error( array( 'message' => __( 'Export failed: ', 'askany' ) . $e->getMessage() ) );
		}
	}

	/**
	 * Create CSV export file.
	 *
	 * @param array $data Export data
	 * @param string $file_path File path
	 */
	private function create_csv_export( $data, $file_path ) {
		$file = fopen( $file_path, 'w' );
		
		if ( empty( $data ) ) {
			fclose( $file );
			return;
		}
		
		// Get all possible columns from the data
		$all_columns = array();
		foreach ( $data as $row ) {
			$row_array = (array) $row;
			$all_columns = array_merge( $all_columns, array_keys( $row_array ) );
		}
		$all_columns = array_unique( $all_columns );
		
		// Add CSV headers
		fputcsv( $file, $all_columns );

		// Add data rows
		foreach ( $data as $row ) {
			$row_array = (array) $row;
			$csv_row = array();
			
			foreach ( $all_columns as $column ) {
				$value = isset( $row_array[$column] ) ? $row_array[$column] : '';
				
				// Handle boolean values
				if ( is_bool( $value ) ) {
					$value = $value ? 'Yes' : 'No';
				} elseif ( $value === '1' || $value === '0' ) {
					// Handle string boolean values
					if ( in_array( $column, array( 'is_ai_handled', 'is_read', 'is_typing', 'is_active', 'is_online' ) ) ) {
						$value = $value === '1' ? 'Yes' : 'No';
					}
				}
				
				$csv_row[] = $value;
			}
			
			fputcsv( $file, $csv_row );
		}

		fclose( $file );
	}

	/**
	 * Create JSON export file.
	 *
	 * @param array $data Export data
	 * @param string $file_path File path
	 */
	private function create_json_export( $data, $file_path ) {
		// Calculate total records
		$total_records = 0;
		if ( is_array( $data ) ) {
			if ( isset( $data[0] ) && is_object( $data[0] ) ) {
				// Flattened data (CSV format)
				$total_records = count( $data );
			} else {
				// Structured data (table format)
				foreach ( $data as $table_data ) {
					if ( is_array( $table_data ) ) {
						$total_records += count( $table_data );
					}
				}
			}
		}
		
		$export_data = array(
			'export_date' => current_time( 'mysql' ),
			'plugin_version' => ASKANY_VERSION,
			'total_records' => $total_records,
			'data' => $data
		);

		file_put_contents( $file_path, wp_json_encode( $export_data, JSON_PRETTY_PRINT ) );
	}

	/**
	 * Import data via AJAX.
	 *
	 * @return void
	 */
	public function import_data() {
		// Verify nonce and capabilities
		if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'askany_db_management' ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'askany' ) ) );
		}

		// Check PRO status
		$plugin = \Askany\Plugin::get_instance();
		if ( ! $plugin->is_pro_active() ) {
			wp_send_json_error( array( 'message' => __( 'This feature requires AskAny Pro. Please upgrade to access advanced database management.', 'askany' ) ) );
		}

		if ( empty( $_FILES['import_file'] ) ) {
			wp_send_json_error( array( 'message' => __( 'No file uploaded.', 'askany' ) ) );
		}

		$file = $_FILES['import_file'];
		
		// Validate file upload errors
		if ( $file['error'] !== UPLOAD_ERR_OK ) {
			wp_send_json_error( array( 'message' => __( 'File upload failed.', 'askany' ) ) );
		}
		
		// Sanitize filename
		$filename = sanitize_file_name( $file['name'] );
		$file_extension = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );

		// Validate file extension with strict comparison
		if ( ! in_array( $file_extension, array( 'csv', 'json', 'sql' ), true ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid file format. Only CSV, JSON, and SQL files are allowed.', 'askany' ) ) );
		}

		// Validate MIME type for additional security
		$allowed_mime_types = array(
			'csv' => array( 'text/csv', 'text/plain', 'application/csv' ),
			'json' => array( 'application/json', 'text/plain' ),
			'sql' => array( 'application/sql', 'text/plain' )
		);
		
		$finfo = finfo_open( FILEINFO_MIME_TYPE );
		$mime_type = finfo_file( $finfo, $file['tmp_name'] );
		finfo_close( $finfo );
		
		if ( ! in_array( $mime_type, $allowed_mime_types[ $file_extension ], true ) ) {
			wp_send_json_error( array( 'message' => __( 'File MIME type does not match extension.', 'askany' ) ) );
		}

		// TODO: Implement data import functionality
		// This would process the uploaded file and import data
		
		wp_send_json_success( array(
			'message' => sprintf( 
				__( 'Import functionality for %s files will be implemented in the next phase.', 'askany' ),
				strtoupper( $file_extension )
			)
		) );
	}

	/**
	 * Filter data via AJAX.
	 *
	 * @return void
	 */
	public function filter_data() {
		// Verify nonce and capabilities
		if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'askany_db_management' ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'askany' ) ) );
		}

		// Check PRO status
		$plugin = \Askany\Plugin::get_instance();
		if ( ! $plugin->is_pro_active() ) {
			wp_send_json_error( array( 'message' => __( 'This feature requires AskAny Pro. Please upgrade to access advanced database management.', 'askany' ) ) );
		}

		// Sanitize and unslash input data
		$start_date = sanitize_text_field( wp_unslash( $_POST['start_date'] ?? '' ) );
		$end_date = sanitize_text_field( wp_unslash( $_POST['end_date'] ?? '' ) );
		$session_type = sanitize_text_field( wp_unslash( $_POST['session_type'] ?? 'all' ) );

		if ( empty( $start_date ) || empty( $end_date ) ) {
			wp_send_json_error( array( 'message' => __( 'Start date and end date are required.', 'askany' ) ) );
		}

		// Validate session type with whitelist
		$valid_session_types = array( 'all', 'anonymous', 'logged_in', 'agent_handled', 'ai_only' );
		if ( ! in_array( $session_type, $valid_session_types, true ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid session type.', 'askany' ) ) );
		}

		global $wpdb;
		$sessions_table = $this->database->get_sessions_table();
		$messages_table = $this->database->get_messages_table();

		// Convert to datetime for database query
		$start_datetime = $start_date . ' 00:00:00';
		$end_datetime = $end_date . ' 23:59:59';

		// Build queries based on session type
		$session_query = "SELECT COUNT(*) FROM {$sessions_table} WHERE created_at BETWEEN %s AND %s";
		$message_query = "SELECT COUNT(*) FROM {$messages_table} m INNER JOIN {$sessions_table} s ON m.session_id = s.session_id WHERE s.created_at BETWEEN %s AND %s";
		
		$query_params = array( $start_datetime, $end_datetime );

		// Add session type filter
		switch ( $session_type ) {
			case 'anonymous':
				$session_query .= " AND session_id LIKE %s";
				$message_query .= " AND s.session_id LIKE %s";
				$query_params[] = 'anon_%';
				break;
			case 'logged_in':
				$session_query .= " AND session_id LIKE %s";
				$message_query .= " AND s.session_id LIKE %s";
				$query_params[] = 'user_%';
				break;
			case 'agent_handled':
				$session_query .= " AND agent_id IS NOT NULL";
				$message_query .= " AND s.agent_id IS NOT NULL";
				break;
			case 'ai_only':
				$session_query .= " AND (agent_id IS NULL OR is_ai_handled = 1)";
				$message_query .= " AND (s.agent_id IS NULL OR s.is_ai_handled = 1)";
				break;
		}

		// Count sessions in date range
		if ( in_array( $session_type, array( 'anonymous', 'logged_in' ), true ) ) {
			$session_count = $wpdb->get_var( $wpdb->prepare( $session_query, $query_params ) );
			$message_count = $wpdb->get_var( $wpdb->prepare( $message_query, $query_params ) );
		} else {
			$session_count = $wpdb->get_var( $wpdb->prepare( $session_query, $start_datetime, $end_datetime ) );
			$message_count = $wpdb->get_var( $wpdb->prepare( $message_query, $start_datetime, $end_datetime ) );
		}

		wp_send_json_success( array(
			'sessions' => (int) $session_count,
			'messages' => (int) $message_count,
			'start_date' => $start_date,
			'end_date' => $end_date,
			'session_type' => $session_type
		) );
	}

	/**
	 * Get fresh database statistics via AJAX.
	 *
	 * @return void
	 */
	public function get_database_stats() {
		// Verify nonce and capabilities
		if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'askany_db_management' ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'askany' ) ) );
		}

		$database_manager = new \Askany\DatabaseManager( $this->database );
		
		// Get fresh statistics
		$table_sizes = $database_manager->get_table_sizes();
		$record_counts = $database_manager->get_record_counts();

		// Format the data for JavaScript
		$stats = array();
		
		// Add all available tables
		$table_keys = array(
			'chat_messages', 'chat_sessions', 'qa_pairs', 'external_sources',
			'content_index', 'pdf_index', 'chat_history', 'user_agents',
			'typing_indicators', 'home_faqs', 'home_links', 'api_stats'
		);
		
		foreach ( $table_keys as $key ) {
			if ( isset( $table_sizes[$key] ) && isset( $record_counts[$key] ) ) {
				$stats[$key] = array(
					'formatted_size' => $table_sizes[$key]['formatted_size'],
					'record_count' => number_format( $record_counts[$key] )
				);
			}
		}
		
		// Add total
		if ( isset( $table_sizes['total'] ) ) {
			$stats['total'] = array(
				'formatted_size' => $table_sizes['total']['formatted_size']
			);
		}

		wp_send_json_success( $stats );
	}
	
	/**
	 * Handle get started form submission
	 *
	 * @return void
	 */
	public function submit_get_started() {
		check_ajax_referer( 'askany_chat_nonce', 'nonce' );
		
		$name = isset( $_POST['name'] ) ? sanitize_text_field( $_POST['name'] ) : '';
		$email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : '';
		$session_id = isset( $_POST['session_id'] ) ? sanitize_text_field( $_POST['session_id'] ) : '';
		
		// Validate email if provided
		if ( ! empty( $email ) && ! is_email( $email ) ) {
			wp_send_json_error( array(
				'message' => __( 'Please provide a valid email address.', 'askany' )
			) );
		}
		
		// Check if email belongs to a registered user
		$avatar_url = '';
		if ( ! empty( $email ) ) {
			$user = get_user_by( 'email', $email );
			if ( $user ) {
				// Get user avatar
				$avatar_url = get_avatar_url( $email, array( 'size' => 96 ) );
			} else {
				// Get Gravatar for non-registered email
				$avatar_url = get_avatar_url( $email, array( 'size' => 96, 'default' => 'mp' ) );
			}
		}
		
		// Store user info in session metadata if session_id is provided
		if ( ! empty( $session_id ) ) {
			global $wpdb;
			$sessions_table = $this->database->get_sessions_table();
			
			// Update session with user info
			$wpdb->update(
				$sessions_table,
				array(
					'user_name' => $name,
					'user_email' => $email,
				),
				array( 'session_id' => $session_id ),
				array( '%s', '%s' ),
				array( '%s' )
			);
		}
		
		wp_send_json_success( array(
			'message' => __( 'Welcome! Let\'s get started.', 'askany' ),
			'name' => $name,
			'email' => $email,
			'avatar_url' => $avatar_url
		) );
	}

	/**
	 * Mark session messages as read.
	 *
	 * @return void
	 */
	public function mark_session_read() {
		// Verify nonce
		if ( ! wp_verify_nonce( $_POST['nonce'], 'askany_chat_nonce' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed', 'askany' ) ) );
		}

		// Check user permissions
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions', 'askany' ) ) );
		}

		$session_id = sanitize_text_field( $_POST['session_id'] );

		if ( empty( $session_id ) ) {
			wp_send_json_error( array( 'message' => __( 'Session ID is required', 'askany' ) ) );
		}

		// Mark all messages in the session as read
		$result = $this->database->mark_session_messages_as_read( $session_id );

		if ( $result ) {
			wp_send_json_success( array( 'message' => __( 'Messages marked as read', 'askany' ) ) );
		} else {
			wp_send_json_error( array( 'message' => __( 'Failed to mark messages as read', 'askany' ) ) );
		}
	}

	/**
	 * Get total unread message count.
	 *
	 * @return void
	 */
	public function get_unread_count() {
		// Verify nonce
		if ( ! wp_verify_nonce( $_POST['nonce'], 'askany_chat_nonce' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed', 'askany' ) ) );
		}

		// Check user permissions
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions', 'askany' ) ) );
		}

		// Get total unread count (only user messages)
		$unread_count = $this->database->get_total_unread_message_count( 'user' );

		wp_send_json_success( array( 
			'unread_count' => $unread_count 
		) );
	}

	/**
	 * Save integration settings.
	 *
	 * @return void
	 */
	public function save_integration_settings() {
		// Verify nonce
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'askany_chat_nonce' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed', 'askany' ) ) );
		}

		// Check user permissions
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions', 'askany' ) ) );
		}

		$setting = isset( $_POST['setting'] ) ? sanitize_text_field( wp_unslash( $_POST['setting'] ) ) : '';
		$value = isset( $_POST['value'] ) ? sanitize_text_field( wp_unslash( $_POST['value'] ) ) : '';

		if ( empty( $setting ) ) {
			wp_send_json_error( array( 'message' => __( 'Setting name is required', 'askany' ) ) );
		}

		// Get current settings
		$settings = $this->api_manager->get_settings();
		
		// Ensure settings is an array
		if ( ! is_array( $settings ) ) {
			$settings = array();
		}
		
		// Update the specific setting
		$settings[$setting] = $value;
		
		// Save settings
		$result = $this->api_manager->update_settings( $settings );

		if ( $result ) {
			wp_send_json_success( array( 'message' => __( 'Settings saved successfully', 'askany' ) ) );
		} else {
			wp_send_json_error( array( 'message' => __( 'Failed to save settings', 'askany' ) ) );
		}
	}

	/**
	 * Save Slack settings.
	 *
	 * @return void
	 */
	public function save_slack_settings() {
		// Verify nonce
		if ( ! isset( $_POST['askany_slack_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['askany_slack_nonce'] ) ), 'askany_save_slack_settings' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed', 'askany' ) ) );
		}

		// Check user permissions
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions', 'askany' ) ) );
		}

		$type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';

		// Get current settings
		$settings = $this->api_manager->get_settings();
		
		// Ensure settings is an array
		if ( ! is_array( $settings ) ) {
			$settings = array();
		}
		
		if ( ! isset( $settings['slack'] ) ) {
			$settings['slack'] = array();
		}

		if ( $type === 'webhook' ) {
			// Save webhook settings
			$settings['slack']['enabled'] = isset( $_POST['slack_enabled'] ) ? 1 : 0;
			$settings['slack']['webhook_url'] = isset( $_POST['slack_webhook_url'] ) ? esc_url_raw( wp_unslash( $_POST['slack_webhook_url'] ) ) : '';
			$settings['slack']['channel'] = isset( $_POST['slack_channel'] ) ? sanitize_text_field( wp_unslash( $_POST['slack_channel'] ) ) : '';
		} elseif ( $type === 'forwarding' ) {
			// Save forwarding settings
			$settings['slack']['notify_user_messages'] = isset( $_POST['notify_user_messages'] ) ? 1 : 0;
			$settings['slack']['forward_agent_messages'] = isset( $_POST['forward_agent_messages'] ) ? 1 : 0;
			$settings['slack']['forward_ai_messages'] = isset( $_POST['forward_ai_messages'] ) ? 1 : 0;
		}

		// Save settings
		$result = $this->api_manager->update_settings( $settings );

		if ( $result ) {
			wp_send_json_success( array( 'message' => __( 'Slack settings saved successfully', 'askany' ) ) );
		} else {
			wp_send_json_error( array( 'message' => __( 'Failed to save Slack settings', 'askany' ) ) );
		}
	}

	/**
	 * Test Slack webhook.
	 *
	 * @return void
	 */
	public function test_slack_webhook() {
		// Verify nonce
		if ( ! wp_verify_nonce( $_POST['nonce'], 'askany_chat_nonce' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed', 'askany' ) ) );
		}

		// Check user permissions
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions', 'askany' ) ) );
		}

		$webhook_url = esc_url_raw( $_POST['webhook_url'] );
		$channel = sanitize_text_field( $_POST['channel'] );

		if ( empty( $webhook_url ) ) {
			wp_send_json_error( array( 'message' => __( 'Webhook URL is required', 'askany' ) ) );
		}

		// Prepare test message
		$message = array(
			'text' => __( 'Test message from Askany! 🚀', 'askany' ),
			'username' => 'Askany',
			'icon_emoji' => ':robot_face:',
		);

		if ( ! empty( $channel ) ) {
			$message['channel'] = $channel;
		}

		// Send test message
		$response = wp_remote_post( $webhook_url, array(
			'body' => wp_json_encode( $message ),
			'headers' => array(
				'Content-Type' => 'application/json',
			),
			'timeout' => 15,
		) );

		if ( is_wp_error( $response ) ) {
			wp_send_json_error( array( 'message' => __( 'Failed to send test message: ', 'askany' ) . $response->get_error_message() ) );
		}

		$response_code = wp_remote_retrieve_response_code( $response );
		
		if ( $response_code === 200 ) {
			wp_send_json_success( array( 'message' => __( 'Test message sent successfully!', 'askany' ) ) );
		} else {
			$response_body = wp_remote_retrieve_body( $response );
			wp_send_json_error( array( 'message' => __( 'Failed to send test message. Response: ', 'askany' ) . $response_body ) );
		}
	}

	/**
	 * Save WooCommerce integration settings via AJAX.
	 *
	 * @return void
	 */
	public function save_woocommerce_settings() {
		// Verify nonce
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'askany_chat_nonce' ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed', 'askany' ) ) );
		}

		// Check user permissions
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to save settings', 'askany' ) ) );
		}

		// Get settings
		$woocommerce_enabled = isset( $_POST['woocommerce_enabled'] ) ? (bool) $_POST['woocommerce_enabled'] : false;
		$order_tracking_enabled = isset( $_POST['woocommerce_order_tracking'] ) ? (bool) $_POST['woocommerce_order_tracking'] : false;

		// Save settings
		update_option( 'askany_woocommerce_enabled', $woocommerce_enabled );
		update_option( 'askany_woocommerce_order_tracking', $order_tracking_enabled );

		wp_send_json_success( array( 
			'message' => __( 'WooCommerce settings saved successfully!', 'askany' ),
			'woocommerce_enabled' => $woocommerce_enabled,
			'order_tracking_enabled' => $order_tracking_enabled,
		) );
	}
	
	/**
	 * Get indexed content by type for viewing.
	 *
	 * @return void
	 */
	public function get_indexed_content() {
		// Verify nonce
		if ( ! wp_verify_nonce( $_POST['nonce'], 'askany_admin_nonce' ) ) {
			wp_send_json_error( 'Invalid nonce' );
		}
		
		// Check user permissions
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( 'Insufficient permissions' );
		}
		
		$content_type = sanitize_text_field( $_POST['content_type'] );
		
		// Get content indexer instance
		$database = new Database();
		$content_indexer = new ContentIndexer( $database );
		
		// Get indexed content
		$content_items = $content_indexer->get_indexed_content_by_type( $content_type, 50, 0 );
		
		wp_send_json_success( $content_items );
	}
	
	/**
	 * Get full content details by ID.
	 *
	 * @return void
	 */
	public function get_content_details() {
		// Verify nonce
		if ( ! wp_verify_nonce( $_POST['nonce'], 'askany_admin_nonce' ) ) {
			wp_send_json_error( 'Invalid nonce' );
		}
		
		// Check user permissions
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( 'Insufficient permissions' );
		}
		
		$content_id = intval( $_POST['content_id'] );
		
		// Get content indexer instance
		$database = new Database();
		$content_indexer = new ContentIndexer( $database );
		
		// Get content details
		$content_item = $content_indexer->get_indexed_content_by_id( $content_id );
		
		if ( ! $content_item ) {
			wp_send_json_error( 'Content not found' );
		}
		
		wp_send_json_success( $content_item );
	}

	/**
	 * Get full post content for news display.
	 *
	 * @return void
	 */
	public function get_full_post() {
		check_ajax_referer( 'askany_chat_nonce', 'nonce' );

		$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;

		if ( ! $post_id ) {
			wp_send_json_error( array( 'message' => __( 'Invalid post ID', 'askany' ) ) );
		}

		$news_handler = $this->plugin->get_news_handler();
		$post = $news_handler->get_full_post( $post_id );

		if ( ! $post ) {
			wp_send_json_error( array( 'message' => __( 'Post not found', 'askany' ) ) );
		}

		wp_send_json_success( $post );
	}


	/**
	 * Save feature request from chat conversation.
	 *
	 * @return void
	 */
	public function save_feature_request() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
		$user_name = isset($_POST['user_name']) ? sanitize_text_field( wp_unslash( $_POST['user_name'] ) ) : '';
		$user_email = isset($_POST['user_email']) ? sanitize_email( wp_unslash( $_POST['user_email'] ) ) : '';
		$title = isset($_POST['title']) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';
		$description = isset($_POST['description']) ? sanitize_textarea_field( wp_unslash( $_POST['description'] ) ) : '';

		if ( empty($session_id) || empty($title) || empty($description) ) {
			wp_send_json_error(array( 'message' => __('Missing required fields.', 'askany') ));
		}

		$result = $this->database->save_feature_request($session_id, $user_name, $user_email, $title, $description);

		if ( $result ) {
			wp_send_json_success(array(
				'message' => __('Feature request submitted successfully!', 'askany'),
				'id' => $result['id'],
				'unique_id' => $result['unique_id']
			));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to save feature request.', 'askany') ));
		}
	}

	/**
	 * Save bug report from chat conversation.
	 *
	 * @return void
	 */
	public function save_bug_report() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		$session_id = isset($_POST['session_id']) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '';
		$user_name = isset($_POST['user_name']) ? sanitize_text_field( wp_unslash( $_POST['user_name'] ) ) : '';
		$user_email = isset($_POST['user_email']) ? sanitize_email( wp_unslash( $_POST['user_email'] ) ) : '';
		$title = isset($_POST['title']) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';
		$description = isset($_POST['description']) ? sanitize_textarea_field( wp_unslash( $_POST['description'] ) ) : '';

		if ( empty($session_id) || empty($title) || empty($description) ) {
			wp_send_json_error(array( 'message' => __('Missing required fields.', 'askany') ));
		}

		$result = $this->database->save_bug_report($session_id, $user_name, $user_email, $title, $description);

		if ( $result ) {
			wp_send_json_success(array(
				'message' => __('Bug report submitted successfully!', 'askany'),
				'id' => $result['id'],
				'unique_id' => $result['unique_id']
			));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to save bug report.', 'askany') ));
		}
	}

	/**
	 * Get feature requests for admin page.
	 *
	 * @return void
	 */
	public function get_feature_requests() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$status = isset($_POST['status']) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : null;
		$limit = isset($_POST['limit']) ? intval($_POST['limit']) : 50;

		$requests = $this->database->get_feature_requests($status, $limit);

		if ( $requests !== false ) {
			wp_send_json_success(array( 'requests' => $requests ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to retrieve feature requests.', 'askany') ));
		}
	}

	/**
	 * Get bug reports for admin page.
	 *
	 * @return void
	 */
	public function get_bug_reports() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$status = isset($_POST['status']) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : null;
		$limit = isset($_POST['limit']) ? intval($_POST['limit']) : 50;

		$reports = $this->database->get_bug_reports($status, $limit);

		if ( $reports !== false ) {
			wp_send_json_success(array( 'reports' => $reports ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to retrieve bug reports.', 'askany') ));
		}
	}

	/**
	 * Update feature request status.
	 *
	 * @return void
	 */
	public function update_feature_request_status() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
		$status = isset($_POST['status']) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : '';
		$notes = isset($_POST['notes']) ? sanitize_textarea_field( wp_unslash( $_POST['notes'] ) ) : '';

		if ( empty($id) || empty($status) ) {
			wp_send_json_error(array( 'message' => __('Missing required fields.', 'askany') ));
		}

		$result = $this->database->update_feature_request_status($id, $status, $notes);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('Feature request status updated successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to update feature request status.', 'askany') ));
		}
	}

	/**
	 * Update bug report status.
	 *
	 * @return void
	 */
	public function update_bug_report_status() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
		$status = isset($_POST['status']) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : '';
		$notes = isset($_POST['notes']) ? sanitize_textarea_field( wp_unslash( $_POST['notes'] ) ) : '';

		if ( empty($id) || empty($status) ) {
			wp_send_json_error(array( 'message' => __('Missing required fields.', 'askany') ));
		}

		$result = $this->database->update_bug_report_status($id, $status, $notes);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('Bug report status updated successfully.', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to update bug report status.', 'askany') ));
		}
	}

	/**
	 * Get feature request details.
	 *
	 * @return void
	 */
	public function get_feature_request_details() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$id = isset($_POST['id']) ? intval($_POST['id']) : 0;

		if ( empty($id) ) {
			wp_send_json_error(array( 'message' => __('Missing required fields.', 'askany') ));
		}

		global $wpdb;
		$table = $wpdb->prefix . 'askany_feature_requests';
		$request = $wpdb->get_row(
			$wpdb->prepare("SELECT * FROM {$table} WHERE id = %d", $id)
		);

		if ( $request ) {
			wp_send_json_success(array(
				'description' => $request->feature_description,
				'notes' => $request->notes
			));
		} else {
			wp_send_json_error(array( 'message' => __('Feature request not found.', 'askany') ));
		}
	}

	/**
	 * Get bug report details.
	 *
	 * @return void
	 */
	public function get_bug_report_details() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$id = isset($_POST['id']) ? intval($_POST['id']) : 0;

		if ( empty($id) ) {
			wp_send_json_error(array( 'message' => __('Missing required fields.', 'askany') ));
		}

		global $wpdb;
		$table = $wpdb->prefix . 'askany_bug_reports';
		$report = $wpdb->get_row(
			$wpdb->prepare("SELECT * FROM {$table} WHERE id = %d", $id)
		);

		if ( $report ) {
			wp_send_json_success(array(
				'description' => $report->bug_description,
				'notes' => $report->notes
			));
		} else {
			wp_send_json_error(array( 'message' => __('Bug report not found.', 'askany') ));
		}
	}

	/**
	 * Delete feature request
	 */
	public function delete_feature_request() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$id = isset($_POST['id']) ? intval($_POST['id']) : 0;

		if ( empty($id) ) {
			wp_send_json_error(array( 'message' => __('Invalid feature request ID.', 'askany') ));
		}

		$result = $this->database->delete_feature_request($id);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('Feature request deleted successfully!', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to delete feature request.', 'askany') ));
		}
	}

	/**
	 * Delete bug report
	 */
	public function delete_bug_report() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('You do not have permission to perform this action.', 'askany') ));
		}

		$id = isset($_POST['id']) ? intval($_POST['id']) : 0;

		if ( empty($id) ) {
			wp_send_json_error(array( 'message' => __('Invalid bug report ID.', 'askany') ));
		}

		$result = $this->database->delete_bug_report($id);

		if ( $result ) {
			wp_send_json_success(array( 'message' => __('Bug report deleted successfully!', 'askany') ));
		} else {
			wp_send_json_error(array( 'message' => __('Failed to delete bug report.', 'askany') ));
		}
	}

	/**
	 * Check status of bug report or feature request by unique ID
	 */
	public function check_status() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		$unique_id = isset($_POST['unique_id']) ? sanitize_text_field( wp_unslash( $_POST['unique_id'] ) ) : '';

		if ( empty($unique_id) ) {
			wp_send_json_error(array( 'message' => __('Invalid ID provided.', 'askany') ));
		}

		// Check if it's a bug report or feature request
		if ( strpos($unique_id, 'BUG-') === 0 ) {
			$item = $this->database->get_bug_report_by_unique_id($unique_id);
			$type = 'bug';
		} elseif ( strpos($unique_id, 'FEATURE-') === 0 ) {
			$item = $this->database->get_feature_request_by_unique_id($unique_id);
			$type = 'feature';
		} else {
			wp_send_json_error(array( 'message' => __('Invalid ID format.', 'askany') ));
			return;
		}

		if ( $item ) {
			$response = array(
				'type' => $type,
				'unique_id' => $item->unique_id,
				'status' => $item->status,
				'notes' => $item->notes,
				'created_at' => $item->created_at,
				'updated_at' => $item->updated_at
			);

			if ($type === 'bug') {
				$response['title'] = $item->bug_title;
				$response['description'] = $item->bug_description;
				$response['severity'] = $item->severity;
			} else {
				$response['title'] = $item->feature_title;
				$response['description'] = $item->feature_description;
				$response['priority'] = $item->priority;
			}

			wp_send_json_success($response);
		} else {
			wp_send_json_error(array( 'message' => __('No record found with this ID.', 'askany') ));
		}
	}

	/**
	 * Generate embeddings in batch for RAG
	 */
	public function generate_embeddings_batch() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		// Check if RAG is enabled
		$rag_enabled = get_option( 'askany_rag_enabled', false );
		if ( ! $rag_enabled ) {
			wp_send_json_error(array( 'message' => __('RAG is not enabled.', 'askany') ));
		}

		// Get batch size (default: 10)
		$batch_size = isset($_POST['batch_size']) ? intval($_POST['batch_size']) : 10;
		$offset = isset($_POST['offset']) ? intval($_POST['offset']) : 0;

		// Get content without embeddings (including pending, processing, and failed)
		global $wpdb;
		$content_table = $wpdb->prefix . 'askany_content_index';
		
		$content_items = $wpdb->get_results( $wpdb->prepare(
			"SELECT * FROM {$content_table} 
			WHERE (has_embedding = 0 OR has_embedding IS NULL 
				OR embedding_status = 'pending' 
				OR embedding_status = 'processing' 
				OR embedding_status = 'failed')
			ORDER BY id ASC
			LIMIT %d OFFSET %d",
			$batch_size,
			$offset
		), ARRAY_A );

		if ( empty($content_items) ) {
			wp_send_json_success(array(
				'completed' => true,
				'processed' => 0,
				'message' => __('All embeddings have been generated!', 'askany')
			));
		}

		// Get API manager instance
		$api_manager = new ApiManager();
		
		// Initialize embedding manager
		$embedding_manager = new Embedding_Manager( $this->database, $api_manager );
		
		// Check if optimization is enabled
		$optimization_enabled = get_option( 'askany_rag_optimization_enabled', false );

		$processed = 0;
		$failed = 0;
		$errors = array();

		foreach ( $content_items as $item ) {
			// Update status to processing
			$wpdb->update(
				$content_table,
				array( 'embedding_status' => 'processing' ),
				array( 'id' => $item['id'] )
			);

			// Generate embeddings (use optimized method if enabled)
			if ( $optimization_enabled ) {
				$result = $embedding_manager->generate_content_embeddings_optimized(
					$item['id'],
					$item['object_type'],
					$item['content'],
					array(
						'source_url' => $item['url'],
						'title' => $item['title'],
						'excerpt' => substr( wp_strip_all_tags( $item['content'] ), 0, 500 ),
					)
				);
			} else {
				$result = $embedding_manager->generate_content_embeddings(
					$item['id'],
					$item['object_type'],
					$item['content'],
					array(
						'source_url' => $item['url'],
						'title' => $item['title'],
						'excerpt' => substr( wp_strip_all_tags( $item['content'] ), 0, 500 ),
					)
				);
			}

			if ( is_wp_error( $result ) ) {
				$failed++;
				$errors[] = array(
					'id' => $item['id'],
					'type' => $item['object_type'],
					'error' => $result->get_error_message()
				);
			} else {
				$processed++;
			}
		}

		// Get total count
		$total = $wpdb->get_var( "SELECT COUNT(*) FROM {$content_table}" );
		$remaining = $wpdb->get_var( "SELECT COUNT(*) FROM {$content_table} WHERE (has_embedding = 0 OR has_embedding IS NULL OR embedding_status = 'pending' OR embedding_status = 'processing' OR embedding_status = 'failed')" );

		// Clear dismissed notice when processing completes
		if ( $remaining == 0 ) {
			delete_option( 'askany_rag_notice_dismissed' );
		}

		wp_send_json_success(array(
			'completed' => $remaining == 0,
			'processed' => $processed,
			'failed' => $failed,
			'total' => $total,
			'remaining' => $remaining,
			'errors' => $errors,
			'next_offset' => $offset + $batch_size
		));
	}

	/**
	 * Get embeddings generation status
	 */
	public function get_embeddings_status() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		global $wpdb;
		$content_table = $wpdb->prefix . 'askany_content_index';
		$embeddings_table = $wpdb->prefix . 'askany_embeddings';

		$stats = array(
			'total_content' => $wpdb->get_var( "SELECT COUNT(*) FROM {$content_table}" ),
			'with_embeddings' => $wpdb->get_var( "SELECT COUNT(*) FROM {$content_table} WHERE has_embedding = 1" ),
			'pending' => $wpdb->get_var( "SELECT COUNT(*) FROM {$content_table} WHERE embedding_status = 'pending' OR embedding_status IS NULL" ),
			'processing' => $wpdb->get_var( "SELECT COUNT(*) FROM {$content_table} WHERE embedding_status = 'processing'" ),
			'failed' => $wpdb->get_var( "SELECT COUNT(*) FROM {$content_table} WHERE embedding_status = 'failed'" ),
			'total_embeddings' => $wpdb->get_var( "SELECT COUNT(*) FROM {$embeddings_table}" ),
			'chunked_content' => $wpdb->get_var( "SELECT COUNT(DISTINCT content_id) FROM {$embeddings_table} WHERE total_chunks > 1" ),
		);

		// Get embeddings by content type
		$by_type = $wpdb->get_results( "
			SELECT content_type, COUNT(*) as count 
			FROM {$embeddings_table} 
			GROUP BY content_type
		", ARRAY_A );

		$stats['by_type'] = $by_type;

		wp_send_json_success($stats);
	}

	/**
	 * Clear all embeddings
	 */
	public function clear_all_embeddings() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		global $wpdb;
		$content_table = $wpdb->prefix . 'askany_content_index';
		$embeddings_table = $wpdb->prefix . 'askany_embeddings';

		// Clear embeddings table
		$wpdb->query( "TRUNCATE TABLE {$embeddings_table}" );

		// Reset content index embedding status
		$wpdb->query( "
			UPDATE {$content_table} 
			SET has_embedding = 0, 
				embedding_status = 'pending', 
				embedding_error = NULL
		" );

		wp_send_json_success(array(
			'message' => __('All embeddings cleared successfully', 'askany')
		));
	}

	/**
	 * Save embedding model selection
	 */
	public function save_embedding_model() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		$model = isset( $_POST['model'] ) ? sanitize_text_field( $_POST['model'] ) : '';

		if ( empty( $model ) ) {
			wp_send_json_error(array( 'message' => __('Invalid model', 'askany') ));
		}

		// Validate model
		$valid_models = array(
			'text-embedding-3-small',
			'text-embedding-3-large',
			'text-embedding-ada-002',
			'gemini-embedding-001',
		);

		if ( ! in_array( $model, $valid_models ) ) {
			wp_send_json_error(array( 'message' => __('Invalid model', 'askany') ));
		}

		// Save the model
		update_option( 'askany_embedding_model', $model );

		wp_send_json_success(array(
			'message' => __('Embedding model saved successfully', 'askany'),
			'model' => $model
		));
	}

	/**
	 * Get embedding errors from database
	 */
	public function get_embedding_errors() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		global $wpdb;
		$content_table = $wpdb->prefix . 'askany_content_index';

		// Get all failed items with details (using object_type instead of content_type)
		$errors = $wpdb->get_results( "
			SELECT 
				id as content_id,
				object_type as content_type,
				title,
				embedding_error as error_message,
				updated_at as last_attempt
			FROM {$content_table}
			WHERE embedding_status = 'failed'
			ORDER BY updated_at DESC
			LIMIT 100
		", ARRAY_A );

		if ( empty( $errors ) ) {
			wp_send_json_success(array(
				'errors' => array(),
				'message' => __('No errors found', 'askany')
			));
		}

		// Format the errors for better display
		foreach ( $errors as &$error ) {
			// Format the timestamp
			if ( $error['last_attempt'] ) {
				$error['last_attempt'] = human_time_diff( strtotime( $error['last_attempt'] ), current_time('timestamp') ) . ' ' . __('ago', 'askany');
			}
			
			// Decode title if needed
			if ( $error['title'] ) {
				$error['title'] = html_entity_decode( $error['title'], ENT_QUOTES, 'UTF-8' );
			}
			
			// Clean up error message
			if ( $error['error_message'] ) {
				$error['error_message'] = strip_tags( $error['error_message'] );
			}
		}

		wp_send_json_success(array(
			'errors' => $errors,
			'total' => count( $errors )
		));
	}

	/**
	 * Reset stuck embeddings (items stuck in 'processing' status)
	 */
	public function reset_stuck_embeddings() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		global $wpdb;
		$content_table = $wpdb->prefix . 'askany_content_index';

		// Reset items stuck in 'processing' status back to 'pending'
		$updated = $wpdb->query( "
			UPDATE {$content_table}
			SET embedding_status = 'pending'
			WHERE embedding_status = 'processing'
		" );

		wp_send_json_success(array(
			'message' => sprintf( __('Reset %d stuck items', 'askany'), $updated ),
			'updated' => $updated
		));
	}

	/**
	 * Dismiss RAG notice
	 */
	public function dismiss_rag_notice() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		$notice_type = isset( $_POST['notice_type'] ) ? sanitize_text_field( wp_unslash( $_POST['notice_type'] ) ) : '';

		if ( empty( $notice_type ) ) {
			wp_send_json_error(array( 'message' => __('Invalid notice type.', 'askany') ));
		}

		// Save dismissed notice type to database
		update_option( 'askany_rag_notice_dismissed', $notice_type );

		wp_send_json_success(array( 'message' => __('Notice dismissed.', 'askany') ));
	}

	/**
	 * Check if quota error exists
	 */
	public function check_quota_error() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		$quota_error = get_option( 'askany_quota_error_state', array() );
		
		if ( ! empty( $quota_error ) && isset( $quota_error['has_error'] ) && $quota_error['has_error'] ) {
			wp_send_json_success(array(
				'has_quota_error' => true,
				'error_message' => isset( $quota_error['message'] ) ? $quota_error['message'] : '',
				'is_dismissed' => isset( $quota_error['is_dismissed'] ) ? $quota_error['is_dismissed'] : false
			));
		} else {
			wp_send_json_success(array( 'has_quota_error' => false ));
		}
	}

	/**
	 * Save quota error state
	 */
	public function save_quota_error() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		$error_message = isset( $_POST['error_message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['error_message'] ) ) : '';

		// Get existing quota error state
		$existing_error = get_option( 'askany_quota_error_state', array() );
		$existing_message = isset( $existing_error['message'] ) ? $existing_error['message'] : '';

		// If this is a NEW error (different message), clear the dismissed state
		// This allows the notice to show again for a new quota error
		$is_dismissed = false;
		if ( $existing_message === $error_message && isset( $existing_error['is_dismissed'] ) ) {
			// Same error, keep dismissed state
			$is_dismissed = $existing_error['is_dismissed'];
		}

		// Save quota error state to database
		update_option( 'askany_quota_error_state', array(
			'has_error' => true,
			'message' => $error_message,
			'is_dismissed' => $is_dismissed,
			'timestamp' => current_time( 'mysql' )
		));

		wp_send_json_success(array( 'message' => __('Quota error state saved.', 'askany') ));
	}

	/**
	 * Dismiss quota error notice (but keep blocking processing)
	 */
	public function dismiss_quota_error() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		// Get existing quota error state
		$quota_error = get_option( 'askany_quota_error_state', array() );

		if ( ! empty( $quota_error ) ) {
			// Mark as dismissed but keep the error state (still blocks processing)
			$quota_error['is_dismissed'] = true;
			update_option( 'askany_quota_error_state', $quota_error );
		}

		wp_send_json_success(array( 'message' => __('Quota error notice dismissed.', 'askany') ));
	}

	/**
	 * Clear quota error state (allow retry)
	 */
	public function clear_quota_error() {
		check_ajax_referer('askany_chat_nonce', 'nonce');

		if ( ! current_user_can('manage_options') ) {
			wp_send_json_error(array( 'message' => __('Unauthorized access.', 'askany') ));
		}

		// Clear quota error state from database completely
		delete_option( 'askany_quota_error_state' );

		wp_send_json_success(array( 'message' => __('Quota error state cleared.', 'askany') ));
	}

	/**
	 * Save rate limit settings via AJAX.
	 *
	 * @return void
	 */
	public function save_rate_limit_settings() {
		check_ajax_referer( 'askany_chat_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Permission denied.', 'askany' ) ) );
		}

		$enabled = isset( $_POST['rate_limit_enabled'] ) ? (bool) $_POST['rate_limit_enabled'] : false;
		$roles_raw = isset( $_POST['rate_limit_roles'] ) ? wp_unslash( $_POST['rate_limit_roles'] ) : '{}';
		$roles = json_decode( $roles_raw, true );

		if ( ! is_array( $roles ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid data format.', 'askany' ) ) );
		}

		\Askany\RateLimiter::save_settings( $enabled, $roles );

		wp_send_json_success( array( 'message' => __( 'Rate limit settings saved.', 'askany' ) ) );
	}
}