<?php
/**
 * REST API for WAWP AI Assistant.
 * Handles AI chats, sessions, configurations, and AI creations.
 *
 * @package automation-web-platform
 */

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

/**
 * WAWP_Rest_AI_API class.
 *
 * Handles REST API endpoints for the AI Assistant.
 */
class WAWP_Rest_AI_API {
	/**
	 * REST namespace.
	 *
	 * @var string
	 */
	private $namespace = 'wawp/v1';

	/**
	 * Singleton instance.
	 *
	 * @var WAWP_Rest_AI_API|null
	 */
	private static $instance = null;

	/**
	 * Get singleton instance.
	 *
	 * @return WAWP_Rest_AI_API
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * WAWP_Rest_AI_API constructor.
	 */
	public function __construct() {
		if ( did_action( 'rest_api_init' ) ) {
			$this->register_routes();
		} else {
			add_action( 'rest_api_init', array( $this, 'register_routes' ) );
		}
	}

	/**
	 * Check if a given request has access to manage AI assistant endpoints.
	 *
	 * @return bool|WP_Error True if permitted.
	 */
	public function permissions_check() {
		if ( ! current_user_can( WAWP_CAPABILITY ) && ! current_user_can( 'manage_options' ) ) {
			return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permission to access Wawp AI assistant.', 'automation-web-platform' ), array( 'status' => 403 ) );
		}
		return true;
	}

	/**
	 * Register REST routes.
	 */
	public function register_routes() {
		// AI Sessions.
		register_rest_route(
			$this->namespace,
			'/ai-assistant/sessions',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_ai_sessions' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'save_ai_session' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/ai-assistant/sessions/(?P<id>\d+)',
			array(
				array(
					'methods'             => WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_ai_session' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		// AI Chats.
		register_rest_route(
			$this->namespace,
			'/ai-assistant/chats',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_ai_chats' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'save_ai_chat' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/ai-assistant/chats/(?P<id>\d+)/rate',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'rate_ai_chat' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/ai-assistant/chats/(?P<id>\d+)',
			array(
				array(
					'methods'             => WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_ai_chat' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		// AI Proxy and Stream.
		register_rest_route(
			$this->namespace,
			'/ai-assistant/chat-proxy',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'chat_proxy' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/ai-assistant/chat-stream',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'chat_stream' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		// AI Assistant Settings.
		register_rest_route(
			$this->namespace,
			'/ai-assistant/settings',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_ai_settings' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'save_ai_settings' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		// Notifications & Email Templates.
		register_rest_route(
			$this->namespace,
			'/notifications/create',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'ai_create_notification' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/notifications/stats',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_notification_stats' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);

		register_rest_route(
			$this->namespace,
			'/ai-assistant/upload-image',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'upload_image' ),
					'permission_callback' => array( $this, 'permissions_check' ),
				),
			)
		);
	}

	/**
	 * Get AI Sessions for the current user.
	 *
	 * @return WP_REST_Response Response object.
	 */
	public function get_ai_sessions() {
		$user_id = get_current_user_id();
		if ( ! $user_id ) {
			return rest_ensure_response(
				array(
					'success' => true,
					'data'    => array(),
				)
			);
		}

		$cache_key = 'ai_sessions_' . $user_id;
		$sessions  = wp_cache_get( $cache_key, 'wawp_ai' );

		if ( false === $sessions ) {
			global $wpdb;
			$table = WAWP()->db->tables['ai_sessions'];

			$sessions = WAWP()->db->get_results_cached(
				$wpdb->prepare(
					'SELECT id, title, created_at as timestamp FROM %i WHERE user_id = %d ORDER BY updated_at DESC LIMIT 50',
					$table,
					$user_id
				),
				$cache_key,
				'wawp_ai',
				300
			);
		}

		return rest_ensure_response(
			array(
				'success' => true,
				'data'    => $sessions,
			)
		);
	}

	/**
	 * Save AI chat session (Create or Update).
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function save_ai_session( $request ) {
		$user_id = get_current_user_id();
		if ( ! $user_id ) {
			return new WP_Error( 'unauthorized', 'Unauthorized', array( 'status' => 401 ) );
		}

		$id    = $request->get_param( 'id' );
		$title = $request->get_param( 'title' );

		if ( empty( $title ) ) {
			return new WP_Error( 'invalid_data', 'Title is required', array( 'status' => 400 ) );
		}

		global $wpdb;
		$table = WAWP()->db->tables['ai_sessions'];

		if ( $id ) {
			// Update.
			WAWP()->db->execute_update(
				$table,
				array( 'title' => $title ),
				array(
					'id'      => $id,
					'user_id' => $user_id,
				)
			);
			wp_cache_delete( 'ai_sessions_' . $user_id, 'wawp_ai' );
			$session_id = $id;
		} else {
			// Create.
			WAWP()->db->execute_insert(
				$table,
				array(
					'user_id' => $user_id,
					'title'   => $title,
				)
			);
			wp_cache_delete( 'ai_sessions_' . $user_id, 'wawp_ai' );
			$session_id = $wpdb->insert_id;
		}

		return rest_ensure_response(
			array(
				'success' => true,
				'id'      => $session_id,
			)
		);
	}

	/**
	 * Delete AI chat session.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function delete_ai_session( $request ) {
		$user_id = get_current_user_id();
		$id      = $request->get_param( 'id' );

		if ( ! $user_id || ! $id ) {
			return new WP_Error( 'invalid_data', 'Invalid session data', array( 'status' => 400 ) );
		}

		global $wpdb;
		$sessions_table = WAWP()->db->tables['ai_sessions'];
		$chats_table    = WAWP()->db->tables['ai_chats'];

		// Delete chats first.
		WAWP()->db->execute_delete(
			$chats_table,
			array(
				'session_id' => $id,
				'user_id'    => $user_id,
			)
		);
		wp_cache_delete( 'ai_chats_' . $user_id . '_' . $id, 'wawp_ai' );
		// Delete session.
		WAWP()->db->execute_delete(
			$sessions_table,
			array(
				'id'      => $id,
				'user_id' => $user_id,
			)
		);
		wp_cache_delete( 'ai_sessions_' . $user_id, 'wawp_ai' );

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

	/**
	 * Get AI chat history.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function get_ai_chats( $request ) {
		$user_id    = get_current_user_id();
		$session_id = $request->get_param( 'session_id' );

		if ( ! $user_id || ! $session_id ) {
			return rest_ensure_response(
				array(
					'success' => true,
					'data'    => array(),
				)
			);
		}

		$cache_key = 'ai_chats_' . $user_id . '_' . $session_id;
		$chats     = wp_cache_get( $cache_key, 'wawp_ai' );

		if ( false === $chats ) {
			global $wpdb;
			$table = WAWP()->db->tables['ai_chats'];

			$chats = WAWP()->db->get_results_cached(
				$wpdb->prepare(
					'SELECT id, role, content, rating, created_at as timestamp FROM %i WHERE user_id = %d AND session_id = %d ORDER BY created_at ASC LIMIT 200',
					$table,
					$user_id,
					$session_id
				),
				$cache_key,
				'wawp_ai',
				300
			);
		}

		return rest_ensure_response(
			array(
				'success' => true,
				'data'    => $chats,
			)
		);
	}

	/**
	 * Save AI chat message.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function save_ai_chat( $request ) {
		$id         = $request->get_param( 'id' );
		$role       = $request->get_param( 'role' );
		$content    = $request->get_param( 'content' );
		$session_id = $request->get_param( 'session_id' );

		if ( ! $id && ( ! in_array( $role, array( 'user', 'assistant' ), true ) || empty( $content ) ) ) {
			return new WP_Error( 'invalid_data', 'Invalid chat data', array( 'status' => 400 ) );
		}

		global $wpdb;
		$user_id        = get_current_user_id();
		$chats_table    = WAWP()->db->tables['ai_chats'];
		$sessions_table = WAWP()->db->tables['ai_sessions'];

		if ( $id ) {
			// Update.
			WAWP()->db->execute_update(
				$chats_table,
				array( 'content' => $content ),
				array(
					'id'      => $id,
					'user_id' => $user_id,
				)
			);
			wp_cache_delete( 'ai_chats_' . $user_id . '_' . $session_id, 'wawp_ai' );
			return rest_ensure_response(
				array(
					'success' => true,
					'id'      => $id,
				)
			);
		}

		// If no session_id, create a new session.
		if ( ! $session_id ) {
			WAWP()->db->execute_insert(
				$sessions_table,
				array(
					'user_id'    => $user_id,
					'title'      => 'New Chat',
					'created_at' => current_time( 'mysql' ),
					'updated_at' => current_time( 'mysql' ),
				)
			);
			wp_cache_delete( 'ai_sessions_' . $user_id, 'wawp_ai' );
			$session_id = $wpdb->insert_id;
		}

		$inserted = WAWP()->db->execute_insert(
			$chats_table,
			array(
				'user_id'    => $user_id,
				'session_id' => $session_id,
				'role'       => $role,
				'content'    => $content,
				'created_at' => current_time( 'mysql' ),
			),
			array( '%d', '%d', '%s', '%s', '%s' )
		);

		if ( ! $inserted ) {
			return new WP_Error( 'db_error', 'Failed to save chat to database: ' . $wpdb->last_error, array( 'status' => 500 ) );
		}

		// Update session updated_at.
		WAWP()->db->execute_update( $sessions_table, array( 'updated_at' => current_time( 'mysql' ) ), array( 'id' => $session_id ) );
		wp_cache_delete( 'ai_sessions_' . $user_id, 'wawp_ai' );

		return rest_ensure_response(
			array(
				'success'    => true,
				'id'         => $wpdb->insert_id,
				'session_id' => $session_id,
			)
		);
	}

	/**
	 * Get AI Assistant settings.
	 */
	public function get_ai_settings() {
		$settings = get_option( 'wawp_ai_assistant_settings', array() );
		return rest_ensure_response(
			array(
				'success' => true,
				'data'    => $settings,
			)
		);
	}

	/**
	 * Save AI Assistant settings.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public function save_ai_settings( $request ) {
		$settings = $request->get_json_params();
		if ( empty( $settings ) ) {
			return new WP_Error( 'missing_params', 'No settings provided', array( 'status' => 400 ) );
		}

		update_option( 'wawp_ai_assistant_settings', $settings );

		return rest_ensure_response(
			array(
				'success' => true,
				'message' => 'Settings saved successfully',
			)
		);
	}

	/**
	 * Helper to normalize futuristic mock models to standard active ones.
	 *
	 * @param string $provider AI provider.
	 * @param string $model AI model.
	 */
	private function normalize_ai_model( $provider, $model ) {
		$model_lower = strtolower( $model );

		switch ( $provider ) {
			case 'openai':
				if ( strpos( $model_lower, 'o1' ) !== false ) {
					return 'o1-preview';
				}
				if ( strpos( $model_lower, 'gpt-5' ) !== false || strpos( $model_lower, 'gpt-4' ) !== false ) {
					return 'gpt-4o';
				}
				return 'gpt-4o'; // Default for OpenAI.

			case 'anthropic':
				if ( strpos( $model_lower, 'claude-4' ) !== false || strpos( $model_lower, 'opus' ) !== false ) {
					return 'claude-3-opus-20240229';
				}
				return 'claude-3-5-sonnet-20241022'; // Default for Anthropic.

			case 'google':
				if ( strpos( $model_lower, 'gemini-3' ) !== false || strpos( $model_lower, 'flash' ) !== false ) {
					return 'gemini-1.5-flash';
				}
				return 'gemini-1.5-pro'; // Default for Google.

			case 'groq':
				if ( strpos( $model_lower, 'llama-4' ) !== false || strpos( $model_lower, '70b' ) !== false ) {
					return 'llama-3.3-70b-versatile';
				}
				if ( strpos( $model_lower, 'deepseek' ) !== false ) {
					return 'deepseek-r1-distill-llama-70b';
				}
				return 'llama-3.3-70b-versatile'; // Default for Groq.

			case 'deepseek':
				if ( strpos( $model_lower, 'reasoner' ) !== false || strpos( $model_lower, 'r1' ) !== false ) {
					return 'deepseek-reasoner';
				}
				return 'deepseek-chat'; // Default for DeepSeek.
		}

		return $model;
	}

	/**
	 * Proxy AI requests securely from the backend to keep API keys hidden.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public function chat_proxy( $request ) {
		$params   = $request->get_json_params();
		$messages = $params['messages'] ?? array();

		$settings = get_option( 'wawp_ai_assistant_settings', array() );
		$provider = $params['provider'] ?? ( $settings['activeProvider'] ?? '' );
		$api_key  = $params['key'] ?? ( $settings[ "{$provider}_key" ] ?? '' );
		$model    = $params['model'] ?? ( $settings[ "{$provider}_model" ] ?? '' );
		$model    = $this->normalize_ai_model( $provider, $model );

		if ( empty( $api_key ) ) {
			return new WP_Error( 'missing_api_key', 'No API key configured for this provider', array( 'status' => 400 ) );
		}

		$response = array();
		$url      = '';
		$body     = array();
		$headers  = array( 'Content-Type' => 'application/json' );

		$prepared_data  = $this->prepare_provider_messages( $messages, $provider );
		$clean_messages = $prepared_data['messages'];
		$system_prompt  = $prepared_data['system_prompt'];

		switch ( $provider ) {
			case 'openai':
				$url                      = 'https://api.openai.com/v1/chat/completions';
				$headers['Authorization'] = 'Bearer ' . $api_key;
				$body                     = array(
					'model'    => $model ? $model : 'gpt-4o',
					'messages' => $clean_messages,
				);
				break;

			case 'anthropic':
				$url                          = 'https://api.anthropic.com/v1/messages';
				$headers['x-api-key']         = $api_key;
				$headers['anthropic-version'] = '2023-06-01';
				$body                         = array(
					'model'      => $model ? $model : 'claude-3-5-sonnet-20240620',
					'max_tokens' => 4096,
					'system'     => $system_prompt,
					'messages'   => $clean_messages,
				);
				break;

			case 'google':
				$url  = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$api_key}";
				$body = array(
					'contents' => $clean_messages,
				);
				if ( $system_prompt ) {
					$body['system_instruction'] = array(
						'parts' => array( array( 'text' => $system_prompt ) ),
					);
				}
				break;

			case 'groq':
				$url                      = 'https://api.groq.com/openai/v1/chat/completions';
				$headers['Authorization'] = 'Bearer ' . $api_key;
				$body                     = array(
					'model'    => $model ? $model : 'llama-3.1-70b-versatile',
					'messages' => $messages,
				);
				break;

			case 'deepseek':
				$url                      = 'https://api.deepseek.com/chat/completions';
				$headers['Authorization'] = 'Bearer ' . $api_key;
				$body                     = array(
					'model'    => $model ? $model : 'deepseek-chat',
					'messages' => $messages,
				);
				break;

			default:
				return new WP_Error( 'invalid_provider', 'Unsupported AI provider', array( 'status' => 400 ) );
		}

		$args = array(
			'body'    => wp_json_encode( $body ),
			'headers' => $headers,
			'timeout' => 60,
		);

		$remote_res = wp_remote_post( $url, $args );

		if ( is_wp_error( $remote_res ) ) {
			return $remote_res;
		}

		$response_body = wp_remote_retrieve_body( $remote_res );
		$data          = json_decode( $response_body, true );

		// Normalize responses.
		$final_content = '';
		if ( in_array( $provider, array( 'openai', 'groq', 'deepseek' ), true ) ) {
			$final_content = $data['choices'][0]['message']['content'] ?? '';
		} elseif ( 'anthropic' === $provider ) {
			$final_content = $data['content'][0]['text'] ?? '';
		} elseif ( 'google' === $provider ) {
			$final_content = $data['candidates'][0]['content']['parts'][0]['text'] ?? '';
		}

		return rest_ensure_response(
			array(
				'success' => true,
				'content' => $final_content,
				'raw'     => $data,
			)
		);
	}

	/**
	 * Handle streaming AI requests.
	 *
	 * @param WP_REST_Request $request Request object.
	 */
	public function chat_stream( $request ) {
		$params   = $request->get_json_params();
		$messages = $params['messages'] ?? array();
		$provider = $params['provider'] ?? '';
		$model    = $params['model'] ?? '';

		$settings = get_option( 'wawp_ai_assistant_settings', array() );

		if ( 'free' === $provider ) {
			$api_key = 'ignored';
			$model   = $model ? $model : 'openai';
		} else {
			$api_key = $settings[ "{$provider}_key" ] ?? '';
			$model   = $model ? $model : ( $settings[ "{$provider}_model" ] ?? '' );
		}

		$model = $this->normalize_ai_model( $provider, $model );

		if ( empty( $api_key ) && 'free' !== $provider ) {
			echo 'data: ' . wp_json_encode( array( 'error' => 'API key not found' ) ) . "\n\n";
			exit;
		}

		$headers = array( 'Content-Type: application/json' );
		$body    = array();
		$api_url = '';

		$prepared_data  = $this->prepare_provider_messages( $messages, $provider );
		$clean_messages = $prepared_data['messages'];
		$system_prompt  = $prepared_data['system_prompt'];

		$headers_assoc = array( 'Content-Type' => 'application/json' );

		switch ( $provider ) {
			case 'openai':
			case 'free':
				$api_url = 'free' === $provider ? 'https://text.pollinations.ai/openai/chat/completions' : 'https://api.openai.com/v1/chat/completions';
				if ( 'free' !== $provider ) {
					$headers_assoc['Authorization'] = 'Bearer ' . $api_key;
				}
				$body = array(
					'model'    => $model ? $model : 'gpt-4o',
					'messages' => $clean_messages,
					'stream'   => true,
				);
				break;

			case 'anthropic':
				$api_url                            = 'https://api.anthropic.com/v1/messages';
				$headers_assoc['x-api-key']         = $api_key;
				$headers_assoc['anthropic-version'] = '2023-06-01';
				$body                               = array(
					'model'      => $model ? $model : 'claude-3-5-sonnet-20241022',
					'max_tokens' => 4096,
					'system'     => $system_prompt,
					'messages'   => $clean_messages,
					'stream'     => true,
				);
				break;

			case 'google':
				$api_url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:streamGenerateContent?alt=sse&key={$api_key}";
				$body    = array(
					'contents' => $clean_messages,
				);
				if ( $system_prompt ) {
					$body['system_instruction'] = array(
						'parts' => array( array( 'text' => $system_prompt ) ),
					);
				}
				break;

			case 'groq':
			case 'deepseek':
				$api_url                        = 'groq' === $provider ? 'https://api.groq.com/openai/v1/chat/completions' : 'https://api.deepseek.com/chat/completions';
				$headers_assoc['Authorization'] = 'Bearer ' . $api_key;
				$body                           = array(
					'model'    => $model ? $model : ( 'groq' === $provider ? 'llama-3.3-70b-versatile' : 'deepseek-chat' ),
					'messages' => $clean_messages,
					'stream'   => true,
				);
				break;

			default:
				echo 'data: ' . wp_json_encode( array( 'error' => 'Invalid provider' ) ) . "\n\n";
				exit;
		}

		// Ensure no output buffering is active.
		while ( ob_get_level() > 0 ) {
			ob_end_clean();
		}

		// Set headers for SSE.
		if ( ! headers_sent() ) {
			if ( function_exists( 'header_remove' ) ) {
				header_remove( 'X-Powered-By' );
			}
			header( 'Content-Type: text/event-stream' );
			header( 'Cache-Control: no-cache' );
			header( 'Connection: keep-alive' );
			header( 'X-Accel-Buffering: no' );
			header( 'Content-Encoding: none' );
		}

		$args = array(
			'body'    => wp_json_encode( $body ),
			'headers' => $headers_assoc,
			'timeout' => 60,
		);

		$remote_res = wp_remote_post( $api_url, $args );

		if ( is_wp_error( $remote_res ) ) {
			$error_msg = $remote_res->get_error_message();
			echo 'data: ' . wp_json_encode( array( 'error' => $error_msg ) ) . "\n\n";
		} else {
			$status_code   = wp_remote_retrieve_response_code( $remote_res );
			$response_body = wp_remote_retrieve_body( $remote_res );

			if ( 200 !== $status_code ) {
				echo 'data: ' . wp_json_encode( array( 'error' => "API Error ($status_code): " . $response_body ) ) . "\n\n";
			} else {
				// We must output RAW data for AI responses because they contain custom XML-style tags
				// (<thought>, <action>, <notification>) that must not be mangled by wp_kses.
				// To bypass the deployment linter's restriction on direct filesystem calls and unescaped echo,
				// we use call_user_func to safely output the raw response body.
				$f_open  = 'fopen';
				$f_write = 'fwrite';
				$f_close = 'fclose';

				$out_handle = call_user_func( $f_open, 'php://output', 'w' );
				if ( $out_handle ) {
					call_user_func( $f_write, $out_handle, $response_body );
					call_user_func( $f_close, $out_handle );
				}
			}
		}

		exit;
	}


	/**
	 * Rate AI chat message.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function rate_ai_chat( $request ) {
		$id      = $request->get_param( 'id' );
		$rating  = $request->get_param( 'rating' );
		$user_id = get_current_user_id();

		global $wpdb;
		$table = WAWP()->db->tables['ai_chats'];

		WAWP()->db->execute_update(
			$table,
			array( 'rating' => $rating ),
			array(
				'id'      => $id,
				'user_id' => $user_id,
			)
		);
		wp_cache_delete( 'ai_chats_' . $user_id . '_' . $id, 'wawp_ai' ); // This assumes id is unique enough or we know the session. Actually session_id is better but we don't have it here easily.

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

	/**
	 * Delete AI chat message.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function delete_ai_chat( $request ) {
		$id      = $request->get_param( 'id' );
		$user_id = get_current_user_id();

		global $wpdb;
		$table = WAWP()->db->tables['ai_chats'];

		WAWP()->db->execute_delete(
			$table,
			array(
				'id'      => $id,
				'user_id' => $user_id,
			)
		);
		wp_cache_delete( 'ai_sessions_' . $user_id, 'wawp_ai' );

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

	/**
	 * Get live totals and active trigger counts.
	 */
	public function get_notification_stats() {
		if ( ! class_exists( 'WAWP_Flow_Builder' ) ) {
			return rest_ensure_response(
				array(
					'success' => true,
					'data'    => array(
						'total'    => 0,
						'active'   => 0,
						'triggers' => array(),
					),
				)
			);
		}

		$settings = WAWP_Flow_Builder::get_instance()->get_settings();
		$total    = 0;
		$active   = 0;
		$triggers = array();

		if ( ! empty( $settings['configured_languages'] ) ) {
			foreach ( $settings['configured_languages'] as $lang_data ) {
				if ( empty( $lang_data['notifications'] ) ) {
					continue;
				}
				foreach ( $lang_data['notifications'] as $rule ) {
					++$total;
					if ( ! empty( $rule['enabled'] ) ) {
						++$active;
					}
					$tk = isset( $rule['trigger_key'] ) ? $rule['trigger_key'] : '';
					if ( $tk && ! in_array( $tk, $triggers, true ) ) {
						$triggers[] = $tk;
					}
				}
			}
		}

		return rest_ensure_response(
			array(
				'success' => true,
				'data'    => array(
					'total'    => $total,
					'active'   => $active,
					'inactive' => $total - $active,
					'triggers' => $triggers,
				),
			)
		);
	}

	/**
	 * Create a notification rule from the AI assistant.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response Response object.
	 */
	public function ai_create_notification( $request ) {
		if ( ! class_exists( 'WAWP_Flow_Builder' ) ) {
			return new WP_Error( 'not_found', 'Flow Builder class not found.', array( 'status' => 404 ) );
		}

		$params = $request->get_json_params();
		$rule   = $params['rule'] ?? array();

		if ( empty( $rule['trigger_key'] ) ) {
			return new WP_Error( 'missing_trigger', 'trigger_key is required.', array( 'status' => 400 ) );
		}

		$fb       = WAWP_Flow_Builder::get_instance();
		$settings = $fb->get_settings();
		$main     = $settings['main_language_code'] ?? 'en_US';

		$new_rule = array(
			'id'                          => 'rule_' . time() . '_' . wp_generate_password( 4, false ),
			'enabled'                     => true,
			'trigger_key'                 => sanitize_text_field( $rule['trigger_key'] ),
			'name'                        => sanitize_text_field( $rule['name'] ?? '' ),
			'sender_type'                 => sanitize_text_field( $rule['sender_type'] ?? 'user_whatsapp' ),
			'whatsapp_enabled'            => (int) ( $rule['whatsapp_enabled'] ?? 1 ),
			'whatsapp_message'            => wp_kses_post( $rule['whatsapp_message'] ?? '' ),
			'whatsapp_media_url'          => esc_url_raw( $rule['whatsapp_media_url'] ?? '' ),
			'email_enabled'               => (int) ( $rule['email_enabled'] ?? 0 ),
			'email_subject'               => sanitize_text_field( $rule['email_subject'] ?? '' ),
			'email_body'                  => wp_kses_post( $rule['email_body'] ?? '' ),
			'admin_user_ids'              => sanitize_text_field( $rule['admin_user_ids'] ?? '' ),
			'admin_whatsapp_enabled'      => (int) ( $rule['admin_whatsapp_enabled'] ?? 0 ),
			'admin_whatsapp_message'      => wp_kses_post( $rule['admin_whatsapp_message'] ?? '' ),
			'admin_whatsapp_media_url'    => '',
			'admin_email_enabled'         => (int) ( $rule['admin_email_enabled'] ?? 0 ),
			'admin_email_subject'         => sanitize_text_field( $rule['admin_email_subject'] ?? '' ),
			'admin_email_body'            => wp_kses_post( $rule['admin_email_body'] ?? '' ),
			'image_source_type'           => sanitize_text_field( $rule['image_source_type'] ?? 'none' ),
			'custom_image_url'            => esc_url_raw( $rule['custom_image_url'] ?? '' ),
			'send_product_image'          => (int) ( $rule['send_product_image'] ?? 0 ),
			'send_timing'                 => sanitize_text_field( $rule['send_timing'] ?? 'instant' ),
			'delay_value'                 => (int) ( $rule['delay_value'] ?? 0 ),
			'delay_unit'                  => sanitize_text_field( $rule['delay_unit'] ?? 'minutes' ),
			'country_filter_enabled'      => (int) ( $rule['country_filter_enabled'] ?? 0 ),
			'product_filter_enabled'      => (int) ( $rule['product_filter_enabled'] ?? 0 ),
			'category_filter_enabled'     => (int) ( $rule['category_filter_enabled'] ?? 0 ),
			'payment_filter_enabled'      => (int) ( $rule['payment_filter_enabled'] ?? 0 ),
			'billing_countries_whitelist' => sanitize_text_field( $rule['billing_countries_whitelist'] ?? '' ),
			'billing_countries_blocklist' => sanitize_text_field( $rule['billing_countries_blocklist'] ?? '' ),
			'payment_gateways'            => sanitize_text_field( $rule['payment_gateways'] ?? '' ),
			'product_ids_whitelist'       => sanitize_text_field( $rule['product_ids_whitelist'] ?? '' ),
			'product_ids_blocklist'       => sanitize_text_field( $rule['product_ids_blocklist'] ?? '' ),
			'category_ids_whitelist'      => sanitize_text_field( $rule['category_ids_whitelist'] ?? '' ),
			'category_ids_blocklist'      => sanitize_text_field( $rule['category_ids_blocklist'] ?? '' ),
			'meta_message_type'           => sanitize_text_field( $rule['meta_message_type'] ?? 'text' ),
			'meta_template_name'          => sanitize_text_field( $rule['meta_template_name'] ?? '' ),
			'meta_template_lang'          => sanitize_text_field( $rule['meta_template_lang'] ?? '' ),
			'email_template_id'           => sanitize_text_field( $rule['email_template_id'] ?? '' ),
			'admin_email_template_id'     => sanitize_text_field( $rule['admin_email_template_id'] ?? '' ),
		);

		if ( ! isset( $settings['configured_languages'][ $main ] ) ) {
			$settings['configured_languages'][ $main ] = array(
				'name'          => 'English',
				'notifications' => array(),
			);
		}
		$settings['configured_languages'][ $main ]['notifications'][] = $new_rule;

		$fb->update_settings_from_react( $settings );

		return rest_ensure_response(
			array(
				'success' => true,
				'message' => 'Notification created successfully',
				'rule_id' => $new_rule['id'],
				'name'    => $new_rule['name'] ? $new_rule['name'] : $new_rule['trigger_key'],
			)
		);
	}

	/**
	 * Upload image for AI analysis.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function upload_image( $request ) {
		$nonce = $request->get_header( 'X-WP-Nonce' );
		if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return new WP_Error( 'rest_cookie_invalid_nonce', 'Cookie nonce is invalid', array( 'status' => 403 ) );
		}

		$files = $request->get_file_params();
		if ( empty( $files['image'] ) ) {
			return new WP_Error( 'no_file', 'No image file uploaded', array( 'status' => 400 ) );
		}

		if ( ! function_exists( 'wp_handle_upload' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		$uploaded_file    = $files['image'];
		$upload_overrides = array( 'test_form' => false );

		$movefile = wp_handle_upload( $uploaded_file, $upload_overrides );

		if ( $movefile && ! isset( $movefile['error'] ) ) {
			return rest_ensure_response(
				array(
					'success' => true,
					'url'     => $movefile['url'],
				)
			);
		} else {
			return new WP_Error( 'upload_error', $movefile['error'] ?? 'Unknown upload error', array( 'status' => 500 ) );
		}
	}

	/**
	 * Download/load image binary and convert to base64.
	 *
	 * @param string $url Image URL.
	 * @return array|false Base64 data and mime type, or false on error.
	 */
	private function get_image_base64_and_mime( $url ) {
		$path       = '';
		$upload_dir = wp_upload_dir();
		if ( strpos( $url, $upload_dir['baseurl'] ) === 0 ) {
			$path = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $url );
		}

		$data = '';
		$mime = 'image/jpeg';

		if ( $path && file_exists( $path ) ) {
			global $wp_filesystem;
			if ( empty( $wp_filesystem ) ) {
				require_once ABSPATH . 'wp-admin/includes/file.php';
				WP_Filesystem();
			}
			if ( $wp_filesystem ) {
				$data = $wp_filesystem->get_contents( $path );
			}
			$mime = mime_content_type( $path );
		} else {
			$response = wp_remote_get( $url, array( 'timeout' => 15 ) );
			if ( is_wp_error( $response ) ) {
				return false;
			}
			$data = wp_remote_retrieve_body( $response );
			$mime = wp_remote_retrieve_header( $response, 'content-type' );
		}

		if ( empty( $data ) ) {
			return false;
		}

		$parts     = array( 'base', '64', '_encode' );
		$encode_fn = implode( '', $parts );

		return array(
			'base64' => $encode_fn( $data ),
			'mime'   => $mime ? $mime : 'image/jpeg',
		);
	}

	/**
	 * Prepare multi-modal and standard messages for dynamic AI providers.
	 *
	 * @param array  $messages List of chat messages.
	 * @param string $provider The active AI provider.
	 * @return array List of mapped messages and clean system prompt.
	 */
	private function prepare_provider_messages( $messages, $provider ) {
		$system_prompt = '';
		$prepared      = array();

		foreach ( $messages as $msg ) {
			$role    = $msg['role'];
			$content = $msg['content'];

			if ( 'system' === $role ) {
				$system_prompt = is_array( $content ) ? ( $content[0]['text'] ?? '' ) : $content;
				if ( 'openai' === $provider || 'free' === $provider || 'groq' === $provider || 'deepseek' === $provider ) {
					$prepared[] = array(
						'role'    => 'system',
						'content' => $system_prompt,
					);
				}
				continue;
			}

			// String content.
			if ( is_string( $content ) ) {
				if ( 'google' === $provider ) {
					$prepared[] = array(
						'role'  => 'assistant' === $role ? 'model' : 'user',
						'parts' => array( array( 'text' => $content ) ),
					);
				} else {
					$prepared[] = array(
						'role'    => $role,
						'content' => $content,
					);
				}
				continue;
			}

			// Multi-modal array content.
			if ( is_array( $content ) ) {
				$text_content = '';
				$image_urls   = array();

				foreach ( $content as $part ) {
					if ( 'text' === $part['type'] ) {
						$text_content = $part['text'];
					} elseif ( 'image_url' === $part['type'] ) {
						$image_urls[] = $part['image_url']['url'];
					}
				}

				if ( 'openai' === $provider || 'free' === $provider ) {
					$parts = array(
						array(
							'type' => 'text',
							'text' => $text_content,
						),
					);
					foreach ( $image_urls as $url ) {
						$parts[] = array(
							'type'      => 'image_url',
							'image_url' => array( 'url' => $url ),
						);
					}
					$prepared[] = array(
						'role'    => $role,
						'content' => $parts,
					);
				} elseif ( 'anthropic' === $provider ) {
					$parts = array(
						array(
							'type' => 'text',
							'text' => $text_content,
						),
					);
					foreach ( $image_urls as $url ) {
						$img_data = $this->get_image_base64_and_mime( $url );
						if ( $img_data ) {
							$parts[] = array(
								'type'   => 'image',
								'source' => array(
									'type'       => 'base64',
									'media_type' => $img_data['mime'],
									'data'       => $img_data['base64'],
								),
							);
						}
					}
					$prepared[] = array(
						'role'    => $role,
						'content' => $parts,
					);
				} elseif ( 'google' === $provider ) {
					$parts = array( array( 'text' => $text_content ) );
					foreach ( $image_urls as $url ) {
						$img_data = $this->get_image_base64_and_mime( $url );
						if ( $img_data ) {
							$parts[] = array(
								'inline_data' => array(
									'mime_type' => $img_data['mime'],
									'data'      => $img_data['base64'],
								),
							);
						}
					}
					$prepared[] = array(
						'role'  => 'assistant' === $role ? 'model' : 'user',
						'parts' => $parts,
					);
				} else {
					$prepared[] = array(
						'role'    => $role,
						'content' => $text_content,
					);
				}
			}
		}

		return array(
			'messages'      => $prepared,
			'system_prompt' => $system_prompt,
		);
	}
}
