<?php
/**
 * Plugin Name: Compibot
 * Text Domain: compibot
 * Description: Potencia tu sitio de WordPress con un <strong>avanzado asistente virtual con IA generativa. Integración completa con tu instalación</strong> para ofrecer una atención al cliente personalizada y precisa. ¡Transforma la experiencia de tus usuarios con respuestas instantáneas y eficientes! Tus datos y los de tus clientes son totalmente privados y no se comparten con terceros.
 * Version: 2.1
 * Author: Inferencia Integral SL
 * Author URI: https://compibot.com/
 * Requires at least: 5.2
 * Tested up to: 6.9
 * Requires PHP: 7.0
 * License: GPLv3 or later
 * License URI: http://www.gnu.org/licenses/gpl-3.0.html

 * Copyright (C) 2024 Inferencia Integral SL

 * Este programa es software libre: puedes redistribuirlo y/o modificarlo bajo los términos de la
 * Licencia Pública General de GNU publicada por la Free Software Foundation, ya sea la versión 3
 * de la Licencia o (a tu elección) cualquier versión posterior.

 * Este programa se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTÍA; sin
 * incluso la garantía implícita de COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Para
 * más detalles, consulta la Licencia Pública General de GNU.

 * Deberías haber recibido una copia de la Licencia Pública General de GNU junto con este programa.
 * Si no es así, consulta <http://www.gnu.org/licenses/>.

 * @package Compibot
 */

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

if ( ! headers_sent() ) {
	ob_start();
}

// Define la constante para referenciar el archivo principal del plugin.
define( 'COMPIBOT_PLUGIN_FILE', __FILE__ );

/**
 * Clase principal del plugin Compibot.
 *
 * Gestiona la inicialización del plugin, los hooks y la interacción con la base de datos.
 */
class CompibotPlugin {

	const VERSION            = '2.0';
	const PLUGIN_NAME        = 'Compibot';
	const PLUGIN_SLUG        = 'compibot';
	const MINIMUM_WP_VERSION = '5.1';

	/**
	 * Constructor de la clase.
	 */
	public function __construct() {
		$this->define_constants();
		$this->load_dependencies();
		$this->register_hooks();
	}

	/**
	 * Obtiene la versión del plugin.
	 *
	 * @return string
	 */
	public static function get_version() {
		return self::VERSION;
	}

	/**
	 * Obtiene el nombre del plugin.
	 *
	 * @return string
	 */
	public static function get_plugin_name() {
		return self::PLUGIN_NAME;
	}

	/**
	 * Obtiene el slug del plugin.
	 *
	 * @return string
	 */
	public static function get_plugin_slug() {
		return self::PLUGIN_SLUG;
	}

	/**
	 * Obtiene la versión mínima de WordPress requerida por el plugin.
	 *
	 * @return string
	 */
	public static function get_minimum_wp_version() {
		return self::MINIMUM_WP_VERSION;
	}



	/**
	 * Método que define las constantes del plugin
	 */
	private function define_constants() {
		define( 'COMPIBOT_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
		define( 'COMPIBOT_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
	}

	/**
	 * Carga las dependencias requeridas por el plugin
	 */
	private function load_dependencies() {
		require_once COMPIBOT_PLUGIN_PATH . 'crons/cron-check-service.php';
		require_once COMPIBOT_PLUGIN_PATH . 'crons/class-dailycmsdata.php';
		require_once COMPIBOT_PLUGIN_PATH . 'crons/cron-scan.php';
		require_once COMPIBOT_PLUGIN_PATH . 'crons/cron-functions.php';
		require_once COMPIBOT_PLUGIN_PATH . 'admin/admin-menu.php';
		require_once COMPIBOT_PLUGIN_PATH . 'admin/class-compibotadminpage.php';
		require_once COMPIBOT_PLUGIN_PATH . 'admin/login-form.php';
		require_once COMPIBOT_PLUGIN_PATH . 'includes/activation.php';
		require_once COMPIBOT_PLUGIN_PATH . 'includes/deactivation.php';
		require_once COMPIBOT_PLUGIN_PATH . 'includes/api-login.php'; // Script que contiene la lógica relacionada con el manejo del formulario de inicio de sesión y el token del usuario.
		require_once COMPIBOT_PLUGIN_PATH . 'includes/enqueue-script.php';
		require_once COMPIBOT_PLUGIN_PATH . 'includes/services-checks.php';
		require_once COMPIBOT_PLUGIN_PATH . 'includes/class-compibotscanner.php';
		require_once COMPIBOT_PLUGIN_PATH . 'includes/get-conversations.php';
		require_once COMPIBOT_PLUGIN_PATH . 'includes/get-monthly-info.php';
		require_once COMPIBOT_PLUGIN_PATH . 'manager/class-compibotdatabasemanager.php';
		require_once COMPIBOT_PLUGIN_PATH . 'actions/compibot-requirements-check.php';
		require_once COMPIBOT_PLUGIN_PATH . 'actions/class-compibotwpcheckcache.php';
		require_once COMPIBOT_PLUGIN_PATH . 'actions/class-compibotnumberconversations.php';
	}

	/**
	 * Método para registrar todos los hooks necesarios para el plugin
	 */
	private function register_hooks() {
		register_activation_hook( __FILE__, array( $this, 'activate_plugin' ) );
		register_deactivation_hook( __FILE__, array( $this, 'deactivate_plugin' ) );
		register_uninstall_hook( __FILE__, array( 'CompibotPlugin', 'uninstall_plugin' ) );

		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
		add_action( 'admin_init', array( $this, 'redirect_after_activation' ) );
		add_action( 'wp_ajax_save_addons_to_db', array( $this, 'save_addons_to_db' ) );
		add_action( 'admin_footer', array( $this, 'enqueue_frontend_script' ) );
		add_action( 'admin_post_compibot_save_settings', 'compibot_save_settings' );
		add_action( 'admin_post_compibot_save_prompt', 'compibot_save_prompt' );
		add_action( 'admin_post_compibot_save_hours_module', 'compibot_save_hours_module' );
		add_action( 'admin_post_compibot_save_comportamiento_module', 'compibot_save_comportamiento_module' );
		add_action( 'admin_notices', array( 'CompibotWPCheckCache', 'show_wp_rocket_warning' ) );
		add_action( 'wp_ajax_compibot_dismiss_wp_rocket_notice', array( 'CompibotWPCheckCache', 'dismiss_wp_rocket_notice' ) );
		add_action( 'upgrader_process_complete', array( self::class, 'handle_plugin_update' ), 10, 2 );
		add_action( 'admin_init', array( self::class, 'maybe_update_table' ) );
		add_action( 'current_screen', 'compibot_load_admin_notice_on_plugins_page' );
		add_action( 'wp_ajax_compibot_get_scanned_items', array( 'CompibotScanner', 'compibot_get_scanned_items' ) );
	}

	/**
	 * Método que se ejecuta al activar el plugin
	 */
	public function activate_plugin() {
		compibot_check_wp_version();
		compibot_compibot_create_table();
		compibot_register_cron_event();
		compibot_register_daily_cron_event();
		compibot_register_daily_data_cron_event();
		compibot_select_type_login();
		update_option( 'compibot_activation_redirect', true );
	}

	/**
	 * Método que se ejecuta al desactivar el plugin
	 */
	public function deactivate_plugin() {
		compibot_compibot_remove_table(); // TODO: Cambiar el nombre de la función.
		compibot_remove_daily_cron_event();
		compibot_remove_cron_event();

		// Eliminamos de la base de datos el valor de "compibot_wp_rocket_notice_closed" para que cuando se active vuelva a aparecer el mensaje.
		update_option( 'compibot_wp_rocket_notice_closed', false );
	}

	/**
	 * Método para actualizar la tabla de la base de datos si es necesario.
	 *
	 * @return void
	 */
	public static function maybe_update_table() {
		// Comprobar si la flag está activa.
		$needs_update = get_transient( 'compibot_updated' );

		if ( ! $needs_update ) {
			return; // Salir si la flag no está activa.
		}

		// Si la flag está activa, iniciar la actualización.

		// Llama al método de actualización de la tabla.
		$db_manager = new CompibotDatabaseManager();
		$db_manager->update_table_schema();

		// Eliminar el transient después de la actualización.
		delete_transient( 'compibot_updated' );
	}

	/**
	 * Método que se ejecuta en el proceso de instalación/actualización del plugin.
	 *
	 * @param WP_Upgrader $upgrader Objeto WP_Upgrader.
	 * @param array       $hook_extra Información adicional sobre la actualización.
	 * @return void
	 */
	public static function handle_plugin_update( $upgrader, $hook_extra ) {
		if ( 'plugin' === $hook_extra['type'] && ! empty( $hook_extra['type'] )
			&& ! empty( $hook_extra['action'] ) && in_array( $hook_extra['action'], array( 'install', 'update', 'upgrade' ), true ) ) {

			// Ruta del plugin que se está actualizando.
			$plugin_source = isset( $upgrader->result['source'] ) ? $upgrader->result['source'] : '';

			if ( basename( $plugin_source ) === 'compibot' ) {

				// Establecer la flag como transient por 15 minutos.
				set_transient( 'compibot_updated', true, 15 * MINUTE_IN_SECONDS );

				// Establece la flag de actualización.
				update_option( 'compibot_updated', 1 ); // 1 significa que se necesita actualizar la tabla.
			}
		}
	}

	/**
	 * Método que se ejecuta al desinstalar el plugin
	 */
	public static function uninstall_plugin() {
		$db_manager = new CompibotDatabaseManager();

		global $wpdb;

		// Definimos la URL de la API.
		$url = 'https://panel.compibot.com/api/cms-deactivation/';

		// Comprobamos si existe el token en la base de datos.
		$exists = $db_manager->compibot_table_exists();

		if ( $exists ) {
			$token = $db_manager->compibot_select( 'token', 'plugin_token_compibot_page', 60 );
		}

		if ( $token ) {
			// Hacemos la llamada API al endpoint para actualizar el estado del plugin.
			$response = wp_remote_post(
				$url,
				array(
					'headers' => array(
						'Authorization' => 'Bearer ' . $token,
						'Content-Type'  => 'application/json',
					),
					'body'    => wp_json_encode(
						array(
							'accion' => 'desinstallation',
						)
					),
				)
			);

			// Verificamos si hubo algún error en la solicitud.
			if ( is_wp_error( $response ) ) {
				wp_die( 'Error al desinstalar el plugin: ' . esc_html( $response->get_error_message() ) . 'Error XXXXX' );
			}
		}

		$db_manager->compibot_drop_table();
	}

	/**
	 * Guarda los addons en la base de datos
	 *
	 * @return void
	 */
	public function save_addons_to_db() {
		$db_manager = new CompibotDatabaseManager();
		global $wpdb;
		$table_name = $wpdb->prefix . 'compibot';

		// Comprobar permisos y validar la solicitud.
		if ( ! isset( $_POST['addons'] ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( 'Permisos insuficientes o falta de parámetros.' );
			return;
		}

		// Verificamos el nonce.
		if ( ! isset( $_POST['compibot_compibot_addons_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['compibot_compibot_addons_nonce'] ) ), 'compibot_compibot_addons_action' ) ) {
			wp_die( 'Permiso denegado: solicitud no válida.' );
		}

		// Sanitizar y preparar los datos recibidos.
		$addons_json = sanitize_text_field( wp_unslash( $_POST['addons'] ) );
		$is_active   = isset( $_POST['is_active'] ) ? sanitize_text_field( wp_unslash( $_POST['is_active'] ) ) : 'false';

		// Verificar valor de "is_active".
		$is_active = ( 'true' === $is_active ) ? 1 : 0;

		$update_result = $db_manager->compibot_update(
			array(
				'modulos' => $addons_json,
				'active'  => $is_active,
			),
			array( 'id' => 1 ),
			array( '%s', '%d' ),
			array( '%d' )
		);

		// Verificar si la actualización fue exitosa.
		if ( false !== $update_result ) {
			wp_send_json_success( 'Addons guardados correctamente.' );
		} else {
			wp_send_json_error( 'Error al guardar los addons en la base de datos.' );
		}
	}

	/**
	 * Encola el script de Compibot en el frontend
	 *
	 * @return void
	 */
	public function enqueue_frontend_script() {

		$current_screen = get_current_screen();

		if ( 'toplevel_page_compibot' !== $current_screen->id ) {
			return;
		}

		// Obtiene el token de Compibot.
		$token = $this->get_compibot_public_token();

		// Encola el script de Compibot en el frontend si el token está disponible.
		if ( $token ) {
			wp_enqueue_script( 'compibot-js', 'https://bot.compibot.com/compibot.js', array(), 1.0, true ); // TODO: Añadir versión al JS.
			add_filter(
				'script_loader_tag',
				function ( $tag, $handle ) use ( $token ) {
					if ( 'compibot-js' === $handle ) {
						return str_replace( '<script', '<script data-token="' . esc_attr( $token ) . '"', $tag );
					}
					return $tag;
				},
				10,
				2
			);
		}
	}


	/**
	 * Redirige al usuario a la página de administración después de activar el plugin.
	 *
	 * @return void
	 */
	public function redirect_after_activation() {
		// Comprueba si la opción de redirección está configurada.
		if ( get_option( 'compibot_activation_redirect', false ) ) {
			// Elimina la opción para evitar múltiples redirecciones.
			delete_option( 'compibot_activation_redirect' );

			// Comprueba si el usuario está en el área de administración.
			if ( is_admin() ) {
				wp_safe_redirect( admin_url( 'admin.php?page=compibot' ) );
				exit;
			}
		}
	}

	/**
	 * Hook para encolar los scripts y estilos necesarios en el panel de administración
	 */
	public function enqueue_admin_scripts( $hook ) {
		$allowed = array(
			'toplevel_page_compibot',
			'compibot_page_compibot_login',
		);

		if ( ! in_array( $hook, $allowed, true ) ) {
			return;
		}

		$this->enqueue_scripts();
		$this->enqueue_styles();
	}



	/**
	 *  Encola los scripts JS necesarios para el plugin
	 */
	public function enqueue_scripts() {
		$scripts = array(
			'leaflet-js'          => 'assets/js/leaflet.js',
			'chart-umd-js'        => 'assets/js/chart.umd.js',
			'chart-datalabels-js' => 'assets/js/chartjs-plugin-datalabels.min.js',
			'intro-js'            => 'assets/js/intro.min.js',
			'markdown-it-js'      => 'assets/js/markdown-it.min.js',
			'compibot-admin-js'   => 'assets/js/compibot-admin-notification.js',
			'admin-page-js'       => 'assets/js/admin-page.js',
		);

		foreach ( $scripts as $script => $path ) {
			wp_enqueue_script(
				$script,
				plugins_url( $path, __FILE__ ),
				array(), // Dependencias si las hay.
				1.0, // Versión.
				true // Cargar en el footer.
			);
		}

		wp_localize_script(
			'admin-page-js',
			'compibotData',
			array(
				'ajaxurl'                                 => admin_url( 'admin-ajax.php' ),
				'nonce_addons_action'                     => wp_create_nonce( 'compibot_compibot_addons_action' ),
				'nonce_update_conversations_action'       => wp_create_nonce( 'compibot_update_conversations_action' ),
				'nonce_compibot_save_total_viewed_action' => wp_create_nonce( 'compibot_save_total_viewed_action' ),
				'nonce_compibot_update_info_section_action' => wp_create_nonce( 'compibot_update_info_section_action' ),
				'token'                                   => $this->get_compibot_token(),
				'kbScanned'                               => $this->compibot_get_kb_scanned(),
				'kbPlan'                                  => 0,
				'nonce_compibot_get_scanned_items'        => wp_create_nonce( 'compibot_get_scanned_items' ),
			)
		);

		// Localizar el script para AJAX (solo si se añadió compibot-admin.js).
		if ( isset( $scripts['compibot-admin-js'] ) ) {
			wp_localize_script(
				'compibot-admin-js',
				'compibotAjax',
				array(
					'ajaxurl' => admin_url( 'admin-ajax.php' ),
					'nonce'   => wp_create_nonce( 'compibot_nonce' ),
				)
			);
		}
	}

	/**
	 *  Encola los estilos CSS necesarios para el plugin
	 */
	public function enqueue_styles() {
		$styles = array(
			'font-awesome' => 'assets/css/font-awesome.min.css',
			'leaflet-css'  => 'assets/css/leaflet.css',
			'intro-css'    => 'assets/css/introjs.min.css',
		);

		foreach ( $styles as $handle => $path ) {
			wp_enqueue_style( $handle, plugins_url( $path, __FILE__ ), array(), '1.0' );
		}

		// Agregar estilos en línea.
		$inline_styles = array(
			'leaflet-css'         => ".leaflet-container img {
                background-image: url('" . plugins_url( 'assets/css/images/marker-icon.png', __FILE__ ) . "');
            }",
			'plugin-admin-styles' => "
                .plugin-description-image {
                    background-image: url('" . plugin_dir_url( __FILE__ ) . "assets/ventana-plugin-descripcion.png');
                    background-size: contain;
                    background-repeat: no-repeat;
                    display: block;
                    width: 260px;
                    height: 420px;
                    max-width: 239px;
                    border-radius: 8px;
                    overflow: hidden;
                }
                .responsive-chat-icon-1 {
                    width: 50px;
                    height: 50px;
                    object-fit: contain; 
                    background-size: contain;
                    background-repeat: no-repeat;
                    background-position: center;
                    display: inline-block;
                    background-image: url('" . plugin_dir_url( __FILE__ ) . "assets/bubble-blanco-negro.png');
                }
                .responsive-chat-icon-2 {
                    width: 50px;
                    height: 50px;
                    object-fit: contain; 
                    background-size: contain;
                    background-repeat: no-repeat;
                    background-position: center;
                    display: inline-block;
                    background-image: url('" . plugin_dir_url( __FILE__ ) . "assets/bubble-blanco-verde.png');
                }
                .responsive-chat-icon-3 {
                    width: 50px;
                    height: 50px;
                    object-fit: contain; 
                    background-size: contain;
                    background-repeat: no-repeat;
                    background-position: center;
                    display: inline-block;
                    background-image: url('" . plugin_dir_url( __FILE__ ) . "assets/bubble-defecto.png');
                }
                .compibot-plugin-logo {
                    background-image: url('" . plugin_dir_url( __FILE__ ) . "assets/logo.svg');
                    background-size: contain;
                    background-repeat: no-repeat;
                    background-position: center;
                    display: inline-block;
                    width: 250px;
                    height: 50px;
                }
                .plugin-description-image.small {
                    width: 200px;
                    height: 300px;
                }
                .plugin-data-transfusion {
                    background-image: url('" . plugin_dir_url( __FILE__ ) . "assets/data-transfusion-compibot.png');
                    background-size: contain;
                    background-repeat: no-repeat;
                    display: block;
                    width: 100%;
                    max-width: 400px;
                    aspect-ratio: 4 / 3;
                    margin: 0 auto -60px;
                }
            ",
		);

		wp_register_style( 'plugin-admin-styles', false, array(), '1.0.0' );
		wp_enqueue_style( 'plugin-admin-styles' );

		foreach ( $inline_styles as $handle => $css ) {
			wp_add_inline_style( $handle, $css );
		}
	}

	/**
	 * Obtener el token público de Compibot desde la base de datos.
	 *
	 * @return string|null El token si se encuentra, null en caso contrario.
	 */
	private function get_compibot_public_token() {
		global $wpdb;

		$db_manager = new CompibotDatabaseManager();

		$columns = $db_manager->compibot_get_columns();
		if ( in_array( 'public_token', $columns, true ) ) {
			// Intenta obtener el "public_token".
			$public_token = $db_manager->compibot_select( 'public_token', 'plugin_token_compibot_page', 60 );

		} elseif ( in_array( 'token', $columns, true ) ) {
			// Si no existe "public_token", intenta obtener "token".
			$public_token = $db_manager->compibot_select( 'token', 'plugin_token_compibot_page', 60 );

		} else {
			return;
		}

		return $public_token;
	}

	/**
	 * Devuelve el token de Compibot desde la base de datos.
	 *
	 * @return string|null El token si se encuentra, null en caso contrario.
	 */
	private function get_compibot_token() {
		$db_manager = new CompibotDatabaseManager();

		$token = $db_manager->compibot_select( 'token', 'plugin_token_compibot_page', 60 );

		return $token;
	}


	/**
	 * Método que obtiene el total de kb escaneados desde la base de datos
	 *
	 * @return int
	 */
	private function compibot_get_kb_scanned() {
		$db_manager = new CompibotDatabaseManager();
		$kb_scanned = $db_manager->compibot_select( 'kb_scanned', 'plugin_kb_scanned_compibot_page', 60 );

		return $kb_scanned;
	}
}

if ( class_exists( 'CompibotPlugin' ) ) {
	new CompibotPlugin();
}
