<?php
/**
 * Plugin Name: Talk To Website
 * Plugin URI: https://talktowebsite.com/
 * Description: An AI chatbot that is pre-trained on articles from your website. It allows users to communicate with the website as if it were a live person. Ask context-sensitive questions and get answers based on the information that is written within the articles. The plugin works by interacting with the OpenAI API.
 * Version: 1.0
 * Author: Vitalii A. Popov
 * Author URI: https://profiles.wordpress.org/talktowebsite/
 * License: GPLv2
 * License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
 * Text Domain: talk-to-website
 * Domain Path: /languages
 */

// Plugin requirements (developer environment)
// PHP v.8.2
// WordPress: 6.2

//------------------------------------------------------------------------
// Used files structure: Boilerplate template, recommended by Wordpress.
// https://developer.wordpress.org/plugins/plugin-basics/best-practices/
// WordPress coding standards (PHP):
// https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/
//------------------------------------------------------------------------
// AI search based on OpenAI Assistants and FileSearch.
// Assistants docs: https://platform.openai.com/docs/assistants/overview
// File search docs: https://platform.openai.com/docs/assistants/tools/file-search
//------------------------------------------------------------------------

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

// Defile location constants
define( 'VAPPV_TTW_PLUGIN_FILE', __FILE__ );
define( 'VAPPV_TTW_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'VAPPV_TTW_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'VAPPV_TTW_PLUGINS_URL', plugins_url() );
define( 'VAPPV_TTW_UPLOADS_DIR', wp_upload_dir() );

//------------------------------------------------------------------------
// Plugin translation (localization to different languages):
// EasyPo for creating .pot file | http://www.eazypo.ca/
// PoEdit for creating .po / .mo files | https://poedit.net/

add_action( 'plugins_loaded', function(){
	load_plugin_textdomain( 'talk-to-website', false, VAPPV_TTW_PLUGIN_DIR . '/languages' );
} );

//------------------------------------------------------------------------

require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-chat-dialogues.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-chat-messages.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-common.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-core.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-installer.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-openai-api-connector.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-statistics.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-training.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-ui-data-paginator.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/class-vappv-ttw-settings-storage.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'includes/vappv-ttw-exceptions.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'public/vappv-ttw-public.php';
require_once VAPPV_TTW_PLUGIN_DIR . 'admin/vappv-ttw-admin.php';

/* ---------------------------------------------------------------------- */
/*                               Public part                              */
/* ---------------------------------------------------------------------- */

if ( ! function_exists( 'vappv_ttw_enqueue_public_scripts' ) ) {

	/**
	 * Add public CSS and JS (publicly-available pages, every page of the website)
	 */
	function vappv_ttw_enqueue_public_scripts() {
		//Add scripts to the public page
		wp_enqueue_script( 'vappv-ttw-public-js', VAPPV_TTW_PLUGIN_URL . 'public/js/vappv.ttw.public.js', array( 'jquery' ), '1.7', true );
		wp_localize_script( 'vappv-ttw-public-js', 'vappv_ttw_public_js', array(
			'pluginsUrl' => VAPPV_TTW_PLUGINS_URL,
			'ajaxurl'    => admin_url( 'admin-ajax.php' ),
			'nonce'      => wp_create_nonce( 'vappv-ttw-public-js-ajax-nonce' )
		) );

		//Add styles to the public page
		wp_enqueue_style( 'vappv-ttw-public-css', VAPPV_TTW_PLUGIN_URL . 'public/css/vappv.ttw.public.css', array(), '1.7' );
	}

	add_action( 'wp_enqueue_scripts', 'vappv_ttw_enqueue_public_scripts' );
}

if ( ! function_exists( 'vappv_ttw_add_ws_public_footer' ) ) {

	/**
	 * Draw plugin public section to the footer (using wp_footer function)
	 */
	function vappv_ttw_add_ws_public_footer() {
		vappv_ttw_draw_public_section();
	}

	add_action( 'wp_footer', 'vappv_ttw_add_ws_public_footer' );
}

if ( ! function_exists( 'vappv_ttw_send_message_as_user' ) ) {

	/**
	 * Send message to the Ai chat as user
	 */
	function vappv_ttw_send_message_as_user() {

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-public-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['user_name'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['user_name'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'user_name'
				)
			) );
			exit;
		}
		
		if ( ! isset( $_POST['user_email'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'user_email'
				)
			) );
			exit;
		}
		
		if (
			! isset( $_POST['user_guid'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['user_guid'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'user_guid'
				)
			) );
			exit;
		}
		
		if (
			! isset( $_POST['message_guid'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['message_guid'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'message_guid'
				)
			) );
			exit;
		}
		
		if (
			! isset( $_POST['message_text'] ) ||
			'' == trim( sanitize_textarea_field( wp_unslash( $_POST['message_text'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'message_text'
				)
			) );
			exit;
		}

		//Sanitize text
		$user_name    = sanitize_text_field( wp_unslash( $_POST['user_name'] ) );
		$user_email   = sanitize_text_field( wp_unslash( $_POST['user_email'] ) );
		$user_guid    = sanitize_text_field( wp_unslash( $_POST['user_guid'] ) );
		$message_guid = sanitize_text_field( wp_unslash( $_POST['message_guid'] ) );
		$message_text = sanitize_textarea_field( wp_unslash( $_POST['message_text'] ) );

		//Replace tags and protect XSS
		$user_name    = wp_strip_all_tags( $user_name );
		$user_email   = wp_strip_all_tags( $user_email );
		$user_guid    = wp_strip_all_tags( $user_guid );
		$message_guid = wp_strip_all_tags( $message_guid );
		$message_text = wp_strip_all_tags( $message_text );

		//Trim fields
		$user_name 		= trim( $user_name );
		$user_email 	= trim( $user_email );
		$user_guid 		= trim( $user_guid );
		$message_guid 	= trim( $message_guid );
		$message_text 	= trim( $message_text );

		echo wp_json_encode( VAPPV_TTW_Core::send_message_to_ai_as_user( $user_name, $user_email, $user_guid, $message_guid, $message_text ) );
		exit;

	}

	add_action( 'wp_ajax_vappv_ttw_send_message_as_user', 'vappv_ttw_send_message_as_user' );
	add_action( 'wp_ajax_nopriv_vappv_ttw_send_message_as_user', 'vappv_ttw_send_message_as_user' );
}

if ( ! function_exists( 'vappv_ttw_try_get_message_responses_from_ai_as_user' ) ) {

	/**
	 * Try to extract responses from AI (in case of unfinished threads)
	 */
	function vappv_ttw_try_get_message_responses_from_ai_as_user() {

		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-public-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['user_guid'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['user_guid'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'user_guid'
				)
			) );
			exit;
		}

		//Sanitize text field and strip all tags
		$user_guid = sanitize_text_field( wp_unslash( $_POST['user_guid'] ) );
		$user_guid = wp_strip_all_tags( $user_guid );
		$user_guid = trim( $user_guid );

		echo wp_json_encode( VAPPV_TTW_Core::try_extract_message_responses_from_ai_as_user( $user_guid ) );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_try_get_message_responses_from_ai_as_user', 'vappv_ttw_try_get_message_responses_from_ai_as_user' );
	add_action( 'wp_ajax_nopriv_vappv_ttw_try_get_message_responses_from_ai_as_user', 'vappv_ttw_try_get_message_responses_from_ai_as_user' );
}

if ( ! function_exists( 'vappv_ttw_list_user_messages' ) ) {

	/**
	 * List messages for specified user
	 */
	function vappv_ttw_list_user_messages() {

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-public-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['user_guid'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['user_guid'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
						esc_html(
							/* translators: 1. parameter name */
							__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
						),
						'user_guid'
					)
				) );
			exit;
		}
		
		if (
			! isset( $_POST['data_direction'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['data_direction'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'data_direction'
				)
			) );
			exit;
		}
		
		if ( ! isset( $_POST['last_known_id'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'last_known_id'
				)
			) );
			exit;
		}
		
		if (
			! isset( $_POST['data_limit'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'data_limit'
				)
			) );
			exit;
		}

		//Sanitize fields
		$user_guid      = sanitize_text_field( wp_unslash( $_POST['user_guid'] ) );
		$data_direction = sanitize_text_field( wp_unslash( $_POST['data_direction'] ) );
		$last_known_id  = intval( $_POST['last_known_id'] );
		$data_limit     = intval( $_POST['data_limit'] );

		//Strip all tags
		$user_guid      = wp_strip_all_tags( $user_guid );
		$data_direction = wp_strip_all_tags( $data_direction );

		//Trim fields
		$user_guid 		= trim( $user_guid );
		$data_direction = trim( $data_direction );

		//Handle last known ID
		if ( 0 == $last_known_id ) {
			$last_known_id = - 1;
		}
		if ( $data_limit < 0 ) {
			$data_limit = 25;
		}

		echo wp_json_encode( VAPPV_TTW_Core::list_all_chat_messages_as_user( $user_guid, $data_direction, $last_known_id, $data_limit ) );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_list_user_messages', 'vappv_ttw_list_user_messages' );
	add_action( 'wp_ajax_nopriv_vappv_ttw_list_user_messages', 'vappv_ttw_list_user_messages' );
}

if ( ! function_exists( 'vappv_ttw_set_urls_followed_into_message' ) ) {

	/**
	 * Mark URL(s) as followed into specified message
	 */
	function vappv_ttw_set_urls_followed_into_message() {

		if ( isset( $_POST['nonce'] ) ) {
			if ( ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-public-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['message_id'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['message_id'] ) ) )
		) {
			echo wp_json_encode( array(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'message_id'
				)
			) );
			exit;
		}
		
		if (
			! isset( $_POST['message_guid'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['message_guid'] ) ) )
		) {
			echo wp_json_encode( array(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'message_guid'
				)
			) );
			exit;
		}
		
		if (
			! isset( $_POST['followed_url'] ) ||
			'' == trim( sanitize_url( wp_unslash( $_POST['followed_url'] ), array( 'http', 'https' ) ) )
		) {
			echo wp_json_encode( array(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'followed_url'
				)
			) );
			exit;
		}

		//Sanitize text field
		$message_id   = intval( $_POST['message_id'] );
		$message_guid = sanitize_text_field( wp_unslash( $_POST['message_guid'] ) );
		$followed_url = sanitize_url( wp_unslash( $_POST['followed_url'] ), array( 'http', 'https' ) );

		//Strip all tags
		$message_guid = wp_strip_all_tags( $message_guid );
		$followed_url = wp_strip_all_tags( $followed_url );

		//Trim fields
		$message_guid = trim( $message_guid );
		$followed_url = trim( $followed_url );

		echo wp_json_encode( VAPPV_TTW_Core::set_urls_followed_into_message( $message_id, $message_guid, $followed_url ) );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_set_urls_followed_into_message', 'vappv_ttw_set_urls_followed_into_message' );
	add_action( 'wp_ajax_nopriv_vappv_ttw_set_urls_followed_into_message', 'vappv_ttw_set_urls_followed_into_message' );
}

/* ---------------------------------------------------------------------- */
/*                                Admin part                              */
/* ---------------------------------------------------------------------- */

if ( ! function_exists( 'vappv_ttw_enqueue_admin_scripts' ) ) {

	/**
	 * Add admin CSS and JS (plugin inner pages - admin access / control panel only)
	 */
	function vappv_ttw_enqueue_admin_scripts() {
		wp_enqueue_script( 'vappv-ttw-admin-js', VAPPV_TTW_PLUGIN_URL . 'admin/js/vappv.ttw.admin.js', array( 'jquery' ), '1.7' );
		wp_localize_script( 'vappv-ttw-admin-js', 'vappv_ttw_admin_js', array(
			'pluginsUrl' => VAPPV_TTW_PLUGINS_URL,
			'ajaxurl'    => admin_url( 'admin-ajax.php' ),
			'nonce'      => wp_create_nonce( 'vappv-ttw-admin-js-ajax-nonce' )
		) );

		wp_enqueue_style( 'vappv-ttw-admin-css', VAPPV_TTW_PLUGIN_URL . 'admin/css/vappv.ttw.admin.css', array(), '1.7' );
	}

	add_action( 'admin_enqueue_scripts', 'vappv_ttw_enqueue_admin_scripts' );
}

if ( ! function_exists( 'vappv_ttw_admin_bar_menu' ) ) {

	/**
	 * Add menu bar icon to the admin section
	 */
	function vappv_ttw_admin_bar_menu() {

		add_menu_page(
			'Talk To Website - Settings',
			'Talk To Website',
			'manage_options',
			'talk-to-website-settings',
			'vappv_ttw_build_admin_page',
			'data:image/svg+xml;base64,' . base64_encode( '<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"><title>ai</title><g id="Layer_2" data-name="Layer 2"><g id="invisible_box" data-name="invisible box"><rect width="48" height="48" fill="none"/></g><g id="Q3_icons" data-name="Q3 icons"><g><path d="M45.6,18.7,41,14.9V7.5a1,1,0,0,0-.6-.9L30.5,2.1h-.4l-.6.2L24,5.9,18.5,2.2,17.9,2h-.4L7.6,6.6a1,1,0,0,0-.6.9v7.4L2.4,18.7a.8.8,0,0,0-.4.8v9H2a.8.8,0,0,0,.4.8L7,33.1v7.4a1,1,0,0,0,.6.9l9.9,4.5h.4l.6-.2L24,42.1l5.5,3.7.6.2h.4l9.9-4.5a1,1,0,0,0,.6-.9V33.1l4.6-3.8a.8.8,0,0,0,.4-.7V19.4h0A.8.8,0,0,0,45.6,18.7Zm-5.1,6.8H42v1.6l-3.5,2.8-.4.3-.4-.2a1.4,1.4,0,0,0-2,.7,1.5,1.5,0,0,0,.6,2l.7.3h0v5.4l-6.6,3.1-4.2-2.8-.7-.5V25.5H27a1.5,1.5,0,0,0,0-3H25.5V9.7l.7-.5,4.2-2.8L37,9.5v5.4h0l-.7.3a1.5,1.5,0,0,0-.6,2,1.4,1.4,0,0,0,1.3.9l.7-.2.4-.2.4.3L42,20.9v1.6H40.5a1.5,1.5,0,0,0,0,3ZM21,25.5h1.5V38.3l-.7.5-4.2,2.8L11,38.5V33.1h0l.7-.3a1.5,1.5,0,0,0,.6-2,1.4,1.4,0,0,0-2-.7l-.4.2-.4-.3L6,27.1V25.5H7.5a1.5,1.5,0,0,0,0-3H6V20.9l3.5-2.8.4-.3.4.2.7.2a1.4,1.4,0,0,0,1.3-.9,1.5,1.5,0,0,0-.6-2L11,15h0V9.5l6.6-3.1,4.2,2.8.7.5V22.5H21a1.5,1.5,0,0,0,0,3Z"/><path d="M13.9,9.9a1.8,1.8,0,0,0,0,2.2l2.6,2.5v2.8l-4,4v5.2l4,4v2.8l-2.6,2.5a1.8,1.8,0,0,0,0,2.2,1.5,1.5,0,0,0,1.1.4,1.5,1.5,0,0,0,1.1-.4l3.4-3.5V29.4l-4-4V22.6l4-4V13.4L16.1,9.9A1.8,1.8,0,0,0,13.9,9.9Z"/><path d="M31.5,14.6l2.6-2.5a1.8,1.8,0,0,0,0-2.2,1.8,1.8,0,0,0-2.2,0l-3.4,3.5v5.2l4,4v2.8l-4,4v5.2l3.4,3.5a1.7,1.7,0,0,0,2.2,0,1.8,1.8,0,0,0,0-2.2l-2.6-2.5V30.6l4-4V21.4l-4-4Z"/></g></g></g></svg>' )
		);

		add_submenu_page(
			'talk-to-website-settings',
			esc_html(
				__( 'Talk To Website - Settings', 'talk-to-website' )
			),
			esc_html(
				__( 'Settings + Chat', 'talk-to-website' )
			),
			'manage_options',
			'talk-to-website-settings',
			'vappv_ttw_build_admin_page'
		);

	}

	add_action( 'admin_menu', 'vappv_ttw_admin_bar_menu' );
}

if ( ! function_exists( 'vappv_ttw_build_admin_page' ) ) {

	/**
	 * Display admin page
	 */
	function vappv_ttw_build_admin_page() {
		vappv_ttw_draw_admin_section();
	}

}

if ( ! function_exists( 'vappv_ttw_save_openai_api_key' ) ) {

	/**
	 * Save ChatGPT API key
	 */
	function vappv_ttw_save_openai_api_key() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === current_user_can( 'manage_options' ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_CANNOT_MANAGE_OPTIONS',
				esc_html( __( 'You cannot edit plugin settings based on account settings. Please contact the website administrator, or change the permissions of the current account yourself.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['openai_api_key'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['openai_api_key'] ) ) )
		) {
			echo wp_json_encode( array(
			'AJAXCallResults' => 'ERROR',
			'ARG_IS_MISSED',
			sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'openai_api_key'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['openai_api_address'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['openai_api_address'] ) ) )
		) {
			echo wp_json_encode( array(
			'AJAXCallResults' => 'ERROR',
			'ARG_IS_MISSED',
			sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'openai_api_address'
				)
			) );
			exit;
		}

		//Sanitize parameters
		//Sanitize API address
		$openai_api_address = sanitize_url( wp_unslash( $_POST['openai_api_address'] ) );
		$openai_api_address = wp_strip_all_tags( $openai_api_address );

		//Remove last trailing slash from the API address
		$openai_api_address = trim( $openai_api_address );
		$openai_api_address = trim( $openai_api_address, '/' );

		//Sanitize API key
		$openai_api_key = sanitize_text_field( wp_unslash( $_POST['openai_api_key'] ) );
		$openai_api_key = wp_strip_all_tags( $openai_api_key );
		$openai_api_key = trim( $openai_api_key );

		echo wp_json_encode( VAPPV_TTW_Core::update_api_key( $openai_api_address, $openai_api_key ) );
		exit;

	}

	add_action( 'wp_ajax_vappv_ttw_save_openai_api_key', 'vappv_ttw_save_openai_api_key' );
}

if ( ! function_exists( 'vappv_ttw_save_all_settings' ) ) {

	/**
	 * Save plugin settings
	 * @throws Exception
	 */
	function vappv_ttw_save_all_settings() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === current_user_can( 'manage_options' ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_CANNOT_MANAGE_OPTIONS',
				esc_html( __( 'You cannot edit plugin settings based on account settings. Please contact the website administrator, or change the permissions of the current account yourself.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_chatgpt_model'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['settings_chatgpt_model'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_chatgpt_model'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_chatgpt_temperature'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_chatgpt_temperature'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_max_characters_per_user_question'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_max_characters_per_user_question'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_max_words_to_answer'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_max_words_to_answer'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_website_contacts_page'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_website_contacts_page'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_any_direct_instructions'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_any_direct_instructions'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_primary_language'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['settings_primary_language'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_primary_language'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_humor_level'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_humor_level'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_try_intercept_leaving_users'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_try_intercept_leaving_users'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_chat_bot_name'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['settings_chat_bot_name'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_chat_bot_name'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_robot_messages_post_scriptum'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_robot_messages_post_scriptum'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_dialogue_lifetime_minutes'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_dialogue_lifetime_minutes'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_is_chatbot_displayed_right_now'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['settings_is_chatbot_displayed_right_now'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_is_chatbot_displayed_right_now'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['settings_chat_bubble_image_url'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['settings_chat_bubble_image_url'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_chat_bubble_image_url'
				)
			) );
			exit;
		}
		if ( ! isset( $_POST['settings_website_contacts_company_email'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_website_contacts_company_email'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_website_contacts_company_phone'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_website_contacts_company_phone'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_website_contacts_company_address'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_website_contacts_company_address'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_max_input_words_per_day_by_all_users'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_max_input_words_per_day_by_all_users'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_max_input_characters_per_day_by_all_users'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_max_input_characters_per_day_by_all_users'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_max_output_characters_per_day_by_ai'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_max_output_characters_per_day_by_ai'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_max_output_tokens_per_day_by_ai'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_max_output_tokens_per_day_by_ai'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_sugar_limits_summary'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_sugar_limits_summary'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_prohibited_topics_and_words'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_prohibited_topics_and_words'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_plugin_appearance_custom_css'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_plugin_appearance_custom_css'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_show_promo_popup_after_n_seconds'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_show_promo_popup_after_n_seconds'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_show_promo_popup_time_frequency_n_minutes'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_show_promo_popup_time_frequency_n_minutes'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_dialogue_lifetime_max_messages'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_dialogue_lifetime_max_messages'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_welcome_message_html'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_welcome_message_html'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_store_db_on_deletion'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_store_db_on_deletion'
				)
			) );
			exit;
		}

		if ( ! isset ( $_POST['settings_show_powered_by_ttw_public_label'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_show_powered_by_ttw_public_label'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_chat_restricted_pages_urlmasks'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_chat_restricted_pages_urlmasks'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_openai_api_address'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_openai_api_address'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_ai_character'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_ai_character'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_chat_bubble_ui_position'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
					/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_chat_bubble_ui_position'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['settings_chat_bubble_ui_margin'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
					/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'settings_chat_bubble_ui_margin'
				)
			) );
			exit;
		}

		//Sanitize data
		$settings_chatgpt_model                             = sanitize_text_field( wp_unslash( $_POST['settings_chatgpt_model'] ) );
		$settings_chatgpt_temperature                       = floatval( $_POST['settings_chatgpt_temperature'] );
		$settings_max_characters_per_user_question          = intval( $_POST['settings_max_characters_per_user_question'] );
		$settings_max_words_to_answer                       = intval( $_POST['settings_max_words_to_answer'] );
		$settings_website_contacts_page                     = sanitize_text_field( wp_unslash( $_POST['settings_website_contacts_page'] ) );
		$settings_any_direct_instructions                   = sanitize_textarea_field( wp_unslash( $_POST['settings_any_direct_instructions'] ) );
		$settings_primary_language                          = sanitize_text_field( wp_unslash( $_POST['settings_primary_language'] ) );
		$settings_humor_level                               = intval( $_POST['settings_humor_level'] );
		$settings_try_intercept_leaving_users               = intval( $_POST['settings_try_intercept_leaving_users'] );
		$settings_chat_bot_name                             = sanitize_text_field( wp_unslash( $_POST['settings_chat_bot_name'] ) );
		$settings_robot_messages_post_scriptum              = sanitize_textarea_field( wp_unslash( $_POST['settings_robot_messages_post_scriptum'] ) );
		$settings_dialogue_lifetime_minutes                 = intval( $_POST['settings_dialogue_lifetime_minutes'] );
		$settings_is_chatbot_displayed_right_now            = intval( $_POST['settings_is_chatbot_displayed_right_now'] );
		$settings_chat_bubble_image_url                     = sanitize_text_field( wp_unslash( $_POST['settings_chat_bubble_image_url'] ) );
		$settings_website_contacts_company_email            = sanitize_text_field( wp_unslash( $_POST['settings_website_contacts_company_email'] ) );
		$settings_website_contacts_company_phone            = sanitize_text_field( wp_unslash( $_POST['settings_website_contacts_company_phone'] ) );
		$settings_website_contacts_company_address          = sanitize_text_field( wp_unslash( $_POST['settings_website_contacts_company_address'] ) );
		$settings_max_input_words_per_day_by_all_users      = intval( $_POST['settings_max_input_words_per_day_by_all_users'] );
		$settings_max_input_characters_per_day_by_all_users = intval( $_POST['settings_max_input_characters_per_day_by_all_users'] );
		$settings_max_output_characters_per_day_by_ai       = intval( $_POST['settings_max_output_characters_per_day_by_ai'] );
		$settings_max_output_tokens_per_day_by_ai           = intval( $_POST['settings_max_output_tokens_per_day_by_ai'] );
		$settings_sugar_limits_summary                      = intval( $_POST['settings_sugar_limits_summary'] );
		$settings_prohibited_topics_and_words               = sanitize_textarea_field( wp_unslash( $_POST['settings_prohibited_topics_and_words'] ) );
		$settings_plugin_appearance_custom_css              = sanitize_textarea_field( wp_unslash( $_POST['settings_plugin_appearance_custom_css'] ) );
		$settings_show_promo_popup_after_n_seconds          = intval( $_POST['settings_show_promo_popup_after_n_seconds'] );
		$settings_show_promo_popup_time_frequency_n_minutes = intval( $_POST['settings_show_promo_popup_time_frequency_n_minutes'] );
		$settings_dialogue_lifetime_max_messages            = intval( $_POST['settings_dialogue_lifetime_max_messages'] );
		$settings_welcome_message_html                      = sanitize_textarea_field( wp_unslash( $_POST['settings_welcome_message_html'] ) );
		$settings_store_db_on_deletion						= sanitize_text_field( wp_unslash( $_POST['settings_store_db_on_deletion'] ) );
		$settings_show_powered_by_ttw_public_label			= sanitize_text_field( wp_unslash( $_POST['settings_show_powered_by_ttw_public_label'] ) );
		$settings_chat_restricted_pages_urlmasks			= sanitize_textarea_field( wp_unslash( $_POST['settings_chat_restricted_pages_urlmasks'] ) );
		$settings_openai_api_address						= sanitize_url( wp_unslash( $_POST['settings_openai_api_address'] ) );
		$settings_chat_bubble_ui_position					= sanitize_text_field( wp_unslash( $_POST['settings_chat_bubble_ui_position'] ) );
		$settings_chat_bubble_ui_margin						= intval( $_POST['settings_chat_bubble_ui_margin'] );
		$settings_ai_character 								= sanitize_text_field( wp_unslash( $_POST['settings_ai_character'] ) );

		//Remove tags
		$settings_chatgpt_model 							= wp_strip_all_tags( $settings_chatgpt_model );
		$settings_website_contacts_page 					= wp_strip_all_tags( $settings_website_contacts_page );
		$settings_any_direct_instructions 					= wp_strip_all_tags( $settings_any_direct_instructions );
		$settings_primary_language 							= wp_strip_all_tags( $settings_primary_language );
		$settings_chat_bot_name 							= wp_strip_all_tags( $settings_chat_bot_name );
		$settings_chat_bubble_image_url 					= wp_strip_all_tags( $settings_chat_bubble_image_url );
		$settings_website_contacts_company_email 			= wp_strip_all_tags( $settings_website_contacts_company_email );
		$settings_website_contacts_company_phone 			= wp_strip_all_tags( $settings_website_contacts_company_phone );
		$settings_website_contacts_company_address 			= wp_strip_all_tags( $settings_website_contacts_company_address );
		$settings_prohibited_topics_and_words 				= wp_strip_all_tags( $settings_prohibited_topics_and_words );
		$settings_plugin_appearance_custom_css 				= wp_strip_all_tags( $settings_plugin_appearance_custom_css );
		$settings_store_db_on_deletion 						= wp_strip_all_tags( $settings_store_db_on_deletion );
		$settings_show_powered_by_ttw_public_label 			= wp_strip_all_tags( $settings_show_powered_by_ttw_public_label );
		$settings_chat_restricted_pages_urlmasks 			= wp_strip_all_tags( $settings_chat_restricted_pages_urlmasks );
		$settings_openai_api_address 						= wp_strip_all_tags( $settings_openai_api_address );
		$settings_chat_bubble_ui_position					= wp_strip_all_tags( $settings_chat_bubble_ui_position );
		$settings_ai_character								= wp_strip_all_tags( $settings_ai_character );

		//Trim values
		$settings_chatgpt_model 							= trim( $settings_chatgpt_model );
		$settings_website_contacts_page 					= trim( $settings_website_contacts_page );
		$settings_any_direct_instructions 					= trim( $settings_any_direct_instructions );
		$settings_primary_language 							= trim( $settings_primary_language );
		$settings_chat_bot_name 							= trim( $settings_chat_bot_name );
		$settings_chat_bubble_image_url 					= trim( $settings_chat_bubble_image_url );
		$settings_website_contacts_company_email 			= trim( $settings_website_contacts_company_email );
		$settings_website_contacts_company_phone 			= trim( $settings_website_contacts_company_phone );
		$settings_website_contacts_company_address 			= trim( $settings_website_contacts_company_address );
		$settings_prohibited_topics_and_words 				= trim( $settings_prohibited_topics_and_words );
		$settings_plugin_appearance_custom_css 				= trim( $settings_plugin_appearance_custom_css );
		$settings_store_db_on_deletion 						= trim( $settings_store_db_on_deletion );
		$settings_show_powered_by_ttw_public_label 			= trim( $settings_show_powered_by_ttw_public_label );
		$settings_chat_restricted_pages_urlmasks 			= trim( $settings_chat_restricted_pages_urlmasks );
		$settings_openai_api_address 						= trim( $settings_openai_api_address );
		$settings_chat_bubble_ui_position					= trim( $settings_chat_bubble_ui_position );
		$settings_ai_character								= trim( $settings_ai_character );

		echo wp_json_encode( VAPPV_TTW_Core::update_plugin_settings(
			$settings_chatgpt_model,
			$settings_chatgpt_temperature,
			$settings_max_characters_per_user_question,
			$settings_max_words_to_answer,
			$settings_website_contacts_page,
			$settings_any_direct_instructions,
			$settings_primary_language,
			$settings_humor_level,
			$settings_try_intercept_leaving_users,
			$settings_chat_bot_name,
			$settings_robot_messages_post_scriptum,
			$settings_dialogue_lifetime_minutes,
			$settings_is_chatbot_displayed_right_now,
			$settings_chat_bubble_image_url,
			$settings_website_contacts_company_email,
			$settings_website_contacts_company_phone,
			$settings_website_contacts_company_address,
			$settings_max_input_words_per_day_by_all_users,
			$settings_max_input_characters_per_day_by_all_users,
			$settings_max_output_characters_per_day_by_ai,
			$settings_max_output_tokens_per_day_by_ai,
			$settings_sugar_limits_summary,
			$settings_prohibited_topics_and_words,
			$settings_plugin_appearance_custom_css,
			$settings_show_promo_popup_after_n_seconds,
			$settings_show_promo_popup_time_frequency_n_minutes,
			$settings_dialogue_lifetime_max_messages,
			$settings_welcome_message_html,
			$settings_store_db_on_deletion,
			$settings_show_powered_by_ttw_public_label,
			$settings_chat_restricted_pages_urlmasks,
			$settings_openai_api_address,
			$settings_chat_bubble_ui_position,
			$settings_chat_bubble_ui_margin,
			$settings_ai_character
		) );
		exit;

	}

	add_action( 'wp_ajax_vappv_ttw_save_all_settings', 'vappv_ttw_save_all_settings' );
}

if ( ! function_exists( 'vappv_ttw_get_training_items' ) ) {

	/**
	 * Get training section content (posts + according information)
	 */
	function vappv_ttw_get_training_items() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		echo wp_json_encode( VAPPV_TTW_Core::get_training_items() );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_get_training_items', 'vappv_ttw_get_training_items' );
}

if ( ! function_exists( 'vappv_ttw_train_ai' ) ) {

	/**
	 * Train AI on checked materials
	 */
	function vappv_ttw_train_ai() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === current_user_can( 'manage_options' ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_CANNOT_MANAGE_OPTIONS',
				esc_html( __( 'You cannot edit plugin settings based on account settings. Please contact the website administrator, or change the permissions of the current account yourself.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['materials_to_train'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'materials_to_train'
				)
			) );
			exit;
		}

		// --------------------------------------------------
		// Get json as a raw string. Then decode and sanitize

		$materials_to_train = $_POST['materials_to_train'];
		$materials_to_train_sanitized = array();

		try {

			$selected_materials = preg_replace( '/[\x00-\x1F\x80-\xFF]/', '', $materials_to_train );
			$selected_materials = str_replace( '\\', '', $selected_materials );
			$materials_list_decoded = json_decode( $selected_materials, true );

			if ( is_array( $materials_list_decoded ) && count( $materials_list_decoded ) > 0 ) {

				foreach ( $materials_list_decoded as $row_nr => $row_values ) {
					array_push( $materials_to_train_sanitized, array(
						'material_id' => intval( $row_values['material_id'] ),
						'material_type' => sanitize_text_field( wp_unslash( $row_values['material_type'] ) )
					) );
				}

			}
			else {

				// Executed only in PHP 7, will not match in PHP 5
				VAPPV_TTW_Core::add_log_entry(
					'error',
					sprintf(
						/* translators: 1. error details, extracted from PHP throwable object */
						__( 'Failed to decode materials from a JSON object that were claimed for AI retraining. Training array is empty.', 'talk-to-website' )
					)
				);
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'MATERIALS_LIST_DECODING_ERROR',
					esc_html(
						/* translators: plugin exception = failed to decode materials from a JSON object */
						__( 'Failed to decode materials from a JSON object that were claimed for AI retraining. Training array is empty.', 'talk-to-website' )
					)
				) );
				exit;

			}

		} catch ( Throwable $t ) {

			// Executed only in PHP 7, will not match in PHP 5
			VAPPV_TTW_Core::add_log_entry(
				'error',
				sprintf(
				/* translators: 1. error details, extracted from PHP throwable object */
					__( 'Failed to decode materials from a JSON object that were claimed for AI retraining. Error details = %1$s.', 'talk-to-website' ),
					esc_html( $t->getMessage() )
				)
			);
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'MATERIALS_LIST_DECODING_ERROR',
				esc_html(
				/* translators: plugin exception = failed to decode materials from a JSON object */
					__( 'Failed to decode materials from a JSON object that were claimed for AI retraining.', 'talk-to-website' )
				)
			) );
			exit;

		}

		// ~Get json as a raw string. Then decode and sanitize
		// --------------------------------------------------

		echo wp_json_encode( VAPPV_TTW_Core::train_ai( $materials_to_train_sanitized ) );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_train_ai', 'vappv_ttw_train_ai' );
}

if ( ! function_exists( 'vappv_ttw_send_message_as_admin' ) ) {

	/**
	 * Send message to the Ai chat as an admin
	 */
	function vappv_ttw_send_message_as_admin() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['message_guid'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['message_guid'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'message_guid'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['message_text'] ) ||
			'' == trim( sanitize_textarea_field( wp_unslash( $_POST['message_text'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'message_text'
				)
			) );
			exit;
		}

		//Sanitize fields
		$message_guid = sanitize_text_field( wp_unslash( $_POST['message_guid'] ) );
		$message_text = sanitize_textarea_field( wp_unslash( $_POST['message_text'] ) );

		//Strip tags
		$message_guid = wp_strip_all_tags( $message_guid );
		$message_text = wp_strip_all_tags( $message_text );

		//Trim fields
		$message_guid = trim( $message_guid );
		$message_text = trim( $message_text );

		echo wp_json_encode( VAPPV_TTW_Core::send_message_to_ai_as_admin( $message_guid, $message_text ) );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_send_message_as_admin', 'vappv_ttw_send_message_as_admin' );
}

if ( ! function_exists( 'vappv_ttw_try_get_message_responses_from_ai_as_admin' ) ) {

	/**
	 * Try to extract responses from AI (in case of unfinished threads)
	 */
	function vappv_ttw_try_get_message_responses_from_ai_as_admin() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		echo wp_json_encode( VAPPV_TTW_Core::try_extract_message_responses_from_ai_as_admin() );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_try_get_message_responses_from_ai_as_admin', 'vappv_ttw_try_get_message_responses_from_ai_as_admin' );
}

if ( ! function_exists( 'vappv_ttw_list_admin_messages' ) ) {

	/**
	 * Get messages into 'Testing' tab
	 */
	function vappv_ttw_list_admin_messages() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['data_direction'] ) ||
			'' == trim( sanitize_text_field( wp_unslash( $_POST['data_direction'] ) ) )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'data_direction'
				)
			) );
			exit;
		}

		if ( ! isset( $_POST['last_known_id'] ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'last_known_id'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['data_limit'] ) ||
			is_null( $_POST['data_limit'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'data_limit'
				)
			) );
			exit;
		}

		$data_direction = sanitize_text_field( wp_unslash( $_POST['data_direction'] ) );
		$data_direction = wp_strip_all_tags( $data_direction );
		$data_direction = trim( $data_direction );

		$last_known_id = intval( $_POST['last_known_id'] );
		$data_limit    = intval( $_POST['data_limit'] );

		//Handle last known ID
		if ( 0 == $last_known_id ) {
			$last_known_id = - 1;
		}

		echo wp_json_encode( VAPPV_TTW_Core::list_testing_messages_as_admin( $data_direction, $last_known_id, $data_limit ) );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_list_admin_messages', 'vappv_ttw_list_admin_messages' );
}

if ( ! function_exists( 'vappv_ttw_list_dialogues' ) ) {

	/**
	 * Get dialogues list into 'History' tab
	 */
	function vappv_ttw_list_dialogues() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['data_offset'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'data_offset'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['data_limit'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'data_limit'
				)
			) );
			exit;
		}

		$data_offset = intval( $_POST['data_offset'] );
		$data_limit  = intval( $_POST['data_limit'] );

		echo wp_json_encode( VAPPV_TTW_Core::list_dialogues_as_admin( $data_offset, $data_limit ) );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_list_dialogues', 'vappv_ttw_list_dialogues' );
}

if ( ! function_exists( 'vappv_ttw_get_logs' ) ) {

	/**
	 * Get logs content
	 */
	function vappv_ttw_get_logs() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		if (
			! isset( $_POST['offset'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'offset'
				)
			) );
			exit;
		}

		if (
			! isset( $_POST['limit'] )
		) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ARG_IS_MISSED',
				sprintf(
					esc_html(
						/* translators: 1. parameter name */
						__( 'Parameter %1$s is missed or empty', 'talk-to-website' )
					),
					'limit'
				)
			) );
			exit;
		}

		$offset = intval( $_POST['offset'] );
		$limit  = intval( $_POST['limit'] );

		echo wp_json_encode( VAPPV_TTW_Core::get_log_entries( $offset, $limit ) );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_get_logs', 'vappv_ttw_get_logs' );
}

if ( ! function_exists( 'vappv_ttw_qa_enable_plugin' ) ) {

	/**
	 * Enable plugin from notification bar
	 */
	function vappv_ttw_qa_enable_plugin() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === current_user_can( 'manage_options' ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_CANNOT_MANAGE_OPTIONS',
				esc_html( __( 'You cannot edit plugin settings based on account settings. Please contact the website administrator, or change the permissions of the current account yourself.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		echo wp_json_encode( VAPPV_TTW_Core::quick_action_enable_plugin() );
		exit;

	}

	add_action( 'wp_ajax_vappv_ttw_qa_enable_plugin', 'vappv_ttw_qa_enable_plugin' );
}

if ( ! function_exists( 'vappv_ttw_qa_disable_plugin' ) ) {

	/**
	* Disable plugin from notification bar
	*/
	function vappv_ttw_qa_disable_plugin() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === current_user_can( 'manage_options' ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_CANNOT_MANAGE_OPTIONS',
				esc_html( __( 'You cannot edit plugin settings based on account settings. Please contact the website administrator, or change the permissions of the current account yourself.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		echo wp_json_encode( VAPPV_TTW_Core::quick_action_disable_plugin() );
		exit;

	}

	add_action( 'wp_ajax_vappv_ttw_qa_disable_plugin', 'vappv_ttw_qa_disable_plugin' );
}

if ( ! function_exists( 'vappv_ttw_list_available_gpt_models' ) ) {

	/**
	 * Get available AI models
	 */
	function vappv_ttw_list_available_gpt_models() {

		//Checking for security issues and specified permissions
		if ( false === is_admin() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_REQUEST_NOT_FROM_ADMIN_GUI',
				esc_html( __( 'A request to the plugin was sent from a section not related to the administration page. The operation is rejected.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === is_user_logged_in() ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_NOT_LOGGED',
				esc_html( __( 'You are not logged in and cannot send requests to the plugin.', 'talk-to-website' ) )
			) );
			exit;
		}
		if ( false === current_user_can( 'manage_options' ) ) {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'ERROR_USER_CANNOT_MANAGE_OPTIONS',
				esc_html( __( 'You cannot edit plugin settings based on account settings. Please contact the website administrator, or change the permissions of the current account yourself.', 'talk-to-website' ) )
			) );
			exit;
		}
		//~

		// Check for nonce security
		if ( isset( $_POST['nonce'] ) ) {
			if ( !wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'vappv-ttw-admin-js-ajax-nonce' ) ) {
				echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
					'WRONG_NONCE_PARAM',
					esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
				) );
				exit;
			}
		}
		else {
			echo wp_json_encode( VAPPV_TTW_Core::ajax_pack_error(
				'WRONG_NONCE_PARAM',
				esc_html( __( 'Wrong nonce parameter', 'talk-to-website' ) )
			) );
			exit;
		}

		echo wp_json_encode( VAPPV_TTW_Core::list_available_gpt_models() );
		exit;
	}

	add_action( 'wp_ajax_vappv_ttw_list_available_gpt_models', 'vappv_ttw_list_available_gpt_models' );
}

//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//						           Other components
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------

if ( ! function_exists( 'vappv_ttw_add_admin_body_class' ) ) {

	/**
	 * Adds one or more classes to the body tag in the dashboard.
	 *
	 * @link https://wordpress.stackexchange.com/a/154951/17187
	 * @param String $classes Current body classes.
	 * @return String          Altered body classes.
	 */
	function vappv_ttw_add_admin_body_class( $classes ) {

		try {
			$current_request_url = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
			if ( false !== strpos( $current_request_url, 'talk-to-website-settings' ) ) {
				return $classes . ' vappv-ttw-plugin-admin-page';
			} else {
				return $classes;
			}
		}
		catch ( Throwable $t ) {
			return $classes;
		}

	}

	add_filter( 'admin_body_class', 'vappv_ttw_add_admin_body_class' );
}

if ( ! function_exists( 'vappv_ttw_settings_link' ) ) {

	/**
	 * Add 'Settings' button into plugins list
	 * @param array $links
	 * @return array
	 */
	function vappv_ttw_settings_link( array $links ) {
		$url           = get_admin_url() . 'admin.php?page=talk-to-website-settings';
		$settings_link = '<a href="' . $url . '">' . esc_html( __( 'Settings', 'talk-to-website' ) ) . '</a>';
		array_push( $links, $settings_link );
		return $links;
	}

	add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'vappv_ttw_settings_link' );
}

if ( ! function_exists( 'vappv_ttw_activate_plugin' ) ) {

	/**
	 * Initialize plugin activation (Install all necessary DB tables)
	 */
	function vappv_ttw_activate_plugin() {
		$installer = new VAPPV_TTW_Installer();
		$installer->install_plugin();
	}

	register_activation_hook( __FILE__, 'vappv_ttw_activate_plugin' );
}

if ( ! function_exists( 'vappv_ttw_uninstall_plugin' ) ) {

	/**
	 * Initialize plugin deactivation (Delete all plugin DB tables and data)
	 */
	function vappv_ttw_uninstall_plugin() {
		$installer = new VAPPV_TTW_Installer();
		$installer->uninstall_plugin();
	}

	register_uninstall_hook( __FILE__, 'vappv_ttw_uninstall_plugin' );
}

//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

/*
    © 2024 Copyright Vitalii A. Popov. All rights reserved.
*/