<?php
if (!defined('ABSPATH'))
    exit; // Exit if accessed directly

if (!class_exists('XAGIO_API')) {

    class XAGIO_API
    {

        private static $captured_wp_die = null;

        public static function initialize()
        {
            // Fixes for plugins that disable App Passwords
            // and cause Xagio issues with communication
            self::checkWordfenceAndEnableAppPasswords();
            self::checkAllInOneSecurityAndEnableAppPasswords();

            add_action('rest_api_init', [
                'XAGIO_API',
                'registerXagioRoutes'
            ]);
            // Plugin Triggers
            add_action('deleted_plugin', [
                'XAGIO_API',
                'pluginDeleted'
            ], 10, 2);

            add_action('deactivated_plugin', [
                'XAGIO_API',
                'pluginDeactivated'
            ], 10, 2);

            add_action('activated_plugin', [
                'XAGIO_API',
                'pluginActivated'
            ], 10, 2);

            // Theme Trigger
            add_action('after_switch_theme', [
                'XAGIO_API',
                'themeSwitch'
            ]);

        }

        public static function checkAllInOneSecurityAndEnableAppPasswords()
        {

            if (is_plugin_active('all-in-one-wp-security-and-firewall/wp-security.php')) {
                // Get AIOWPS settings
                $aiowps_settings = get_option('aio_wp_security_configs');

                // Check if settings exist and is array
                if ($aiowps_settings && is_array($aiowps_settings)) {
                    // Check if specific setting exists and is set to 1
                    if (isset($aiowps_settings['aiowps_disable_application_password']) && $aiowps_settings['aiowps_disable_application_password'] == 1) {

                        // Modify the setting
                        $aiowps_settings['aiowps_disable_application_password'] = 0;

                        // Update the option in database
                        update_option('aio_wp_security_configs', $aiowps_settings);
                    }
                }
            }

        }

        public static function checkWordfenceAndEnableAppPasswords()
        {
            global $wpdb;

            // Check if Wordfence is installed and active
            if (!function_exists('is_plugin_active')) {
                require_once(ABSPATH . 'wp-admin/includes/plugin.php');
            }

            // Check for both possible Wordfence plugin slugs
            $wordfence_slugs = [
                'wordfence/wordfence.php',
                'wordfence-security/wordfence.php'
                // Alternative slug
            ];

            $wordfence_active = false;
            foreach ($wordfence_slugs as $slug) {
                if (is_plugin_active($slug)) {
                    $wordfence_active = true;
                    break;
                }
            }

            if (!$wordfence_active) {
                return false;
            }

            // Check if application passwords are disabled
            $wfconfig_table = $wpdb->prefix . 'wfconfig';
            $disabled       = $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT val FROM $wfconfig_table WHERE name = %s", 'loginSec_disableApplicationPasswords'
                )
            );

            // Only proceed if application passwords are disabled (val = 1)
            if ($disabled == 1) {
                // Try to enable application passwords
                // Update the wp_wfconfig table
                $wfconfig_table = $wpdb->prefix . 'wfconfig';
                $wfconfig_name  = 'loginSec_disableApplicationPasswords';

                $result1 = $wpdb->update(
                    $wfconfig_table, ['val' => 0], ['name' => $wfconfig_name], ['%d'], // Value format
                    ['%s']  // Where clause format
                );

                // Check for errors in the first update
                if ($result1 === false) {
                    return false;
                }

                // Update the wp_options table
                $options_table = $wpdb->prefix . 'options';
                $option_name   = 'using_application_passwords';

                $result2 = $wpdb->update(
                    $options_table, ['option_value' => 1], ['option_name' => $option_name], ['%d'], // Value format
                    ['%s']  // Where clause format
                );

                // Check for errors in the second update
                if ($result2 === false) {
                    return false;
                }

                // If both updates succeed
                return true;
            }

            return true;
        }

        public static function registerXagioRoutes()
        {
            // General API request route
            register_rest_route(
                'xagio-seo/v1', '/api', [
                    'methods'             => 'POST',
                    'callback'            => [
                        'XAGIO_API',
                        'handleRequest'
                    ],

                    // Permission callback to verify either:
                    //  - The user is already logged in (and is super admin), OR
                    //  - Valid credentials are passed in the X-Xagio-Auth header.
                    'permission_callback' => [
                        'XAGIO_API',
                        'restPermissionCheck'
                    ],
                ]
            );

            register_rest_route('xagio-seo/v1', '/templates/install', [
                'methods'             => 'POST',
                'callback'            => [
                    'XAGIO_API',
                    'installTemplateByKey'
                ],
                'permission_callback' => [
                    'XAGIO_API',
                    'restPermissionCheck'
                ]
            ]);

            // General API request route
            register_rest_route('xagio-seo/v1', '/ping', [
                'methods'             => 'POST',
                'callback'            => [
                    'XAGIO_API',
                    'ping'
                ],
                'permission_callback' => function ($request = null) {
                    return true;
                }
            ]);

            // Handle remote login
            register_rest_route('xagio-seo/v1', '/remote-login', [
                'methods'             => 'GET',
                'callback'            => [
                    'XAGIO_API',
                    'remoteLogin'
                ],
                'permission_callback' => function ($request = null) {
                    if (!empty($request->get_param('xagio_remoteLoginToken'))) {

                        // Sanitize the token
                        $xagio_remoteLoginToken = sanitize_text_field(wp_unslash($request->get_param('xagio_remoteLoginToken')));

                        // Compare the temporary token with the stored transient
                        if ($xagio_remoteLoginToken !== get_transient('xagio_remoteLoginToken')) {
                            return false;
                        }

                        return true;

                    } else {
                        return false;
                    }
                }
            ]);

        }

        public static function restPermissionCheck($request)
        {
            if ($request === null) {
                return new WP_Error('invalid_request', 'Invalid REST request context.', ['status' => 400]);
            }

            if (is_user_logged_in() && is_super_admin()) {
                return true;
            }

            $authHeader = $request->get_header('x-xagio-auth');
            if (empty($authHeader)) {
                return new WP_Error(
                    'missing_auth_header', 'X-Xagio-Auth header is missing.', ['status' => 401]
                );
            }

            $decoded = base64_decode($authHeader, true);
            if ($decoded === false) {
                return new WP_Error(
                    'invalid_base64', 'Invalid X-Xagio-Auth header (not valid Base64).', ['status' => 401]
                );
            }

            $parts = explode(':', $decoded, 2);
            if (count($parts) !== 2) {
                return new WP_Error(
                    'invalid_credentials_format', 'Could not parse username:password from X-Xagio-Auth header.', ['status' => 401]
                );
            }

            list($username, $password) = $parts;

            $user = wp_authenticate($username, $password);

            if (is_wp_error($user)) {
                if (function_exists('wp_is_application_passwords_available') && wp_is_application_passwords_available()) {
                    $app_user = wp_authenticate_application_password(null, $username, $password);
                    if (is_wp_error($app_user)) {
                        return new WP_Error(
                            'authentication_failed', 'Invalid username or password (normal or app password).', ['status' => 401]
                        );
                    }
                    $user = $app_user;
                } else {
                    return new WP_Error(
                        'authentication_failed', 'Invalid username or password (normal credentials).', ['status' => 401]
                    );
                }
            }

            wp_set_current_user($user->ID);

            if (!is_super_admin($user->ID)) {
                return new WP_Error(
                    'permission_denied', 'You do not have the required privileges.', ['status' => 403]
                );
            }

            return true;
        }

        public static function ping($request = null)
        {
            xagio_json("success", "pong");
        }

        public static function syncWithPanel($request = null)
        {
            if (!defined('XAGIO_DOMAIN') || XAGIO_DOMAIN === '') {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            XAGIO_API::apiRequest(
                $endpoint = 'sync', $method = 'GET', [
                    'domain' => XAGIO_DOMAIN,
                ]
            );
        }

        public static function themeSwitch($old_name)
        {
            if (!defined('XAGIO_DOMAIN') || XAGIO_DOMAIN === '') {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            $new_theme = wp_get_theme();
            XAGIO_API::apiRequest(
                $endpoint = 'themes', $method = 'POST', [
                    'domain' => XAGIO_DOMAIN,
                    'new'    => $new_theme->get('Name'),
                    'old'    => $old_name,
                    'event'  => 'switched',
                ]
            );
        }

        public static function pluginDeleted($root_name, $success)
        {
            if (!defined('XAGIO_DOMAIN') || XAGIO_DOMAIN === '') {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            if (!$success) {
                return FALSE;
            }
            XAGIO_API::apiRequest(
                $endpoint = 'plugins', $method = 'POST', [
                    'domain'    => XAGIO_DOMAIN,
                    'root_name' => $root_name,
                    'event'     => 'deleted',
                ]
            );
        }

        public static function pluginDeactivated($root_name, $network_activation)
        {
            if (!defined('XAGIO_DOMAIN') || XAGIO_DOMAIN === '') {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            XAGIO_API::apiRequest(
                $endpoint = 'plugins', $method = 'POST', [
                    'domain'    => XAGIO_DOMAIN,
                    'root_name' => $root_name,
                    'event'     => 'deactivated',
                ]
            );
        }

        public static function pluginActivated($root_name, $network_activation)
        {
            if (!defined('XAGIO_DOMAIN') || XAGIO_DOMAIN === '') {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            XAGIO_API::apiRequest(
                $endpoint = 'plugins', $method = 'POST', [
                    'domain'    => XAGIO_DOMAIN,
                    'root_name' => $root_name,
                    'event'     => 'activated',
                ]
            );
        }

        /***************************************************************************************************************
         *
         *   Remote Datatables
         *
         **************************************************************************************************************/

        public static function getPostTypes($request = null)
        {
            $xagio_post_types = XAGIO_MODEL_SEO::getAllPostTypes();

            xagio_json('success', 'Retrieved post types.', $xagio_post_types);
        }

        public static function getCategoriesAndTags($request = null)
        {
            $data = XAGIO_MODEL_SEO::getAllCategoriesAndTags();

            xagio_json('success', 'Retrieved categories and tags.', $data);
        }

        public static function getTaxonomies($request = null)
        {
            $xagio_taxonomies = XAGIO_MODEL_SEO::getAllTaxonomies(FALSE);
            xagio_json('success', 'Retrieved taxonomies.', $xagio_taxonomies);
        }

        public static function searchTaxonomies( $request = null ) {
            global $wpdb;

            // Paging (numbers only)
            $start  = absint( $request->get_param( 'iDisplayStart' ) );
            $length = absint( $request->get_param( 'iDisplayLength' ) );
            if ( $length < 1 ) {
                $length = 50;
            }
            if ( $length > 200 ) {
                $length = 200;
            }

            // ORDER BY
            $sortable = [
                'term_id'      => 't.term_id',
                'name'         => 't.name',
                'description'  => 'tt.description',
                'count'        => 'tt.count',
                'taxonomy'     => 'tt.taxonomy',
            ];
            $order_by  = 't.term_id';
            $order_dir = 'DESC';

            // DataTables style input
            $sort_col = $request->get_param( 'mDataProp_0' );
            $sort_dir = $request->get_param( 'sSortDir_0' );

            if ( is_string( $sort_col ) ) {
                $sort_col = sanitize_key( $sort_col );
                if ( isset( $sortable[ $sort_col ] ) ) {
                    $order_by = $sortable[ $sort_col ];
                }
            }
            if ( is_string( $sort_dir ) ) {
                $sort_dir  = strtolower( sanitize_text_field( wp_unslash( $sort_dir ) ) );
                $order_dir = ( 'asc' === $sort_dir ) ? 'ASC' : 'DESC';
            }

            // Filters (values only)
            $taxonomy = $request->get_param( 'taxonomy' );
            $search   = $request->get_param( 'sSearch' );

            $taxonomy = is_string( $taxonomy ) ? sanitize_key( $taxonomy ) : '';
            $search   = is_string( $search ) ? sanitize_text_field( wp_unslash( $search ) ) : '';

            // Strong validation for taxonomy
            if ( $taxonomy ) {
                $allowed_tax = get_taxonomies( [], 'names' );
                if ( ! in_array( $taxonomy, $allowed_tax, true ) ) {
                    $taxonomy = '';
                }
            }

            $where_sql = 'WHERE 1=1';
            $args      = [];

            if ( $taxonomy ) {
                $where_sql .= ' AND tt.taxonomy = %s';
                $args[] = $taxonomy;
            }

            if ( $search !== '' ) {
                $like = '%' . $wpdb->esc_like( $search ) . '%';
                $where_sql .= ' AND (t.name LIKE %s OR t.term_id LIKE %s OR tt.description LIKE %s)';
                $args[] = $like;
                $args[] = $like;
                $args[] = $like;
            }

            // Main query: keep query string literal
            $rResult = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT SQL_CALC_FOUND_ROWS
				t.term_id,
				t.name,
				tt.description,
				tt.count,
				tt.taxonomy
			FROM {$wpdb->prefix}terms t
			JOIN {$wpdb->prefix}term_taxonomy tt ON tt.term_id = t.term_id
			{$where_sql}
			ORDER BY {$order_by} {$order_dir}
			LIMIT %d, %d",
                    array_merge( $args, [ $start, $length ] )
                ),
                ARRAY_A
            );

            $iFilteredTotal = (int) $wpdb->get_var( 'SELECT FOUND_ROWS()' );
            $iTotal         = (int) $wpdb->get_var( "SELECT COUNT(term_id) FROM {$wpdb->prefix}terms" );

            foreach ( $rResult as $xagio_i => $row ) {
                $term = get_term( (int) $row['term_id'] );
                if ( $term && ! is_wp_error( $term ) ) {
                    $rResult[ $xagio_i ]['schema'] = XAGIO_MODEL_SCHEMA::getSchemas( (int) $row['term_id'], 'term' );
                } else {
                    $rResult[ $xagio_i ]['schema'] = false;
                }
            }

            $xagio_output = [
                'sEcho'                => absint( $request->get_param( 'sEcho' ) ),
                'iTotalRecords'        => $iTotal,
                'iTotalDisplayRecords' => $iFilteredTotal,
                'aaData'               => $rResult,
            ];

            wp_send_json( $xagio_output );
        }


        public static function searchPosts( $request = null ) {
            global $wpdb;

            // Paging (numbers only)
            $start  = absint( $request->get_param( 'iDisplayStart' ) );
            $length = $request->get_param( 'iDisplayLength' );
            $length = ( null === $length ) ? 50 : absint( $length );

            if ( $length < 1 ) {
                $length = 50;
            }
            if ( $length > 200 ) {
                $length = 200;
            }

            // ORDER BY (whitelist only)
            $sortable = [
                'ID'            => 'ID',
                'post_author'   => 'post_author',
                'post_date'     => 'post_date',
                'post_title'    => 'post_title',
                'post_status'   => 'post_status',
                'comment_status'=> 'comment_status',
                'post_name'     => 'post_name',
                'post_parent'   => 'post_parent',
                'guid'          => 'guid',
                'post_type'     => 'post_type',
                'comment_count' => 'comment_count',
            ];

            $order_by  = 'ID';
            $order_dir = 'DESC';

            $sort_col = $request->get_param( 'mDataProp_0' );
            $sort_dir = $request->get_param( 'sSortDir_0' );

            if ( is_string( $sort_col ) ) {
                $sort_col = sanitize_key( $sort_col );
                if ( isset( $sortable[ $sort_col ] ) ) {
                    $order_by = $sortable[ $sort_col ];
                }
            }
            if ( is_string( $sort_dir ) ) {
                $sort_dir  = strtolower( sanitize_text_field( wp_unslash( $sort_dir ) ) );
                $order_dir = ( 'asc' === $sort_dir ) ? 'ASC' : 'DESC';
            }

            // WHERE (build with fixed strings + placeholders only)
            $args  = [];
            $where = "WHERE post_status IN ('publish','future','draft','pending')";

            // Post type filter
            $post_type = $request->get_param( 'PostsType' );
            $post_type = is_string( $post_type ) ? sanitize_key( $post_type ) : '';

            if ( $post_type ) {
                $where .= " AND post_type = %s";
                $args[] = $post_type;
            } else {
                $allowed = (array) XAGIO_MODEL_SEO::getAllPostTypes();
                $allowed = array_values( array_filter( array_map( 'sanitize_key', $allowed ) ) );

                if ( empty( $allowed ) ) {
                    // Fallback to very safe defaults.
                    $allowed = [ 'page', 'post' ];
                }

                $placeholders = implode( ',', array_fill( 0, count( $allowed ), '%s' ) );
                $where .= " AND post_type IN ($placeholders)";
                foreach ( $allowed as $pt ) {
                    $args[] = $pt;
                }
            }

            // Search
            $search = $request->get_param( 'sSearch' );
            $search = is_string( $search ) ? sanitize_text_field( wp_unslash( $search ) ) : '';

            if ( $search !== '' ) {
                $like = '%' . $wpdb->esc_like( $search ) . '%';
                $where .= " AND (post_title LIKE %s OR CAST(ID AS CHAR) LIKE %s OR post_name LIKE %s)";
                $args[] = $like;
                $args[] = $like;
                $args[] = $like;
            }

            // Main query (no $sql variable; literal inside prepare)
            $rResult = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT SQL_CALC_FOUND_ROWS
				ID, post_author, post_date, post_title, post_status,
				comment_status, post_name, post_parent, guid, post_type, comment_count
			FROM {$wpdb->posts}
			{$where}
			ORDER BY {$order_by} {$order_dir}
			LIMIT %d, %d",
                    array_merge( $args, [ $start, $length ] )
                ),
                ARRAY_A
            );

            $iFilteredTotal = (int) $wpdb->get_var( 'SELECT FOUND_ROWS()' );

            // Total data set length (no interpolated identifiers)
            $iTotal = (int) $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_status IN ('publish','future','draft','pending')" );

            // Additional processing
            $aChildren = [];
            foreach ( $rResult as &$row ) {
                $children        = get_pages( [ 'child_of' => (int) $row['ID'] ] );
                $row['page_url'] = esc_url( get_permalink( (int) $row['ID'] ) );

                if ( $children ) {
                    $aChildren[] = XAGIO_MODEL_PROJECTS::getAncestorTree( (int) $row['ID'] );
                }

                $row = XAGIO_MODEL_PROJECTS::generateSiloPageArray( $row );
            }
            unset( $row );

            $tempResults = [];
            foreach ( $aChildren as $tree ) {
                foreach ( (array) $tree as $child_id ) {
                    foreach ( $rResult as $xagio_key => $rows ) {
                        if ( (int) $child_id === (int) $rows['ID'] ) {
                            $tempResults[] = $rows;
                            array_splice( $rResult, $xagio_key, 1 );
                            break;
                        }
                    }
                }
            }

            $rResult = array_merge( $rResult, $tempResults );

            $xagio_output = [
                'sEcho'                => absint( $request->get_param( 'sEcho' ) ),
                'iTotalRecords'        => $iTotal,
                'iTotalDisplayRecords' => $iFilteredTotal,
                'aaData'               => $rResult,
            ];

            wp_send_json( $xagio_output );
        }



        public static function allComments($request = null) {
            global $wpdb;

            // Paging
            $start  = absint($request->get_param('iDisplayStart'));
            $length = $request->get_param('iDisplayLength');
            $length = ($length === null || $length === '' || $length === '-1') ? 50 : absint($length);
            if ($length < 1) {
                $length = 50;
            }
            if ($length > 200) {
                $length = 200;
            }

            $sortable = [
                'comment_ID'         => 'comment_ID',
                'comment_post_ID'    => 'comment_post_ID',
                'comment_author'     => 'comment_author',
                'comment_author_email' => 'comment_author_email',
                'comment_author_url' => 'comment_author_url',
                'comment_date'       => 'comment_date',
                'comment_content'    => 'comment_content',
                'comment_approved'   => 'comment_approved',
                'comment_parent'     => 'comment_parent',
            ];

            $order_by  = 'comment_ID';
            $order_dir = 'DESC';

            $sort_col = $request->get_param('mDataProp_0');
            $sort_dir = $request->get_param('sSortDir_0');

            if (is_string($sort_col)) {
                $sort_col = sanitize_key($sort_col);
                if (isset($sortable[$sort_col])) {
                    $order_by = $sortable[$sort_col];
                }
            }
            if (is_string($sort_dir)) {
                $sort_dir = strtolower(sanitize_text_field(wp_unslash($sort_dir)));
                $order_dir = ($sort_dir === 'asc') ? 'ASC' : 'DESC';
            }

            // Filters
            $state_param = $request->get_param('CommentState');
            $filter_state = 0;
            $comment_state = '';

            if ($state_param !== null && $state_param !== '') {
                $filter_state = 1;
                // allow "0", "1", "spam", "trash" etc.
                $comment_state = sanitize_text_field(wp_unslash((string) $state_param));
            }

            $search_param = $request->get_param('sSearch');
            $filter_search = 0;
            $search_like = '';

            if (is_string($search_param)) {
                $search_param = trim($search_param);
                if ($search_param !== '') {
                    $filter_search = 1;
                    $search_like = '%' . $wpdb->esc_like(sanitize_text_field(wp_unslash($search_param))) . '%';
                }
            }

            // MAIN QUERY
            $rResult = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT SQL_CALC_FOUND_ROWS
                comment_ID, comment_post_ID, comment_author, comment_author_email, comment_author_url, comment_date, comment_content, comment_approved, comment_parent
             FROM {$wpdb->comments}
             WHERE comment_type = 'comment'
               AND (%d = 0 OR comment_approved = %s)
               AND (%d = 0 OR (comment_content LIKE %s OR CAST(comment_ID AS CHAR) LIKE %s OR comment_author LIKE %s))
             ORDER BY {$order_by} {$order_dir}
             LIMIT %d, %d", $filter_state, $comment_state, $filter_search, $search_like, $search_like, $search_like, $start, $length),
                ARRAY_A
            );

            $iFilteredTotal = (int) $wpdb->get_var('SELECT FOUND_ROWS()');
            $iTotal = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE comment_type = 'comment'");

            foreach ($rResult as &$row) {
                $row['author_email_hash'] = md5(strtolower(trim((string) $row['comment_author_email'])));

                if (!empty($row['comment_parent'])) {
                    $parent_comment = $wpdb->get_row(
                        $wpdb->prepare(
                            "SELECT comment_author FROM {$wpdb->comments} WHERE comment_ID = %d",
                            absint($row['comment_parent'])
                        ),
                        ARRAY_A
                    );
                    $row['parent_comment'] = $parent_comment['comment_author'] ?? false;
                } else {
                    $row['parent_comment'] = false;
                }

                $row['post_title'] = esc_html(get_the_title((int) $row['comment_post_ID']));
                $row['post_url']   = esc_url(get_permalink((int) $row['comment_post_ID']));
            }
            unset($row);

            // Count comments by state
            $commentCount = $wpdb->get_results(
                "SELECT comment_approved, COUNT(comment_approved) as num
         FROM {$wpdb->comments}
         WHERE comment_type = 'comment'
         GROUP BY comment_approved",
                ARRAY_A
            );

            $temp = [
                'pending'  => 0,
                'approved' => 0,
                'spam'     => 0,
                'trash'    => 0,
            ];

            foreach ((array) $commentCount as $c) {
                $status = (string) $c['comment_approved'];
                $num    = (int) $c['num'];

                switch ($status) {
                    case "0":
                        $temp['pending'] = $num;
                        break;
                    case "1":
                        $temp['approved'] = $num;
                        break;
                    default:
                        $temp[$status] = $num;
                        break;
                }
            }

            $xagio_output = [
                "sEcho"                => absint($request->get_param('sEcho')) ?: 1,
                "iTotalRecords"        => $iTotal,
                "iTotalDisplayRecords" => $iFilteredTotal,
                "aaData"               => $rResult,
                "commentCount"         => $temp,
            ];

            wp_send_json($xagio_output);
        }



        /***************************************************************************************************************
         *
         *   Handlers
         *
         **************************************************************************************************************/

        static $class_renames = [
            'MXAG_Ai' => 'XAGIO_MODEL_AI',
        ];

        // Handle Request
        public static function handleRequest($request = null)
        {
            if ($request == null) {
                wp_die('Invalid request type.');
            }

            $function = sanitize_text_field(wp_unslash($request->get_param('function')));
            $class    = sanitize_text_field(wp_unslash($request->get_param('class')));

            // Perform class renaming (old Plugin)
            if (!empty(self::$class_renames[$class])) {
                $class = self::$class_renames[$class];
            }

            if (!empty($class)) {

                if (method_exists($class, $function)) {

                    call_user_func([
                        $class,
                        $function
                    ], $request);

                } else {
                    xagio_json('error', 'Requested class/method does not exist! Please update your plugin on this website to the latest version!');
                }

            } else {

                if ($function === 'syncServerAPI') {

                    call_user_func([
                        'XAGIO_API',
                        'syncServerAPI'
                    ], $request);

                } else {

                    if (method_exists('XAGIO_API', $function)) {
                        call_user_func([
                            'XAGIO_API',
                            $function
                        ], $request);
                    } else {
                        xagio_json('error', 'Requested API function does not exist! Please update your plugin on this website to the latest version!');
                    }

                }

            }
        }

        public static function getAPIKey($regenerate = false)
        {
            // Define the length of the password
            $pw_length = 24; // You can define this as static::PW_LENGTH elsewhere

            // Get the first administrator user
            $admin_users = get_users(array(
                'role'    => 'administrator',
                'orderby' => 'ID',
                'order'   => 'ASC',
                'number'  => 1
            ));

            if (!empty($admin_users)) {
                $admin_user = $admin_users[0];
                $username   = $admin_user->user_login;  // Get the username

                // Get existing application passwords from user meta
                $app_passwords = get_user_meta($admin_user->ID, '_application_passwords', true);

                // Check if there is already an API key entry for 'XAGIO_API'
                $existing_api_key = null;
                if (is_array($app_passwords)) {
                    foreach ($app_passwords as $password_entry) {
                        if ($password_entry['name'] === 'XAGIO_API') {
                            $existing_api_key = $password_entry;
                            break;
                        }
                    }
                } else {
                    $app_passwords = array();
                }

                $XAGIO_API     = get_option('XAGIO_API');
                if ($XAGIO_API === false) {
                    $regenerate = true;
                }

                // If an API key for 'XAGIO_API' does not exist, generate a new one
                if ($regenerate === true) {
                    // Generate a new application password
                    $new_password    = wp_generate_password($pw_length, false); // 24 characters, no special characters
                    $hashed_password = wp_hash_password($new_password);

                    // Prepare for sending
                    $encoded_password = base64_encode($username . ":" . $new_password . ':' . $hashed_password);

                    // Prepare new application password entry
                    $new_item = array(
                        'uuid'      => wp_generate_uuid4(),
                        // Generate a unique UUID
                        'app_id'    => '',
                        // Can set or pass custom app_id if needed
                        'name'      => 'XAGIO_API',
                        // Name of the application password
                        'password'  => $hashed_password,
                        // Hashed password stored
                        'created'   => time(),
                        // Time of creation (Unix timestamp)
                        'last_used' => null,
                        // Last used time (null until used)
                        'last_ip'   => null,
                        // Last used IP (null until used)
                        'api_key'   => $encoded_password
                    );

                    if (!empty($existing_api_key)) {

                        // If an existing API key is found, replace the current entry with the new one
                        foreach ($app_passwords as $xagio_key => $password_entry) {
                            if ($password_entry['name'] == 'XAGIO_API') {
                                // Update the existing entry with new password and timestamp
                                $app_passwords[$xagio_key] = $new_item;
                                break;
                            }
                        }

                    } else {

                        // Add the new application password entry to the array
                        $app_passwords[] = $new_item;

                    }

                    // Update the user meta with the new password list
                    update_user_meta($admin_user->ID, '_application_passwords', $app_passwords);
                    update_option('XAGIO_API', $encoded_password);
                    update_option('using_application_passwords', true);

                    return $encoded_password;
                } else {
                    if (isset($existing_api_key['api_key'])) {
                        return $existing_api_key['api_key'];
                    } else {
                        return $existing_api_key['password'];
                    }
                }
            } else {
                return false; // No administrator users found
            }
        }

        public static function downloadFile($xagio_location, $xagio_file)
        {
            include_once ABSPATH . 'wp-admin/includes/file.php';

            // Initialize the WP Filesystem
            global $wp_filesystem;
            if (!function_exists('WP_Filesystem')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }
            $creds = request_filesystem_credentials(site_url() . '/wp-admin/', '', false, false, []);
            if (!WP_Filesystem($creds)) {
                return false;
            }

            // Delete the existing file if it exists
            if ($wp_filesystem->exists($xagio_location)) {
                $wp_filesystem->delete($xagio_location);
            }

            // Download the file using wp_remote_get
            $xagio_response = wp_remote_get($xagio_file, [
                'timeout'  => 60,
                'stream'   => true,
                'filename' => $xagio_location
            ]);

            // Check for errors
            if (is_wp_error($xagio_response)) {
                return false;
            }

            return true;
        }

        /***************************************************************************************************************
         *
         *   API Functions
         *
         **************************************************************************************************************/

        public static function createProjectPlannerGroups($request = null)
        {
            if ($request === null) {
                xagio_json('error', 'Invalid request.');
            }

            $body_params = $request->get_body_params();
            if (!is_array($body_params)) {
                $body_params = [];
            }

            $project_name_raw = '';
            $query_param      = $body_params['query'] ?? $request->get_param('query');
            if (is_scalar($query_param)) {
                $project_name_raw = (string)$query_param;
            }

            if ($project_name_raw === '') {
                $keyword_param  = $body_params['keyword'] ?? $request->get_param('keyword');
                $location_param = $body_params['location'] ?? $request->get_param('location');

                if (is_scalar($keyword_param) || is_scalar($location_param)) {
                    $keyword          = is_scalar($keyword_param) ? (string)$keyword_param : '';
                    $xagio_location         = is_scalar($location_param) ? (string)$location_param : '';
                    $project_name_raw = trim($keyword . ' ' . $xagio_location);
                }
            }

            if (!is_string($project_name_raw)) {
                $project_name_raw = '';
            }

            $project_name_raw       = wp_unslash($project_name_raw);
            $project_name           = sanitize_text_field($project_name_raw);
            $project_name_defaulted = false;
            $default_project_name   = 'Project Planner ' . gmdate('Y-m-d H:i:s');

            if ($project_name === '') {
                $project_name           = $default_project_name;
                $project_name_defaulted = true;
            }

            $groups_param = $body_params['groups'] ?? $request->get_param('groups');

            $homepage_group_param = $body_params['homepage_group'] ?? $request->get_param('homepage_group');
            $homepage_group_name  = '';

            if (is_string($homepage_group_param)) {
                $homepage_group_name = sanitize_text_field(wp_unslash($homepage_group_param));
            }

            $homepage_group_id = 0;

            if (is_string($groups_param)) {
                $decoded = json_decode(wp_unslash($groups_param), true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    $groups_param = $decoded;
                }
            }

            if (!is_array($groups_param)) {
                $payload = $request->get_json_params();
                if (is_array($payload)) {
                    if ($project_name_defaulted && isset($payload['query']) && is_string($payload['query'])) {
                        $project_name_raw = wp_unslash($payload['query']);
                        $sanitized_name   = sanitize_text_field($project_name_raw);
                        if ($sanitized_name !== '') {
                            $project_name           = $sanitized_name;
                            $project_name_defaulted = false;
                        }
                    }
                    if (isset($payload['groups']) && is_array($payload['groups'])) {
                        $groups_param = $payload['groups'];
                    }
                }
            }

            if (!is_array($groups_param)) {
                xagio_json('error', 'Groups data missing from request payload.');
            }

            global $wpdb;

            $project_inserted = $wpdb->insert('xag_projects', [
                'project_name' => $project_name,
                'date_created' => gmdate('Y-m-d H:i:s'),
            ]);

            if ($project_inserted === false) {
                xagio_json('error', 'Failed to create a new project.');
            }

            $project_id        = (int)$wpdb->insert_id;
            $created_group_ids = [];
            $current_date      = gmdate('Y-m-d H:i:s');

            foreach ($groups_param as $xagio_group) {
                if (!is_array($xagio_group)) {
                    continue;
                }

                $group_name_raw = isset($xagio_group['group_name']) && is_string($xagio_group['group_name']) ? $xagio_group['group_name'] : '';
                $group_name     = sanitize_text_field(wp_unslash($group_name_raw));

                if ($group_name === '') {
                    continue;
                }

                $group_inserted = $wpdb->insert('xag_groups', [
                    'project_id'   => $project_id,
                    'group_name'   => $group_name,
                    'date_created' => $current_date,
                ]);

                if ($group_inserted === false) {
                    continue;
                }

                $group_id = (int)$wpdb->insert_id;

                if ($group_id > 0) {
                    $created_group_ids[] = $group_id;
                }

                if ($homepage_group_name !== '' && $group_id > 0 && strcasecmp($group_name, $homepage_group_name) === 0) {
                    $homepage_group_id = $group_id;
                }

                if (empty($xagio_group['keywords']) || !is_array($xagio_group['keywords'])) {
                    continue;
                }

                foreach ($xagio_group['keywords'] as $keyword) {

                    $keyword_name   = sanitize_text_field(wp_unslash($keyword['keyword']));
                    $keyword_volume = absint(wp_unslash($keyword['search_volume']));
                    $keyword_cpc    = (float)number_format((float)wp_unslash($keyword['cpc']), 2, '.', '');


                    if ($keyword_name === '') {
                        continue;
                    }

                    $wpdb->insert('xag_keywords', [
                        'group_id'     => $group_id,
                        'keyword'      => $keyword_name,
                        'volume'       => $keyword_volume,
                        'cpc'          => $keyword_cpc,
                        'date_created' => $current_date,
                    ]);
                }
            }

            if (empty($created_group_ids)) {
                $wpdb->delete('xag_projects', ['id' => $project_id]);
                xagio_json('error', 'No valid groups were provided in the request payload.');
            }

            if ($homepage_group_name !== '' && $homepage_group_id === 0) {
                $homepage_group_id = (int)$wpdb->get_var(
                    $wpdb->prepare(
                        'SELECT id FROM xag_groups WHERE project_id = %d AND group_name = %s ORDER BY id ASC LIMIT 1',
                        $project_id,
                        $homepage_group_name
                    )
                );
            }

            if ($homepage_group_id > 0) {
                set_transient('xagio_agentx_homepage_group_id', $homepage_group_id, HOUR_IN_SECONDS);
            }

            xagio_json('success', 'Project planner groups created successfully.', [
                'project_id' => $project_id,
            ]);
        }

        public static function getTopTenDomainsAgentX($request = null)
        {
            // Check if the 'slug' parameter is set in the POST request
            if (empty($request->get_param('main-keyword')) || empty($request->get_param('location')) || empty($request->get_param('keyword'))) {
                xagio_json('error', 'Invalid request!');
            }

            $main_keyword = sanitize_text_field(wp_unslash($_POST['main-keyword']));
            $xagio_location     = sanitize_text_field(wp_unslash($_POST['location']));
            $keyword      = sanitize_text_field(wp_unslash($_POST['keyword']));

            if (isset($_POST['search_engine'])) {
                $search_engine = sanitize_text_field(wp_unslash($_POST['search_engine']));
            } else {
                $search_engine = '14';
            }
            if (isset($_POST['search_engine_text'])) {
                $search_engine_text = sanitize_text_field(wp_unslash($_POST['search_engine_text']));
            } else {
                $search_engine_text = 'google.com (United States/English)';
            }
            if (isset($_POST['search_location'])) {
                $search_location = sanitize_text_field(wp_unslash($_POST['search_location']));
            } else {
                $search_location = '2840';
            }
            if (isset($_POST['search_location_text'])) {
                $search_location_text = sanitize_text_field(wp_unslash($_POST['search_location_text']));
            } else {
                $search_location_text = 'United States';
            }

            $listings = [
                "facebook.com",
                "google.com",
                "facebook.com",
                "instagram.com",
                "linkedin.com",
                "apple.com",
                "yelp.com",
                "bing.com",
                "bbb.org",
                "mapquest.com",
                "foursquare.com",
                "angi.com",
                "thumbtack.com",
                "yellowpages.com",
                "nextdoor.com",
                "manta.com",
                "merchantcircle.com",
                "yellowbook.com",
                "chamberofcommerce.com",
                "dandb.com",
                "brownbook.net",
                "partners.local.com",
                "turbify.com",
                "dashboard.ezlocal.com",
                "elocal.com",
                "ebusinesspages.com",
                "citysquares.com",
                "local.botw.org",
                "ibegin.com",
                "neustarlocaleze.biz",
                "spoke.com",
                "golocal247.com",
                "callupcontact.com",
                "n49.com",
                "cybo.com",
                "directory.justlanded.com",
                "tuugo.us",
                "lacartes.com",
                "citylocalpro.com",
                "yellow.place",
                "hub.biz",
                "cylex.us.com",
                "fyple.com",
                "opendi.us",
                "expressbusinessdirectory.com",
                "myhuckleberry.com",
                "bizhwy.com",
                "dirjournal.com",
                "usdirectory.com",
                "finduslocal.com"
            ];

            update_option('XAGIO_ONBOARDING_LOCATION', $xagio_location);
            update_option('XAGIO_ONBOARDING_KEYWORD', $keyword);
            update_option('XAGIO_ONBOARDING_MAIN_KEYWORD', $main_keyword);
            update_option('XAGIO_AI_WIZARD_TOP_TEN', serialize([
                'search_engine'        => $search_engine,
                'search_engine_text'   => $search_engine_text,
                'search_location'      => $search_location,
                'search_location_text' => $search_location_text
            ]));

            $xagio_http_code = 0;
            $xagio_result    = self::apiRequest(
                $endpoint = 'find_top_ten_domains_free', $method = 'POST', [
                'keyword' => $main_keyword,
                'se_id'   => $search_engine ?? '14',
                'loc_id'  => $search_location ?? '2840',
                'ip'      => XAGIO_MODEL_LOG404::getIp()
            ], $xagio_http_code
            );

            if ($xagio_http_code == 403) {
                xagio_json('error', $xagio_result['message'] ?? "Oups, something happened, please contact support.");
            }

            if (isset($xagio_result['data']) && sizeof($xagio_result['data']) > 0) {
                $websites = $xagio_result['data'];
                $OUT      = [];

                foreach ($websites as $website) {
                    $path                   = wp_parse_url($website['url'], PHP_URL_PATH);
                    $website['recommended'] = false;
                    if (is_null($path)) {
                        $website['recommended'] = true;
                    } else {
                        if (strlen($path) <= 1) {
                            $website['recommended'] = true;
                        }
                    }

                    $website['host'] = wp_parse_url($website['url'], PHP_URL_HOST);

                    $website['listing'] = false;

                    $host_check = str_replace('www.', '', $website['host']);
                    if (in_array($host_check, $listings)) {
                        $website['listing'] = true;
                    }

                    $OUT[] = $website;
                }

                xagio_jsonc([
                    'status' => 'success',
                    'data'   => $OUT
                ]);
            }

        }

        /**
         *  Install Plugin or Theme from Upload
         */

        public static function installFromUpload($request = null)
        {
            // Check if required POST parameters are set
            if (empty($request->get_param('slug')) || empty($request->get_param('type')) || empty($request->get_param('package'))) {
                xagio_json('error', 'Invalid request!');
            }

            // Sanitize input data
            $slug    = sanitize_text_field(wp_unslash($request->get_param('slug')));
            $type    = sanitize_text_field(wp_unslash($request->get_param('type')));
            $package = esc_url_raw(wp_unslash($request->get_param('package')));

            // Validate the type (either 'plugins' or 'themes')
            if (!in_array($type, [
                'plugins',
                'themes'
            ], true)) {
                xagio_json('error', 'Invalid type specified!');
            }

            // Handle the downloaded file
            $root_directory = get_home_path();
            $plugin_path    = $root_directory . sanitize_file_name($slug) . '.zip';

            // Download the file
            if (!XAGIO_API::downloadFile($plugin_path, $package)) {
                xagio_json('error', 'Failed to download the package.');
            }

            $xagio_result = false;
            $error  = '';

            // Install the plugin or theme based on the type
            if ($type === 'plugins') {
                $xagio_result = XAGIO_MODEL_QUICKWPSETUP::installWordPressPlugin($slug, $plugin_path, $error);
                if ($xagio_result) {
                    @activate_plugin($xagio_result);
                }
            } elseif ($type === 'themes') {
                $xagio_result = XAGIO_MODEL_QUICKWPSETUP::installWordPressTheme($slug, $plugin_path, $error);
            }

            // Handle the installation result
            if (!$xagio_result) {
                xagio_json('error', 'Managed to upload, but failed to install specified file.', $error);
            } else {
                xagio_json('success', 'Successfully installed specified file.');
                self::syncWithPanel();
            }
        }


        /**
         *  Install Plugins from WordPress Repository
         */
        public static function installPluginFromRepo($request = null)
        {

            // Check if the 'slug' parameter is set in the POST request
            if (!!empty($request->get_param('slug'))) {
                xagio_json('error', 'Invalid request!');
            }

            // Sanitize the slug
            $slug = sanitize_text_field(wp_unslash($request->get_param('slug')));

            // Download the plugin from the WordPress repository
            $plugin_path = XAGIO_MODEL_QUICKWPSETUP::downloadWordPressPlugin($slug);
            if (!$plugin_path) {
                xagio_json('error', 'Failed to download specified plugin.');
            } else {
                // Attempt to install the downloaded plugin
                $xagio_result = XAGIO_MODEL_QUICKWPSETUP::installWordPressPlugin($slug, $plugin_path);
                if (!$xagio_result) {
                    xagio_json('error', 'Managed to download, but failed to install specified plugin.');
                } else {
                    // Activate the plugin after successful installation
                    @activate_plugin($xagio_result);
                    xagio_json('success', 'Successfully installed specified plugin.');
                    self::syncWithPanel();
                }
            }
        }


        /**
         *  Install Themes from WordPress Repository
         */
        public static function installThemeFromRepo($request = null)
        {


            // Check if the 'slug' parameter is set in the POST request
            if (!!empty($request->get_param('slug'))) {
                xagio_json('error', 'Invalid request!');
            }

            // Sanitize the slug
            $slug = sanitize_text_field(wp_unslash($request->get_param('slug')));

            // Download the theme from the WordPress repository
            $theme_path = XAGIO_MODEL_QUICKWPSETUP::downloadWordPressTheme($slug);
            if (!$theme_path) {
                xagio_json('error', 'Failed to download specified theme.');
            } else {
                // Attempt to install the downloaded theme
                $xagio_result = XAGIO_MODEL_QUICKWPSETUP::installWordPressTheme($slug, $theme_path);
                if (!$xagio_result) {
                    xagio_json('error', 'Managed to download, but failed to install specified theme.');
                } else {
                    xagio_json('success', 'Successfully installed specified theme.');
                    self::syncWithPanel();
                }
            }
        }


        /**
         *   Restore a Backup
         */
        public static function restoreBackup($request = null)
        {


            // Sanitize and validate the input data
            $storage   = !empty($request->get_param('storage')) ? sanitize_text_field(wp_unslash($request->get_param('storage'))) : '';
            $xagio_backup    = !empty($request->get_param('backup')) ? sanitize_text_field(wp_unslash($request->get_param('backup'))) : '';
            $backup_id = !empty($request->get_param('backup_id')) ? intval($request->get_param('backup_id')) : 0;

            // Validate that required parameters are provided
            if (empty($storage) || empty($xagio_backup) || $backup_id === 0) {
                xagio_json('error', 'Invalid request parameters.');
                return;
            }

            // Since this is async, store the result
            $xagio_result = XAGIO_MODEL_BACKUPS::restoreBackupHandler($storage, $xagio_backup, $backup_id);

            // Send the notification to the panel
            xagio_jsonc($xagio_result);
        }

        /**
         *   Create a Backup for Cloning purposes
         */
        public static function createCloneBackup($request = null)
        {
            xagio_jsonc(XAGIO_MODEL_BACKUPS::doCloneBackup());
        }

        /**
         *   Download cloned backup
         */
        public static function removeCloneBackup($request = null)
        {


            // Sanitize the backup name
            $backup_name = !empty($request->get_param('backup_name')) ? sanitize_file_name(wp_unslash($request->get_param('backup_name'))) : '';

            // Construct the backup path
            $backup_path = XAGIO_PATH . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . $backup_name;

            // Check if the backup file exists and is a file
            if (!empty($backup_name) && file_exists($backup_path) && is_file($backup_path)) {
                wp_delete_file($backup_path);
                xagio_json('success', 'Successfully removed backup file!');
            } else {
                xagio_json('error', 'Specified backup file does not exist or is not a valid file!');
            }
        }

        /**
         *   Create a Backup manually
         */
        public static function createBackup($request = null)
        {
            xagio_jsonc(XAGIO_MODEL_BACKUPS::doBackup());
        }

        /**
         * Set Backup Limit
         */
        public static function setBackupLimit($request = null)
        {


            XAGIO_SYNC::getBackupSettings();

            // Sanitize and validate the backup limit
            $backup_limit = !empty($request->get_param('backup_limit')) ? intval($request->get_param('backup_limit')) : 0;

            if ($backup_limit > 0) {
                update_option('XAGIO_BACKUP_LIMIT', $backup_limit);
                xagio_json('success', 'Backup Limit has been updated!');
            } else {
                xagio_json('error', 'Invalid Backup Limit value!');
            }
        }

        /**
         * Set Backup Location
         */
        public static function setBackupLocation($request = null)
        {


            XAGIO_SYNC::getBackupSettings();

            // Sanitize the backup location
            $backup_location = !empty($request->get_param('backup_location')) ? sanitize_text_field(wp_unslash($request->get_param('backup_location'))) : '';

            if (!empty($backup_location)) {
                update_option('XAGIO_BACKUP_LOCATION', $backup_location);
                xagio_json('success', 'Backup Storage has been updated!');
            } else {
                xagio_json('error', 'Invalid Backup Location value!');
            }
        }


        /**
         * Set Backup Date
         */
        public static function setBackupDate($request = null)
        {
            // Sanitize the backup date
            $backup_date = !empty($request->get_param('backup_date')) ? sanitize_text_field(wp_unslash($request->get_param('backup_date'))) : '';

            if (!empty($backup_date)) {
                update_option('XAGIO_BACKUP_DATE', $backup_date);

                // Init the cronjob
                wp_unschedule_event(wp_next_scheduled('xagio_doBackup'), 'xagio_doBackup');

                if ($backup_date !== 'never') {
                    if (!wp_next_scheduled('xagio_doBackup')) {
                        XAGIO_SYNC::getBackupSettings();
                        wp_schedule_event(time(), $backup_date, 'xagio_doBackup');
                        XAGIO_SYNC::updateBackupSettings();
                    }
                }

                xagio_json('success', 'Backup Schedule has been updated!');
            } else {
                xagio_json('error', 'Invalid Backup Date value!');
            }
        }

        /**
         * Deactivate Plugin - From Panel
         * This will only deactivate plugin
         */
        public static function deactivatePlugin($request = null)
        {
            deactivate_plugins("xagio-seo/xagio-seo.php");
            xagio_json('success', 'Plugin has been successfully deactivated!');
        }


        /**
         *   Hidden Plugin Status
         */
        public static function getPluginHiddenStatus()
        {
            $status = get_option('XAGIO_HIDDEN');
            xagio_json('success', 'Successfully retrieved data.', $status);
        }

        /**
         *   Hide Plugin
         */
        public static function hidePlugin($request = null)
        {
            update_option('XAGIO_HIDDEN', TRUE);
            xagio_json('success', 'Plugin has been successfully hidden from Admin Area!');
        }

        /**
         *   Show Plugin
         */
        public static function showPlugin($request = null)
        {
            update_option('XAGIO_HIDDEN', FALSE);
            xagio_json('success', 'Plugin has been successfully shown on Admin Area!');
        }

        /**
         * Toggle Schema Force ON
         */
        public static function toggleSchemaAlwaysOn($request = null)
        {


            // Sanitize and validate the input value
            $xagio_value = !empty($request->get_param('value')) ? intval($request->get_param('value')) : 0;

            // Update the option
            update_option('XAGIO_SCHEMA_ALWAYS_ON', $xagio_value);

            // Provide a success message based on the value
            if ($xagio_value === 1) {
                xagio_json('success', 'Force Homepage Schemas has been enabled!');
            } else {
                xagio_json('success', 'Force Homepage Schemas has been disabled!');
            }
        }


        /**
         * Toggle reCAPTCHA
         */
        public static function toggleRecaptcha($request = null)
        {
            $xagio_value = !empty($request->get_param('value')) ? intval($request->get_param('value')) : 0;
            update_option('XAGIO_RECAPTCHA', $xagio_value);
            if ($xagio_value === 1) {
                XAGIO_SYNC::getAPIKeys();
                xagio_json('success', 'reCAPTCHA has been enabled!');
            } else {
                xagio_json('success', 'reCAPTCHA has been disabled!');
            }
        }

        /**
         * reCAPTCHA status
         */
        public static function recaptchaStatus()
        {
            $status = get_option('XAGIO_RECAPTCHA');
            xagio_json('success', 'Successfully retrieved data.', $status);
        }

        public static function wipePlugin($request = null)
        {
            XAGIO_LICENSE::removeLicense();
            xagio_json('success', 'Plugin has been successfully wiped!');
        }

        /**
         * Download WordPress Plugin to Panel
         */
        public static function downloadPlugin($request = null)
        {
            try {
                // Check if plugin name is set
                if (empty($request->get_param('plugin'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $plugin_slug_with_file = sanitize_text_field(wp_unslash($request->get_param('plugin')));
                $plugin_slug_parts     = explode('/', $plugin_slug_with_file); // Split by '/' to extract the directory
                $plugin_slug           = $plugin_slug_parts[0]; // The first part is the directory name

                $temp_dir   = XAGIO_PATH . '/tmp/';
                $plugin_dir = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin_slug . DIRECTORY_SEPARATOR;
                $zip_name   = basename($plugin_slug);
                $zip_path   = $temp_dir . $zip_name . '.zip';


                // Check if temp dir exists, create if not
                if (!file_exists($temp_dir)) {
                    xagio_mkdir($temp_dir, 0777, true);
                }

                // Validate plugin directory
                if (!file_exists($plugin_dir) || !is_dir($plugin_dir)) {
                    xagio_json('error', 'Plugin directory does not exist or is not a valid directory!');
                }

                // Check if ZipArchive is available
                if (!class_exists('ZipArchive')) {
                    xagio_json('error', 'ZipArchive is not installed.');
                }

                // Initialize ZipArchive
                $archive = new ZipArchive();
                if ($archive->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
                    xagio_json('error', 'Cannot create zip archive! Ensure write permissions are set.');
                }

                // Add plugin files to the ZIP archive
                $xagio_files = new RecursiveIteratorIterator(
                    new RecursiveDirectoryIterator($plugin_dir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST
                );

                foreach ($xagio_files as $xagio_file) {
                    $file_path     = $xagio_file->getRealPath();
                    $xagio_relative_path = substr($file_path, strlen($plugin_dir));
                    if ($xagio_file->isDir()) {
                        $archive->addEmptyDir($plugin_slug . '/' . $xagio_relative_path);
                    } else {
                        $archive->addFile($file_path, $plugin_slug . '/' . $xagio_relative_path);
                    }
                }

                $archive->close();

                // Check if the zipping has been successful
                if (!file_exists($zip_path)) {
                    xagio_json('error', 'Failed to create zip file from plugin directory!');
                }

                // Upload the zipped plugin
                $xagio_result = XAGIO_API::apiRequestUpload('plugins_upload', $zip_path);
                if ($xagio_result && !empty($xagio_result['message'])) {
                    xagio_json('success', $xagio_result['message']);
                } else {
                    xagio_json('error', 'Failed to upload the plugin zip file.');
                }
            } catch (Exception $e) {
                xagio_json('error', 'An error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }


        /**
         * Activate WordPress Plugins
         */
        public static function activateWpPlugins($request = null)
        {


            try {
                // Check if plugin names are set
                if (empty($request->get_param('pluginNames'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $plugins     = sanitize_text_field(wp_unslash($request->get_param('pluginNames')));
                $pluginNames = is_array($plugins) ? array_map('sanitize_text_field', wp_unslash($plugins)) : [sanitize_text_field(wp_unslash($plugins))];

                $error   = [];
                $success = [];

                foreach ($pluginNames as $pluginName) {
                    $xagio_result = activate_plugin($pluginName);
                    if (is_wp_error($xagio_result)) {
                        $error[] = $pluginName;
                    } else {
                        $success[] = $pluginName;
                    }
                }

                $error_status = !empty($error);

                xagio_json('success', 'Operation successfully finished.', [
                    'success'      => $success,
                    'error'        => $error,
                    'error_status' => $error_status
                ]);
            } catch (Exception $e) {
                xagio_json('error', 'Plugin error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }

        /**
         * Deactivate WordPress Plugins - From Panel
         */
        public static function deactivateWpPlugins($request = null)
        {


            try {
                // Check if plugin names are set
                if (empty($request->get_param('pluginNames'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $plugins     = map_deep(wp_unslash($request->get_param('pluginNames')), 'sanitize_text_field');
                $pluginNames = is_array($plugins) ? array_map('sanitize_text_field', wp_unslash($plugins)) : [sanitize_text_field(wp_unslash($plugins))];

                foreach ($pluginNames as $pluginName) {
                    deactivate_plugins($pluginName);
                }

                xagio_json('success', 'Operation successfully finished.');
            } catch (Exception $e) {
                xagio_json('error', 'Plugin error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }

        /**
         * Delete WordPress Plugins
         */
        public static function deleteWpPlugins($request = null)
        {


            try {
                // Check if plugin names are set
                if (empty($request->get_param('pluginNames'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $plugins     = sanitize_text_field(wp_unslash($request->get_param('pluginNames')));
                $pluginNames = is_array($plugins) ? array_map('sanitize_text_field', wp_unslash($plugins)) : [sanitize_text_field(wp_unslash($plugins))];

                require_once ABSPATH . 'wp-admin/includes/plugin.php';
                require_once ABSPATH . 'wp-admin/includes/file.php';

                $status = delete_plugins($pluginNames);

                xagio_json('success', 'Operation successfully finished.', $status);
            } catch (Exception $e) {
                xagio_json('error', 'Plugin error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }

        /**
         * Activate WordPress Theme
         */
        public static function activateWpTheme($request = null)
        {


            try {
                // Check if theme slug is set
                if (empty($request->get_param('slug'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $slug  = sanitize_text_field(wp_unslash($request->get_param('slug')));
                $theme = wp_get_theme($slug);

                if ($theme->exists()) {
                    switch_theme($slug);
                    xagio_json('success', 'Theme successfully changed.');
                } else {
                    xagio_json('error', 'Theme doesn\'t exist.');
                }
            } catch (Exception $e) {
                xagio_json('error', 'An error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }

        /**
         * Download WordPress Theme to Panel
         */
        public static function downloadTheme($request = null)
        {
            try {
                // Check if theme name is set
                if (empty($request->get_param('theme'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $theme_slug = sanitize_text_field(wp_unslash($request->get_param('theme')));
                $temp_dir   = XAGIO_PATH . '/tmp/';

                // Create temp directory if it doesn't exist
                if (!file_exists($temp_dir)) {
                    xagio_mkdir($temp_dir, 0777, true);
                }

                $theme_dir = get_theme_root() . DIRECTORY_SEPARATOR . $theme_slug . DIRECTORY_SEPARATOR;
                $zip_name  = basename($theme_slug);
                $zip_path  = $temp_dir . $zip_name . '.zip';

                // Validate theme directory
                if (!file_exists($theme_dir) || !is_dir($theme_dir)) {
                    xagio_json('error', 'Theme directory does not exist or is not a valid directory!');
                }

                if (!class_exists('ZipArchive')) {
                    xagio_json('error', 'ZipArchive is not installed.');
                }

                // Initialize ZipArchive
                $archive = new ZipArchive();
                if ($archive->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
                    xagio_json('error', 'Cannot create zip archive! Ensure write permissions are set.');
                }

                // Add theme files to the ZIP archive
                $xagio_files = new RecursiveIteratorIterator(
                    new RecursiveDirectoryIterator($theme_dir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST
                );

                foreach ($xagio_files as $xagio_file) {
                    $file_path     = $xagio_file->getRealPath();
                    $xagio_relative_path = substr($file_path, strlen($theme_dir));
                    if ($xagio_file->isDir()) {
                        $archive->addEmptyDir($theme_slug . '/' . $xagio_relative_path);
                    } else {
                        $archive->addFile($file_path, $theme_slug . '/' . $xagio_relative_path);
                    }
                }

                $archive->close();

                // Check if the zipping was successful
                if (!file_exists($zip_path)) {
                    xagio_json('error', 'Failed to create zip file out of theme directory!');
                }

                // Upload the zipped theme
                $xagio_result = XAGIO_API::apiRequestUpload('themes_upload', $zip_path);
                if ($xagio_result && !empty($xagio_result['message'])) {
                    xagio_json('success', $xagio_result['message']);
                } else {
                    xagio_json('error', 'Failed to upload the theme zip file.');
                }
            } catch (Exception $e) {
                xagio_json('error', 'An error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }


        /**
         * Remote Login
         */
        public static function remoteLogin( $request = null ) {

            if ( is_user_logged_in() ) {
                xagio_redirect( admin_url( 'admin.php?page=xagio-dashboard' ) );
                exit;
            }

            // Pick a target user: requested ID (if valid) or first administrator.
            $target_user = null;

            $requested_id = 0;
            if ( $request && method_exists( $request, 'get_param' ) ) {
                $requested_id = absint( $request->get_param( 'ID' ) );
            }

            if ( $requested_id ) {
                $u = get_userdata( $requested_id );
                if ( $u instanceof WP_User ) {
                    $target_user = $u;
                }
            }

            if ( ! $target_user ) {
                $admins = get_users( [
                    'role'   => 'administrator',
                    'fields' => [ 'ID' ],
                    'number' => 1,
                ] );

                if ( empty( $admins ) ) {
                    xagio_json( 'error', 'No administrator user found.' );
                    return;
                }

                $target_user = get_userdata( (int) $admins[0]->ID );
            }

            if ( ! ( $target_user instanceof WP_User ) ) {
                xagio_json( 'error', 'User not found.' );
                return;
            }

            // Optional: only allow admin users (defensive)
            if ( ! user_can( $target_user, 'administrator' ) ) {
                xagio_json( 'error', 'User is not an administrator.' );
                return;
            }

            // Log in (WP will handle cookies/session)
            wp_set_current_user( $target_user->ID );
            wp_set_auth_cookie( $target_user->ID, true, is_ssl() );

            // Use your own prefixed hook if you need to notify internal code
            do_action( 'xagio_remote_login', $target_user );

            // Clean up token
            delete_transient( 'xagio_remoteLoginToken' );

            xagio_redirect( admin_url() );
            exit;
        }



        /**
         *   Get Temp Token
         */
        public static function getTempToken($request = null)
        {
            set_transient('xagio_remoteLoginToken', md5(gmdate('Y-m-d H:i:s') . microtime() . XAGIO_AUTH_KEY . XAGIO_AUTH_SALT), 30);

            //Get all admin Users
            $users = get_users([
                'role'   => 'administrator',
                'fields' => [
                    'ID',
                    'user_login'
                ],
            ]);

            $xagio_response                           = [];
            $xagio_response['xagio_remoteLoginToken'] = get_transient('xagio_remoteLoginToken');
            $xagio_response['remoteLoginUsers']       = $users;

            xagio_json('success', $xagio_response);
        }

        /**
         *   Get Available Updates
         * @param boolean $array Set crone to true to return array
         * @return void|array
         */
        public static function getUpdates($array = FALSE)
        {
            // Ensure that update functions are available
            if (!function_exists('get_core_updates')) {
                require_once(ABSPATH . 'wp-admin/includes/update.php');
            }

            set_site_transient('update_plugins', new stdClass());
            set_site_transient('update_themes', new stdClass());

            wp_update_plugins(array());
            wp_update_themes(array());

            // Skip paid plugins/themes
            $plugins_raw = get_plugin_updates();
            $themes_raw  = get_theme_updates();

            $plugins = [];
            $themes  = [];

            foreach ($plugins_raw as $plugin => $data) {
                if (!empty($data->update)) {
                    if (!empty($data->update->package)) {
                        $plugins[$plugin] = $data;
                    }
                }
            }

            foreach ($themes_raw as $theme => $data) {
                if (!empty($data->update)) {
                    if (!empty($data->update['package'])) {
                        $themes[$theme] = $data;
                    }
                }
            }

            $data = [
                'core'    => get_core_updates(),
                'plugins' => $plugins,
                'themes'  => $themes
            ];

            /*Returning results*/
            if ($array === TRUE) {
                return $data;
            } else {
                xagio_json('success', 'Successfully retrieved updates.', $data);
            }
        }

        /**
         * get plugins update if site_transient not work in get_plugin_updates wp function
         * @return array
         */
        public static function get_plugins_update($request = null)
        {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';

            $all_plugins     = get_plugins();
            $upgrade_plugins = [];
            $current         = get_option('_site' . '_transient_update' . '_plugins');
            foreach ((array)$all_plugins as $plugin_file => $plugin_data) {
                if (!empty($current->response[$plugin_file])) {
                    $upgrade_plugins[$plugin_file]         = (object)$plugin_data;
                    $upgrade_plugins[$plugin_file]->update = $current->response[$plugin_file];
                }
            }
            return $upgrade_plugins;
        }

        /**
         *   Get Plugins & Themes
         * @param boolean $array Set crone to true to return array
         * @return void|array
         */
        public static function getPluginsThemes($array = FALSE)
        {
            require_once ABSPATH . 'wp-admin/includes/theme.php';
            require_once ABSPATH . 'wp-admin/includes/plugin.php';

            $themes       = wp_get_themes();
            $themes_temp  = [];
            $themes2_temp = [];
            $themes3_temp = [];
            foreach ($themes as $xagio_key => $xagio_value) {
                $screenshot          = $xagio_value->get_screenshot();
                $xagio_value               = (array)$xagio_value;
                $xagio_value['screenshot'] = $screenshot;
                $themes_temp[$xagio_key]   = $xagio_value;
            }
            foreach ($themes_temp as $xagio_key => $theme) {
                if (!!empty($themes2_temp[$xagio_key])) {
                    $themes2_temp[$xagio_key] = [];
                }
                foreach ($theme as $xagio_k => $v) {
                    $xagio_k                      = str_replace('WP_Theme', '', $xagio_k);
                    $xagio_k                      = preg_replace('/[^A-Za-z0-9\-]/', '', $xagio_k);
                    $themes2_temp[$xagio_key][$xagio_k] = $v;
                }
            }
            foreach ($themes2_temp as $xagio_key => $theme) {
                $theme['headers']['screenshot'] = $theme['screenshot'];
                $themes3_temp[$xagio_key]             = $theme['headers'];
            }

            $data = [
                'plugins' => get_plugins(),
                'themes'  => $themes3_temp,
            ];
            /*Returning results*/
            if ($array === TRUE) {
                return $data;
            } else {
                xagio_json('success', 'Successfully retrieved plugins and themes.', $data);
            }
        }

        /**
         *   Get blog info
         * @param boolean $array Set crone to true to return array
         * @return void|array
         */
        public static function getBlogInfo($array = FALSE)
        {
            $data = [
                'name'        => get_bloginfo('name'),
                'description' => get_bloginfo('description'),
                'admin_email' => get_bloginfo('admin_email'),
                'version'     => get_bloginfo('version'),
            ];
            /*Returning results*/
            if ($array === TRUE) {
                return $data;
            } else {
                xagio_json('success', 'Successfully retrieved blog info.', $data);
            }
        }

        /**
         *  Sync comments
         * @param boolean $array Set to true to return array
         * @return void|array
         */
        public static function getComments($array = FALSE)
        {

            $pending_coments = get_comments([
                'status' => 'hold',
                'number' => 2000
            ]);
            $spam_comments   = get_comments([
                'status' => 'spam',
                'number' => 2000
            ]);

            $data = array_merge($pending_coments, $spam_comments);

            $comments = [];
            foreach ($data as $comment) {

                $comments[] = [
                    'name'           => $comment->comment_author,
                    'comment'        => $comment->comment_content,
                    'comment_id'     => $comment->comment_ID,
                    'comment_status' => $comment->comment_approved,
                    'page_id'        => $comment->comment_post_ID,
                    'date'           => $comment->comment_date,
                ];

            }

            /*Returning results*/
            if ($array === TRUE) {
                return $comments;
            } else {
                xagio_json('success', 'Successfully retrieved comments.', $comments);
            }

        }

        /**
         * Delete all unapproved and spam comments
         */
        public static function deleteAllComments($request = null)
        {
            global $wpdb;

            // Fetch pending comments
            $comments_to_delete = get_comments([
                'status' => '',
                'number' => 10000
            ]);

            // Merge comments to delete
            //            $comments_to_delete = array_merge($pending_comments, $spam_comments);

            // If there are comments to delete, proceed with deletion
            if (!empty($comments_to_delete)) {
                $comment_ids             = wp_list_pluck($comments_to_delete, 'comment_ID');
                $comment_ids_placeholder = implode(',', array_fill(0, count($comment_ids), '%d'));

                // Prepare and execute the deletion query
                $deleted = $wpdb->query(
                    $wpdb->prepare(
                        "DELETE FROM {$wpdb->prefix}comments WHERE comment_ID IN ($comment_ids_placeholder)", ...$comment_ids
                    )
                );

                if ($deleted) {
                    xagio_json('success', 'Successfully deleted comments.');
                } else {
                    xagio_json('error', 'Could not delete comments at the moment.');
                }
            } else {
                xagio_json('error', 'No comments to delete.');
            }
        }

        /**
         * Delete all spam comments
         */
        public static function deleteAllSpamComments($request = null)
        {
            global $wpdb;

            // Fetch all spam comments
            $spam_comments = get_comments([
                'status' => 'spam',
                'number' => 10000
            ]);

            if (!empty($spam_comments)) {
                // Extract comment IDs
                $comment_ids             = wp_list_pluck($spam_comments, 'comment_ID');
                $comment_ids_placeholder = implode(',', array_fill(0, count($comment_ids), '%d'));

                // Prepare and execute the deletion query
                $deleted = $wpdb->query(
                    $wpdb->prepare(
                        "DELETE FROM {$wpdb->prefix}comments WHERE comment_ID IN ($comment_ids_placeholder)", ...$comment_ids
                    )
                );

                if ($deleted) {
                    xagio_json('success', 'Successfully deleted spam comments.');
                } else {
                    xagio_json('error', 'Could not delete comments at the moment.');
                }
            } else {
                xagio_json('error', 'No spam comments to delete.');
            }
        }

        /**
         * Delete all trash comments
         */
        public static function deleteAllTrashComments($request = null)
        {
            global $wpdb;

            // Fetch all trash comments
            $trash_comments = get_comments([
                'status' => 'trash',
                'number' => 10000
            ]);

            if (!empty($trash_comments)) {
                // Extract comment IDs
                $comment_ids             = wp_list_pluck($trash_comments, 'comment_ID');
                $comment_ids_placeholder = implode(',', array_fill(0, count($comment_ids), '%d'));

                // Prepare and execute the deletion query
                $deleted = $wpdb->query(
                    $wpdb->prepare(
                        "DELETE FROM {$wpdb->prefix}comments WHERE comment_ID IN ($comment_ids_placeholder)", ...$comment_ids
                    )
                );

                if ($deleted) {
                    xagio_json('success', 'Successfully deleted trash comments.');
                } else {
                    xagio_json('error', 'Could not delete comments at the moment.');
                }
            } else {
                xagio_json('error', 'No trash comments to delete.');
            }
        }


        /**
         *  Sync reviews
         * @param boolean $array Set crone to true to return array
         * @return void|array
         */
        public static function getReviews($array = FALSE)
        {
            global $wpdb;

            $results = $wpdb->get_results('SELECT * FROM xag_reviews', ARRAY_A);

            for ($xagio_i = 0; $xagio_i < sizeof($results); $xagio_i++) {
                if ($results[$xagio_i]['page_id'] !== 0) {
                    $results[$xagio_i]['page_name'] = get_the_title($results[$xagio_i]['page_id']);
                } else {
                    $results[$xagio_i]['page_name'] = 'Global Review';
                }
            }

            /*Returning results*/
            if ($array === TRUE) {
                return $results;
            } else {
                xagio_json('success', 'Successfully retrieved reviews.', $results);
            }

        }

        public static function getComment($request = null)
        {


            if (empty($request->get_param('comment_id'))) {
                xagio_json('error', 'Invalid request!');
            }

            $comment_id = intval($request->get_param('comment_id'));
            $comment    = get_comment($comment_id, ARRAY_A);

            if (!$comment) {
                xagio_json('error', 'Comment not found!');
            } else {
                xagio_json('success', 'Comment retrieved successfully.', $comment);
            }
        }

        public static function editComment($request = null)
        {


            if (empty($request->get_param('args')) || !is_array($request->get_param('args'))) {
                xagio_json('error', 'Invalid request!');
            }

            $xagio_args   = array_map('sanitize_text_field', wp_unslash($request->get_param('args')));
            $xagio_result = wp_update_comment($xagio_args);

            if ($xagio_result) {
                xagio_json('success', 'Comment edited successfully.');
            } else {
                xagio_json('error', 'Could not edit comment at the moment.');
            }
        }

        public static function replyOnComment($request = null)
        {


            if (empty($request->get_param('comment_id')) || empty($request->get_param('content'))) {
                xagio_json('error', 'Invalid request!');
            }

            $comment_id = intval($request->get_param('comment_id'));
            $xagio_content    = sanitize_textarea_field(wp_unslash($request->get_param('content')));

            $comment = get_comment($comment_id, ARRAY_A);

            if (!$comment) {
                xagio_json('error', 'Comment not found!');
            } else {
                $admins = get_users([
                    'role'   => 'administrator',
                    'fields' => ['ID'],
                ]);

                if (empty($admins)) {
                    xagio_json('error', 'No admin users found!');
                }

                $user_info = get_userdata($admins[0]->ID);

                $data = [
                    'comment_post_ID'      => $comment['comment_post_ID'],
                    'comment_author'       => $user_info->user_login,
                    'comment_author_email' => $user_info->user_email,
                    'comment_content'      => $xagio_content,
                    'comment_type'         => '',
                    'comment_parent'       => $comment['comment_ID'],
                    'user_id'              => $user_info->ID,
                    'comment_date'         => current_time('mysql'),
                ];

                $xagio_result = wp_insert_comment($data);

                if ($xagio_result) {
                    xagio_json('success', 'Successfully replied to comment.');
                } else {
                    xagio_json('error', 'Could not reply to comment at the moment.');
                }
            }
        }

        public static function updateComments($request = null)
        {


            global $wpdb;

            // Validate request
            if (empty($request->get_param('method')) || empty($request->get_param('comment_id'))) {
                xagio_json('error', 'Invalid request!');
            }

            $method      = sanitize_text_field(wp_unslash($request->get_param('method')));
            $comment_ids = is_array($request->get_param('comment_id')) ? array_map('intval', $request->get_param('comment_id')) : [intval($request->get_param('comment_id'))];

            $methods = [
                'PUT'    => 'approve',
                'POST'   => 'hold',
                'GET'    => 'spam',
                'DELETE' => 'trash',
            ];

            if (!array_key_exists($method, $methods)) {
                xagio_json('error', 'Invalid method!');
            }

            $status = $methods[$method];

            // Update comments in bulk or individually
            if (!empty($comment_ids)) {
                if (count($comment_ids) > 1) {
                    $xagio_placeholders = implode(',', array_fill(0, count($comment_ids), '%d'));
                    $xagio_result       = $wpdb->query(
                        $wpdb->prepare(
                            "UPDATE {$wpdb->prefix}comments SET comment_approved = %s WHERE comment_ID IN ($xagio_placeholders)", ...array_merge([$status], $comment_ids)
                        )
                    );
                } else {
                    $xagio_result = wp_set_comment_status($comment_ids[0], $status);
                }

                if ($xagio_result !== false) {
                    $message = 'Successfully ' . (($status === 'approve') ? 'approved' : (($status === 'hold') ? 'unapproved' : (($status === 'spam') ? 'moved to spam' : 'deleted'))) . ' comment(s).';
                    xagio_json('success', $message);
                } else {
                    xagio_json('error', 'Could not update comment(s) at the moment.');
                }
            } else {
                xagio_json('error', 'No valid comment IDs provided.');
            }
        }

        /**
         *   Get Posts
         * @param boolean $array Set cron to true to return array
         * @return void|array
         */
        public static function getPosts($array = FALSE)
        {

            global $wpdb;

            $aColumns = [
                'ID',
                'post_author',
                'post_date',
                'post_title',
                'post_status',
                'comment_status',
                'post_name',
                'post_parent',
                'guid',
                'post_type',
                'comment_count',
            ];

            // Determine Post Types
            $allowedPostTypes = XAGIO_MODEL_SEO::getAllPostTypes();

            // Create placeholders for the allowed post types
            $postTypePlaceholders = implode(', ', array_fill(0, count($allowedPostTypes), '%s'));

            // Prepare the WHERE clause for post types and status
            $sWhere = " WHERE post_type IN ($postTypePlaceholders) AND post_status IN ('publish', 'future', 'draft', 'pending') ";

            // Combine columns into a string for the query
            $columns = implode(", ", array_map('esc_sql', $aColumns)); // Escaping the column names for safety

            // Create placeholders for the allowed post types
            $postTypePlaceholders = implode(', ', array_fill(0, count($allowedPostTypes), '%s'));

            // Prepare the WHERE clause for post types and status
            $sWhere = "WHERE post_type IN ($postTypePlaceholders) AND post_status IN ('publish', 'future', 'draft', 'pending')";

            // Execute the query
            $rResult = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT SQL_CALC_FOUND_ROWS $columns
                    FROM {$wpdb->prefix}posts
                    $sWhere", ...$allowedPostTypes
                ), ARRAY_A
            );


            $posts_data = [];

            for ($xagio_i = 0; $xagio_i < count($rResult); $xagio_i++) {
                $posts_data[$xagio_i]['id']            = $rResult[$xagio_i]['ID'];
                $posts_data[$xagio_i]['post_type']     = $rResult[$xagio_i]['post_type'];
                $posts_data[$xagio_i]['post_title']    = $rResult[$xagio_i]['post_title'];
                $posts_data[$xagio_i]['post_status']   = $rResult[$xagio_i]['post_status'];
                $posts_data[$xagio_i]['guid']          = $rResult[$xagio_i]['guid'];
                $posts_data[$xagio_i]['post_author']   = get_the_author_meta('display_name', $rResult[$xagio_i]['post_author']);
                $posts_data[$xagio_i]['comment_count'] = $rResult[$xagio_i]['comment_count'];
            }

            /*Returning results*/
            if ($array === TRUE) {
                return $posts_data;
            } else {
                xagio_json('success', 'Successfully retrieved all post revisions.', $posts_data);
            }

        }

        /**
         *   Get Post Revisions
         * @param boolean $array Set cron to true to return array
         * @return void|array
         */
        public static function getPostRevisions($array = FALSE)
        {
            $posts = get_posts();

            $post_ids = [];
            foreach ($posts as $post) {
                $post_ids[] = $post->ID;
            }

            $revisions = [];
            foreach ($post_ids as $id) {
                $revision_count = sizeof(wp_get_post_revisions($id));

                if ($revision_count > 0) {
                    $revisions[$id]['count'] = $revision_count;
                }
            }

            /*Returning results*/
            if ($array === TRUE) {
                return $revisions;
            } else {
                xagio_json('success', 'Successfully retrieved all post revisions.', $revisions);
            }

        }

        public static function deleteRevisions($request = null)
        {


            if (empty($request->get_param('method')) || empty($request->get_param('post_id'))) {
                xagio_json('error', 'Invalid request!');
            }

            $method  = sanitize_text_field(wp_unslash($request->get_param('method')));
            $post_id = intval(wp_unslash($request->get_param('post_id')));

            if ($method !== 'DELETE') {
                xagio_json('error', 'Invalid request!');
            }

            $revisions = wp_get_post_revisions($post_id);
            $errors    = [];

            foreach ($revisions as $revision) {
                $xagio_result = wp_delete_post_revision($revision->ID);
                if (is_wp_error($xagio_result)) {
                    $errors[] = $revision->ID;
                }
            }

            if (empty($errors)) {
                xagio_json('success', 'Successfully deleted all revisions.');
            } else {
                xagio_json('error', 'Could not delete all revisions.');
            }
        }

        /**
         * Update Features
         */
        public static function updateFeatures($request = null)
        {


            // Update features if provided
            if (!empty($request->get_param('features'))) {
                $features = sanitize_text_field(wp_unslash($request->get_param('features')));
                update_option('XAGIO_FEATURES', $features);
                xagio_json('success', 'Successfully updated features!');
            } else {
                xagio_json('error', 'No features detected!');
            }
        }

        /**
         * Daily Synchronization
         */
        public static function dailySync($request = null)
        {

            try {
                $received_features = false;

                // Update features if detected
                if (!empty($request->get_param('features'))) {
                    $received_features = sanitize_text_field(wp_unslash($request->get_param('features')));
                    update_option('XAGIO_FEATURES', $received_features);
                }

                // Update membership if detected
                if (!empty($request->get_param('membership'))) {
                    $membership = sanitize_text_field(wp_unslash($request->get_param('membership')));
                    update_option('XAGIO_MEMBERSHIP', $membership);
                }

                if (!empty($request->get_param('license_email')) && !empty($request->get_param('license_key'))) {
                    $license_email = sanitize_text_field(wp_unslash($request->get_param('license_email')));
                    $license_key = sanitize_text_field(wp_unslash($request->get_param('license_key')));
                    update_option('XAGIO_LICENSE_EMAIL', $license_email);
                    update_option('XAGIO_LICENSE_KEY', $license_key);
                }

                xagio_json('success', 'Successfully retrieved blog description.', [
                    'posts'            => self::getPosts(true),
                    'pluginsAndThemes' => self::storePluginsThemes(true),
                    'availableUpdates' => self::getUpdates(true),
                    'settings'         => self::getSettings(true),
                    'comments'         => self::getComments(true),
                    'revisions'        => self::getPostRevisions(true),
                    'reviews'          => self::getReviews(true),
                    'coreVersion'      => get_bloginfo('version'),
                    'new_features'     => $received_features,
                    'old_features'     => get_option('XAGIO_FEATURES'),
                    'admin_post'       => XAGIO_MODEL_SETTINGS::getApiUrl(),
                    'ip_address'       => XAGIO_IP_ADDRESS,
                    'timezone'         => wp_timezone_string(),
                    'next_backup'      => wp_next_scheduled('xagio_doBackup')
                ]);

            } catch (Exception $e) {
                xagio_json('error', 'Plugin error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }

        /**
         * Rank Tracker Daily Synchronization
         */
        public static function dailySyncPRT($request = null)
        {
            try {
                // Check if prtData is set and is an array
                if (empty($request->get_param('prtData')) || !is_array($request->get_param('prtData'))) {
                    xagio_json('error', 'Invalid request!');
                }

                // Clear all ranks
                global $wpdb;
                $wpdb->query('UPDATE xag_keywords SET rank = "0"');

                $prtData = map_deep(wp_unslash($request->get_param('prtData')), 'sanitize_text_field');

                // Sanitize and update existing fields with the new rank data
                foreach ($prtData as $termName => $termData) {
                    $sanitizedTermName = sanitize_text_field($termName);
                    $sanitizedTermData = wp_json_encode(
                        array_map(function ($xagio_item) {
                            $xagio_item['term_id'] = absint($xagio_item['term_id']);
                            $xagio_item['url_id']  = absint($xagio_item['url_id']);
                            $xagio_item['rank']    = is_numeric($xagio_item['rank']) ? absint($xagio_item['rank']) : $xagio_item['rank'];
                            $xagio_item['engine']  = esc_url_raw($xagio_item['engine']);
                            return $xagio_item;
                        }, $termData)
                    );

                    $wpdb->update(
                        'xag_keywords', ['rank' => $sanitizedTermData], ['keyword' => $sanitizedTermName]
                    );
                }

                xagio_json('success', 'Rank tracker data synchronized successfully.');
            } catch (Exception $e) {
                xagio_json('error', 'Plugin error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }


        /**
         * Rank Tracker update remove
         */
        public static function removeTermPRT($request = null)
        {


            global $wpdb;
            // Check if term_ids are set
            if (empty($request->get_param('term_ids'))) {
                xagio_json('error', 'Invalid request!');
            }

            $term_ids_raw = sanitize_text_field(wp_unslash($request->get_param('term_ids')));
            $term_ids     = array_map('intval', array_map('sanitize_text_field', explode(',', $term_ids_raw)));

            foreach ($term_ids as $term_id) {
                // Prepare and execute the query to fetch the relevant keyword and rank data
                $results = $wpdb->get_row(
                    $wpdb->prepare(
                        "SELECT keyword, rank FROM xag_keywords WHERE rank != '0' AND rank != '501' AND rank LIKE %s LIMIT 1", '%' . $wpdb->esc_like($term_id) . '%'
                    )
                );

                if ($results) {
                    $data    = json_decode($results->rank, true);
                    $newData = [];

                    foreach ($data as $xagio_key => $val) {
                        if ($val['term_id'] != $term_id) {
                            $newData[] = $val;
                        }
                    }

                    $newData = !empty($newData) ? wp_json_encode($newData) : '0';

                    $wpdb->update(
                        'xag_keywords', ['rank' => $newData], ['keyword' => sanitize_text_field($results->keyword)]
                    );
                }
            }

            xagio_json('success', 'Term(s) removed successfully.');
        }

        /**
         *   Store Plugins and Themes on register
         * @param boolean $array Set crone to true to return array
         * @return void|array
         */
        public static function storePluginsThemes($array = FALSE)
        {

            $pluginsThemes = self::getPluginsThemes(TRUE);

            // Check if plugins are activated
            $plugins = $pluginsThemes['plugins'];

            foreach ($plugins as $xagio_name => $plugin) {
                $pluginsThemes['plugins'][$xagio_name]['active'] = is_plugin_active($xagio_name);
            }

            // Check which theme is activated
            $themes = $pluginsThemes['themes'];

            $current_theme = get_option('current_theme');

            foreach ($themes as $xagio_name => $theme) {
                if ($theme['Name'] == $current_theme) {
                    $pluginsThemes['themes'][$xagio_name]['active'] = TRUE;
                } else {
                    $pluginsThemes['themes'][$xagio_name]['active'] = FALSE;
                }
            }

            /*Returning results*/
            if ($array === TRUE) {
                return $pluginsThemes;
            } else {
                xagio_json('success', 'Successfully retrieved blog description.', $pluginsThemes);
            }

        }

        /**
         *  Get site Environment
         */
        public static function getEnvironment($request = null)
        {
            $wpDebugMode = (defined('WP_DEBUG') && TRUE === WP_DEBUG) ? TRUE : FALSE;
            $data        = [
                'wpEnvironment'     => [
                    'homeURL'       => get_home_url(),
                    'siteURL'       => get_site_url(),
                    'wpVersion'     => get_bloginfo('version'),
                    'wpMultisite'   => is_multisite(),
                    'wpMemoryLimit' => WP_MEMORY_LIMIT,
                    'wpDebugMode'   => $wpDebugMode,
                    'wpLanguage'    => get_bloginfo('language'),
                ],
                'serverEnvironment' => [
                    'serverInfo'       => sanitize_text_field(wp_unslash(!empty($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : 'Unknown')),
                    'phpVersion'       => phpversion(),
                    'phpPostMaxSize'   => ini_get('post_max_size'),
                    'phpMaxUploadSize' => ini_get('upload_max_filesize'),
                    'phpTimeLimit'     => ini_get('max_execution_time'),
                    'phpMaxInputVars'  => ini_get('max_input_vars'),
                    'cURL'             => function_exists('curl_init'),
                    'ZipArchive'       => class_exists('ZipArchive'),
                    'DOMDocument'      => class_exists('DOMDocument'),
                    'wpRemoteGet'      => function_exists('wp_remote_get'),
                    'wpRemotePost'     => function_exists('wp_remote_post'),
                ],
            ];

            xagio_json('success', 'Successfully retrieved Environment info.', $data);
        }

        /**
         * Save Global Scripts
         */
        public static function renderGlobalScripts($request = null)
        {


            // Check if page_id and value are set
            if (empty($request->get_param('page_id')) || !!empty($request->get_param('value'))) {
                xagio_json('error', 'Invalid request!');
            }

            // Sanitize inputs
            $xagio_page_id = intval($request->get_param('page_id'));
            $xagio_value   = sanitize_text_field(wp_unslash($request->get_param('value')));

            // Update post meta
            update_post_meta($xagio_page_id, 'ps_seo_disable_global_scripts', $xagio_value);

            xagio_json('success', 'Successfully updated render global script option.');
        }


        /**
         *  Get Scripts per page
         */
        public static function getPerPageScript($request = null)
        {


            if (!!empty($request->get_param('page_id'))) {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            $xagio_page_id = intval($request->get_param('page_id'));
            $scripts = get_post_meta($xagio_page_id);

            $filtered_value = array();
            $required_key   = array(
                'ps_seo_scripts',
                'ps_seo_body_scripts',
                'ps_seo_footer_scripts',
                'ps_seo_disable_global_scripts',
                'ps_seo_disable_global_body_scripts',
                'ps_seo_disable_global_footer_scripts',
                'ps_seo_disable_page_scripts',
                'ps_seo_disable_page_body_scripts',
                'ps_seo_disable_page_footer_scripts'
            );

            foreach ($scripts as $xagio_key => $val) {
                if (in_array($xagio_key, $required_key)) {
                    $filtered_value[$xagio_key] = $val[0];
                }
            }

            $filtered_value = wp_json_encode($filtered_value);
            $filtered_value = base64_encode($filtered_value);

            xagio_json('success', 'Successfully retrieved scripts.', $filtered_value);
        }

        /**
         * Save Global Scripts
         */
        public static function savePerPageScript($request = null)
        {


            if (!!empty($request->get_param('page_id'))) {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            // Sanitize the page ID
            $xagio_page_id = intval($request->get_param('page_id'));

            // Sanitize and decode the scripts
            $ps_seo_scripts        = !empty($request->get_param('script')['seo_scripts']) ? base64_decode(sanitize_textarea_field(wp_unslash($request->get_param('script')['seo_scripts']))) : '';
            $ps_seo_body_scripts   = !empty($request->get_param('script')['seo_body_scripts']) ? base64_decode(sanitize_textarea_field(wp_unslash($request->get_param('script')['seo_body_scripts']))) : '';
            $ps_seo_footer_scripts = !empty($request->get_param('script')['seo_footer_scripts']) ? base64_decode(sanitize_textarea_field(wp_unslash($request->get_param('script')['seo_footer_scripts']))) : '';

            // Sanitize the disable script options
            $ps_seo_disable_global_scripts        = !empty($request->get_param('script')['seo_disable_global_scripts']) ? sanitize_text_field(wp_unslash($request->get_param('script')['seo_disable_global_scripts'])) : '';
            $ps_seo_disable_global_body_scripts   = !empty($request->get_param('script')['seo_disable_global_body_scripts']) ? sanitize_text_field(wp_unslash($request->get_param('script')['seo_disable_global_body_scripts'])) : '';
            $ps_seo_disable_global_footer_scripts = !empty($request->get_param('script')['seo_disable_global_footer_scripts']) ? sanitize_text_field(wp_unslash($request->get_param('script')['seo_disable_global_footer_scripts'])) : '';

            $ps_seo_disable_page_scripts        = !empty($request->get_param('script')['seo_disable_page_scripts']) ? sanitize_text_field(wp_unslash($request->get_param('script')['seo_disable_page_scripts'])) : '';
            $ps_seo_disable_page_body_scripts   = !empty($request->get_param('script')['seo_disable_page_body_scripts']) ? sanitize_text_field(wp_unslash($request->get_param('script')['seo_disable_page_body_scripts'])) : '';
            $ps_seo_disable_page_footer_scripts = !empty($request->get_param('script')['seo_disable_page_footer_scripts']) ? sanitize_text_field(wp_unslash($request->get_param('script')['seo_disable_page_footer_scripts'])) : '';

            // Update post meta with sanitized values
            update_post_meta($xagio_page_id, 'ps_seo_scripts', trim($ps_seo_scripts));
            update_post_meta($xagio_page_id, 'ps_seo_body_scripts', trim($ps_seo_body_scripts));
            update_post_meta($xagio_page_id, 'ps_seo_footer_scripts', trim($ps_seo_footer_scripts));

            update_post_meta($xagio_page_id, 'ps_seo_disable_global_scripts', trim($ps_seo_disable_global_scripts));
            update_post_meta($xagio_page_id, 'ps_seo_disable_global_body_scripts', trim($ps_seo_disable_global_body_scripts));
            update_post_meta($xagio_page_id, 'ps_seo_disable_global_footer_scripts', trim($ps_seo_disable_global_footer_scripts));

            update_post_meta($xagio_page_id, 'ps_seo_disable_page_scripts', trim($ps_seo_disable_page_scripts));
            update_post_meta($xagio_page_id, 'ps_seo_disable_page_body_scripts', trim($ps_seo_disable_page_body_scripts));
            update_post_meta($xagio_page_id, 'ps_seo_disable_page_footer_scripts', trim($ps_seo_disable_page_footer_scripts));

            xagio_json('success', 'Successfully updated global script.');
        }


        /**
         *  Get global header Scripts
         */
        public static function getGlobalScripts($request = null)
        {

            $scripts = get_option('XAGIO_SEO_GLOBAL_SCRIPTS_HEAD');

            $scripts = base64_encode($scripts);

            xagio_json('success', 'Successfully retrieved header scripts.', $scripts);
        }

        /**
         *  Get global footer Scripts
         */
        public static function getGlobalBodyScripts($request = null)
        {

            $scripts = get_option('XAGIO_SEO_GLOBAL_SCRIPTS_BODY');

            $scripts = base64_encode($scripts);

            xagio_json('success', 'Successfully retrieved body scripts.', $scripts);
        }

        /**
         *  Get global footer Scripts
         */
        public static function getGlobalFooterScripts($request = null)
        {

            $scripts = get_option('XAGIO_SEO_GLOBAL_SCRIPTS_FOOTER');

            $scripts = base64_encode($scripts);

            xagio_json('success', 'Successfully retrieved footer scripts.', $scripts);
        }

        /**
         * Save Global Header Scripts
         */
        public static function saveGlobalScript($request = null)
        {


            // Check and sanitize inputs
            $encoded_header = !empty($request->get_param('script')['global_header_scripts']) ? sanitize_textarea_field(wp_unslash($request->get_param('script')['global_header_scripts'])) : '';
            $encoded_footer = !empty($request->get_param('script')['global_footer_scripts']) ? sanitize_textarea_field(wp_unslash($request->get_param('script')['global_footer_scripts'])) : '';
            $encoded_body   = !empty($request->get_param('script')['global_body_scripts']) ? sanitize_textarea_field(wp_unslash($request->get_param('script')['global_body_scripts'])) : '';

            // Decode the base64 encoded scripts
            $header_script = base64_decode($encoded_header);
            $footer_script = base64_decode($encoded_footer);
            $body_script   = base64_decode($encoded_body);

            // Update options with sanitized and decoded scripts
            update_option('XAGIO_SEO_GLOBAL_SCRIPTS_HEAD', trim($header_script));
            update_option('XAGIO_SEO_GLOBAL_SCRIPTS_FOOTER', trim($footer_script));
            update_option('XAGIO_SEO_GLOBAL_SCRIPTS_BODY', trim($body_script));

            xagio_json('success', 'Successfully updated global scripts.');
        }

        /**
         * Save Global Footer Scripts
         */
        public static function saveGlobalFooterScript($request = null)
        {


            // Check and sanitize the input
            if (!empty($request->get_param('footerScript'))) {
                $encoded = sanitize_textarea_field(wp_unslash($request->get_param('footerScript')));
                $script  = base64_decode($encoded);

                // Update the option with the sanitized and decoded script
                update_option('XAGIO_SEO_GLOBAL_SCRIPTS_FOOTER', trim($script));

                xagio_json('success', 'Successfully updated global footer script.');
            } else {
                xagio_json('error', 'No footer script provided.');
            }
        }

        /**
         *  Update WordPress Core
         */
        public static function updateWpCore($request = null)
        {


            try {

                // Remove the lock
                delete_option('core_updater.lock');

                // Including required class for updates
                require_once(ABSPATH . 'wp-admin/includes/update.php');
                require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');

                $reinstall = !empty($request->get_param('reinstall'));
                $xagio_version   = !empty($request->get_param('version')) ? sanitize_text_field(wp_unslash($request->get_param('version'))) : FALSE;

                // Check if already updated
                if ($xagio_version == get_bloginfo('version')) {
                    xagio_json('success', 'Successfully updated WordPress core.');
                    exit;
                }

                $update = find_core_update($xagio_version, 'en_US');

                if (!$update) {
                    xagio_json('error', 'Cannot find any new updates for WordPress core.');
                    exit;
                }

                $allow_relaxed_file_ownership = !$reinstall && !empty($update->new_files) && !$update->new_files;

                if ($reinstall) {
                    $update->response = 'reinstall';
                }

                ob_start();
                $skin     = new Xagio_Silent_Upgrader_Skin();
                $upgrader = new Core_Upgrader($skin);
                $status   = $upgrader->upgrade($update, [
                    'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership,
                ]);

                ob_end_clean();

                if (is_wp_error($status)) {
                    xagio_json('error', 'Failed to update WordPress core.', $status);
                } else {
                    xagio_json('success', 'Successfully updated WordPress core.');
                }

            } catch (Exception $error) {
                xagio_json('error', 'Plugin error occurred. Please pass this down to support: ' . $error->getMessage());
            }

        }

        /**
         * Update one or more plugins
         * receive plugin root_name
         */
        public static function updateWpPlugins($request = null)
        {


            try {
                // Check if plugin names are set
                if (empty($request->get_param('pluginNames'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $pluginNames = is_array($request->get_param('pluginNames')) ? array_map('sanitize_text_field', wp_unslash($request->get_param('pluginNames'))) : [sanitize_text_field(wp_unslash($request->get_param('pluginNames')))];

                // Include required class for updates
                require_once ABSPATH . 'wp-admin/includes/plugin.php';
                require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

                $status      = [];
                $all_plugins = get_plugins();

                foreach ($pluginNames as $pluginName) {
                    $updates        = self::getUpdates(true);
                    $plugins_update = $updates['plugins'];

                    if (!!empty($all_plugins[$pluginName])) {
                        $status[$pluginName] = 'Plugin is not installed on this website. Please synchronize.';
                    } else {
                        if (!!empty($plugins_update[$pluginName])) {
                            $status[$pluginName] = true;
                        } else {
                            $plugin_active = is_plugin_active($pluginName);
                            $skin          = new Xagio_Silent_Upgrader_Skin();
                            $upgrader      = new Plugin_Upgrader($skin);
                            $temp_check    = $upgrader->upgrade($pluginName);

                            if (!$temp_check || is_wp_error($temp_check)) {
                                $status[$pluginName] = false;
                            } else {
                                if ($plugin_active) {
                                    activate_plugin($pluginName, '', false, true);
                                }
                                $status[$pluginName] = true;
                            }
                        }
                    }
                }

                xagio_json('success', 'Operation successfully finished.', ['success' => $status]);

            } catch (Exception $e) {
                xagio_json('error', 'Plugin error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }

        /**
         * Update one or more themes
         * Theme slug required
         */
        public static function updateWpThemes($request = null)
        {


            try {
                // Check if theme names are set
                if (empty($request->get_param('themeNames'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $themeNames = is_array($request->get_param('themeNames')) ? array_map('sanitize_text_field', wp_unslash($request->get_param('themeNames'))) : [sanitize_text_field(wp_unslash($request->get_param('themeNames')))];

                // Include required class for updates
                require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

                $status         = [];
                $updates        = self::getUpdates(true);
                $themes_updates = $updates['themes'];

                foreach ($themeNames as $themeName) {
                    if (!!empty($themes_updates[$themeName])) {
                        $status[$themeName] = true;
                    } else {
                        $skin     = new Xagio_Silent_Upgrader_Skin();
                        $upgrader = new Theme_Upgrader($skin);
                        $xagio_result   = $upgrader->upgrade($themeName);

                        if (!$xagio_result || is_wp_error($xagio_result)) {
                            $status[$themeName] = false;
                        } else {
                            $status[$themeName] = true;
                        }
                    }
                }

                xagio_json('success', 'Operation successfully finished.', $status);

            } catch (Exception $e) {
                xagio_json('error', 'Theme error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }

        /**
         * Removing theme from WordPress
         * Theme slug required
         */
        public static function removeWpTheme($request = null)
        {


            try {
                // Check if theme slug is set
                if (empty($request->get_param('slug'))) {
                    xagio_json('error', 'Invalid request!');
                }

                $slug = sanitize_text_field(wp_unslash($request->get_param('slug')));

                require_once ABSPATH . 'wp-admin/includes/theme.php';
                require_once ABSPATH . 'wp-admin/includes/file.php';

                $remove = delete_theme($slug);

                if ($remove) {
                    xagio_json('success', 'Theme successfully removed.');
                } else {
                    xagio_json('error', 'There was a problem while removing the theme.');
                }

            } catch (Exception $e) {
                xagio_json('error', 'Theme error occurred. Please pass this down to support: ' . $e->getMessage());
            }
        }


        /**
         *  Approve / Edit / Remove Comment
         */
        public static function deleteComment($request = null)
        {


            if (!!empty($request->get_param('id'))) {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            $comment_id = intval($request->get_param('id'));

            $data = wp_delete_comment($comment_id);

            if ($data) {
                xagio_json('success', 'Successfully deleted Comment.');
            } else {
                xagio_json('error', 'Comment doesn\'t exist!');
            }
        }

        public static function approveComment($request = null)
        {


            if (!!empty($request->get_param('id'))) {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            $comment_id = intval($request->get_param('id'));

            $data = wp_set_comment_status($comment_id, 'approve');

            if ($data) {
                xagio_json('success', 'Successfully approved Comment.');
            } else {
                xagio_json('error', 'Comment doesn\'t exist!');
            }
        }

        /**
         *  Edit / Add Review
         */
        public static function editAddReview($request = null)
        {


            global $wpdb;

            // Sanitize and validate the ID
            $ID = !empty($request->get_param('id')) ? intval($request->get_param('id')) : 0;

            // Sanitize the input data with !empty() checks
            $data = [
                'name'      => !empty($request->get_param('name')) ? sanitize_text_field(wp_unslash($request->get_param('name'))) : '',
                'review'    => !empty($request->get_param('review')) ? sanitize_textarea_field(wp_unslash($request->get_param('review'))) : '',
                'rating'    => !empty($request->get_param('rating')) ? intval($request->get_param('rating')) : 0,
                'email'     => !empty($request->get_param('email')) ? sanitize_email(wp_unslash($request->get_param('email'))) : '',
                'website'   => !empty($request->get_param('website')) ? esc_url_raw(wp_unslash($request->get_param('website'))) : '',
                'telephone' => !empty($request->get_param('telephone')) ? sanitize_text_field(wp_unslash($request->get_param('telephone'))) : '',
                'location'  => !empty($request->get_param('location')) ? sanitize_text_field(wp_unslash($request->get_param('location'))) : '',
                'age'       => !empty($request->get_param('age')) ? intval($request->get_param('age')) : 0,
                // Corrected to use 'age'
            ];

            // Determine if we are inserting or updating based on the ID
            if ($ID == 0) {
                $wpdb->insert('xag_reviews', $data);
            } else {
                $wpdb->update('xag_reviews', $data, ['id' => $ID]);
            }

            xagio_json('success', 'Successfully finished operation.');
        }


        /**
         * Sync reviews
         */
        public static function updateReviews($request = null)
        {
            global $wpdb;

            // Validate the required parameters
            if (empty($request->get_param('method')) || empty($request->get_param('review_ids'))) {
                xagio_json('error', 'Invalid request!');
            }

            // Sanitize and process input
            $method     = sanitize_text_field(wp_unslash($request->get_param('method')));
            $review_ids = array_map('intval', explode(',', sanitize_text_field(wp_unslash($request->get_param('review_ids')))));

            // Ensure that review IDs are provided
            if (empty($review_ids)) {
                xagio_json('error', 'No valid review IDs provided.');
            }

            // Perform the requested operation
            switch ($method) {
                case "approve":
                    $wpdb->update('xag_reviews', ['approved' => 1], ['id' => $review_ids]);
                    break;
                case "unapprove":
                    $wpdb->update('xag_reviews', ['approved' => 0], ['id' => $review_ids]);
                    break;
                case "remove":
                    $wpdb->delete('xag_reviews', ['id' => $review_ids]);
                    break;
                default:
                    xagio_json('error', 'Invalid request method.');
                    break;
            }

            xagio_json('success', 'Operation completed successfully.');
        }

        /**
         * Sync posts
         */
        public static function updatePosts($request = null)
        {


            // Validate the required parameters
            if (empty($request->get_param('method')) || empty($request->get_param('post_ids'))) {
                xagio_json('error', 'Invalid request!');
            }

            // Sanitize and process input
            $method   = sanitize_text_field(wp_unslash($request->get_param('method')));
            $post_ids = array_map('intval', explode(',', sanitize_text_field(wp_unslash($request->get_param('post_ids')))));

            // Ensure that post IDs are provided
            if (empty($post_ids)) {
                xagio_json('error', 'No valid post IDs provided.');
            }

            // Perform the requested operation
            switch ($method) {
                case "seo-enable":
                    foreach ($post_ids as $id) {
                        update_post_meta($id, 'XAGIO_SEO', true);
                    }
                    break;
                case "seo-disable":
                    foreach ($post_ids as $id) {
                        update_post_meta($id, 'XAGIO_SEO', false);
                    }
                    break;
                case "remove":
                    foreach ($post_ids as $id) {
                        wp_trash_post($id);
                    }
                    break;
                default:
                    xagio_json('error', 'Invalid request method.');
                    break;
            }

            xagio_json('success', 'Operation completed successfully.');
        }


        /**
         *  Sync settings
         * @param boolean $array Set crone to true to return array
         * @return void|array
         */
        public static function getSettings($array = FALSE)
        {
            $settings = [
                "blogname",
                "blogdescription",
                "users_can_register",
                "default_role",
                "default_category",
                "default_post_format",
                "show_on_front",
                "page_on_front",
                "page_for_posts",
                "posts_per_page",
                "rss_use_excerpt",
                "blog_public",
                "default_pingback_flag",
                "default_ping_status",
                "default_comment_status",
                "require_name_email",
                "comment_registration",
                "close_comments_for_old_posts",
                "close_comments_days_old",
                "thread_comments",
                "thread_comments_depth",
                "page_comments",
                "comments_per_page",
                "default_comments_page",
                "comment_order",
                "comments_notify",
                "moderation_notify",
                "comment_moderation",
                "comment_whitelist",
                "permalink_structure"
            ];

            $setting_for_panel = [];

            foreach ($settings as $setting) {
                $setting_for_panel[$setting] = @get_option($setting);
            }

            $categories = get_categories([
                "hide_empty" => 0,
                "type"       => "post",
                "orderby"    => "name",
                "order"      => "ASC",
            ]);
            $cat_data   = [];
            foreach ($categories as $category) {
                $cat_data[] = [
                    "term_id"         => $category->term_id,
                    "name"            => $category->name,
                    "slug"            => $category->slug,
                    "category_parent" => $category->category_parent,
                ];
            }

            $setting_for_panel["categories"] = wp_json_encode($cat_data, TRUE);

            /*Returning results*/
            if ($array === TRUE) {
                return $setting_for_panel;
            } else {
                xagio_json('success', 'Successfully retrieved blog description.', $setting_for_panel);
            }

        }

	    public static function rankTrackingSettings($request = null)
	    {
		    $data = $request->get_param('data') ?: [];

		    if (array_key_exists('default_search_engine', $data)) {
			    $search_engines = sanitize_text_field(wp_unslash($data['default_search_engine'] ?? ''));
			    update_option('XAGIO_LOCATION_DEFAULT_SEARCH_ENGINE', json_decode($search_engines, true));
		    }

		    if (array_key_exists('default_country', $data)) {
			    $default_country = (($data['default_country'] ?? '') === 'Select country')
				    ? ''
				    : sanitize_text_field(wp_unslash($data['default_country'] ?? ''));
			    update_option('XAGIO_LOCATION_DEFAULT_COUNTRY', $default_country);
		    }

		    if (array_key_exists('default_location', $data)) {
			    $default_location = sanitize_text_field(wp_unslash($data['default_location'] ?? ''));
			    update_option('XAGIO_LOCATION_DEFAULT_CITY', $default_location);
		    }

		    xagio_json('success', 'Rank tracking settings successfully updated.');
	    }


	    public static function postLicense($request = null)
        {
            // Sanitize and process input
            $email = !empty($request->get_param('license_email')) ? sanitize_email(wp_unslash($request->get_param('license_email'))) : '';
            $xagio_key   = !empty($request->get_param('license_key')) ? sanitize_text_field(wp_unslash($request->get_param('license_key'))) : '';

            // Update the license information
            update_option('XAGIO_LICENSE_EMAIL', $email);
            update_option('XAGIO_LICENSE_KEY', $xagio_key);

            // Return success response
            xagio_json('success', 'License successfully updated.', [
                'blog_name' => get_bloginfo('name'),
                'blog_desc' => get_bloginfo('description'),
            ]);
        }

        public static function activateLicense($request = null)
        {
            if ($request === null) {
                wp_die('Invalid request type.');
            }

            $email = $request->get_param('license_email');
            $xagio_key   = $request->get_param('license_key');

            $email = is_string($email) ? sanitize_email(wp_unslash($email)) : '';
            $xagio_key   = is_string($xagio_key) ? sanitize_text_field(wp_unslash($xagio_key)) : '';

            if (empty($email) || empty($xagio_key)) {
                xagio_json('error', 'License email and key are required.');
            }

            update_option('XAGIO_LICENSE_EMAIL', $email);
            update_option('XAGIO_LICENSE_KEY', $xagio_key);

            $domain = wp_parse_url(admin_url(), PHP_URL_HOST);
            $domain = str_replace('www.', '', (string)$domain);

            $xagio_api = get_option('XAGIO_API');

            $http_query = [
                'license_email' => $email,
                'license_key'   => $xagio_key,
                'domain'        => $domain,
                'admin_post'    => XAGIO_MODEL_SETTINGS::getApiUrl(),
                'api_key'       => $xagio_api,
                'blog_name'     => get_bloginfo('name'),
                'blog_desc'     => get_bloginfo('description'),
            ];

            $xagio_response = wp_remote_post(XAGIO_PANEL_URL . '/api/license?' . http_build_query($http_query, '', '&'), [
                'user-agent'  => 'Xagio - ' . XAGIO_CURRENT_VERSION . " ($domain)",
                'timeout'     => 120,
                'redirection' => 5,
                'httpversion' => '1.0',
                'blocking'    => true,
            ]);

            if (is_wp_error($xagio_response)) {
                xagio_json('error', 'There was a problem while communicating with our server. Make sure your server meets all the requirements.', [
                    'error' => $xagio_response->get_error_message(),
                ]);
            }

            if (empty($xagio_response['body'])) {
                xagio_json('error', 'The license information that you submitted is not valid. Please try again.');
            }

            $code    = isset($xagio_response['response']['code']) ? (int)$xagio_response['response']['code'] : 500;
            $payload = json_decode($xagio_response['body'], true);
            $message = is_array($payload) && !empty($payload['message']) ? $payload['message'] : 'License activation failed.';

            if (!is_array($payload)) {
                xagio_json('error', 'The license information that you submitted is not valid. Please try again.');
            }

            if ($code <= 201) {
                if (class_exists('XAGIO_SYNC')) {
                    XAGIO_SYNC::getMembershipInfo();
                }

                xagio_json('success', 'License successfully activated.', [
                    'account'  => get_option('XAGIO_ACCOUNT_DETAILS'),
                    'response' => $payload,
                ]);
            }

            XAGIO_LICENSE::removeLicense();
            xagio_json('error', $message, $payload);
        }

        public static function updateBlogSettings($request = null)
        {
            if ($request === null) {
                wp_die('Invalid request type.');
            }

            $blog_name    = $request->get_param('blog_name');
            $blog_tagline = $request->get_param('blog_tagline');

            $provided = false;

            if ($blog_name !== null) {
                $provided  = true;
                $blog_name = is_string($blog_name) ? sanitize_text_field(wp_unslash($blog_name)) : '';
                update_option('blogname', $blog_name);
            }

            if ($blog_tagline !== null) {
                $provided     = true;
                $blog_tagline = is_string($blog_tagline) ? sanitize_text_field(wp_unslash($blog_tagline)) : '';
                update_option('blogdescription', $blog_tagline);
            }

            if (!$provided) {
                xagio_json('error', 'You must provide at least one field to update.');
            }

            xagio_json('success', 'Blog settings updated successfully.', [
                'blog_name'    => get_bloginfo('name'),
                'blog_tagline' => get_bloginfo('description'),
            ]);
        }

        public static function getAgentXStatus($request = null)
        {
            XAGIO_MODEL_OCW::runWizard();

            $status = get_option('XAGIO_OCW', [
                'step' => 'not_running',
                'data' => [],
            ]);

            if (!is_array($status)) {
                $status = [
                    'step' => 'not_running',
                    'data' => [],
                ];
            }

            $posts_urls = [];
            if (isset($status['data']['posts'])) {
                foreach($status['data']['posts'] as $post) {
                    $posts_urls[] = [
                        get_the_title($post),
                        get_permalink($post)
                    ];
                }
                $status['data']['posts_urls'] = $posts_urls;
            }

            xagio_json('success', 'Agent X status retrieved.', $status);
        }

        public static function configureAgentX($request = null)
        {
            if ($request === null) {
                xagio_json('error', 'Invalid request.');
            }

            $body_params = $request->get_body_params();
            if (!is_array($body_params)) {
                $body_params = [];
            }

            global $wpdb;
            $project = $wpdb->get_row('SELECT id FROM xag_projects ORDER BY id ASC LIMIT 1', ARRAY_A);

            if (!$project || empty($project['id'])) {
                xagio_json('error', 'No projects found in Project Planner.');
            }

            $project_id = absint($project['id']);

            $homepage_group = false;
            $homepage_group_id = absint(get_transient('xagio_agentx_homepage_group_id'));

            $existing      = get_option('XAGIO_OCW', [
                'step' => 'not_running',
                'data' => [],
            ]);
            $existing_data = isset($existing['data']) && is_array($existing['data']) ? $existing['data'] : [];

            $rank_tracker_defaults = [
                'search_engines'       => [],
                'search_country'       => '',
                'search_location'      => '',
                'search_location_name' => '',
            ];

            if (isset($existing_data['rank_tracker']) && is_array($existing_data['rank_tracker'])) {
                $rank_tracker = array_merge($rank_tracker_defaults, $existing_data['rank_tracker']);
            } else {
                $rank_tracker = $rank_tracker_defaults;
            }

            $rank_tracker['search_country']       = isset($rank_tracker['search_country']) && !is_array($rank_tracker['search_country']) ? sanitize_text_field($rank_tracker['search_country']) : '';
            $rank_tracker['search_location']      = isset($rank_tracker['search_location']) && !is_array($rank_tracker['search_location']) ? sanitize_text_field($rank_tracker['search_location']) : '';
            $rank_tracker['search_location_name'] = isset($rank_tracker['search_location_name']) && !is_array($rank_tracker['search_location_name']) ? sanitize_text_field($rank_tracker['search_location_name']) : '';
            $rank_tracker['search_engines']       = is_array($rank_tracker['search_engines']) ? array_map('absint', $rank_tracker['search_engines']) : [];

            $configuration_data = [
                'project_id'           => $project_id,
                'progress'             => 1,
                'homepage_group'       => $homepage_group_id,
                'templates'            => 1,
                'competition_language' => isset($existing_data['competition_language']) && !is_array($existing_data['competition_language']) ? sanitize_text_field($existing_data['competition_language']) : '',
                'competition_location' => isset($existing_data['competition_location']) && !is_array($existing_data['competition_location']) ? sanitize_text_field($existing_data['competition_location']) : '',
                'rank_tracker'         => $rank_tracker,
                'wait'                 => false,
            ];

            $config_to_save = [
                'step' => 'running_wizard',
                'data' => $configuration_data,
            ];

            update_option('XAGIO_OCW', $config_to_save);

            xagio_json('success', 'Agent X configuration updated.', $config_to_save);
        }

        public static function getSystemStatus()
        {

            $xagio_output = [
                "xagio_version"          => xagio_get_version(),
                "xagio_panel_url"        => XAGIO_PANEL_URL,
                "xagio_plugin_path"      => XAGIO_PATH,
                "xagio_plugin_url_path"  => XAGIO_URL,
                "xagio_plugin_api_url"   => XAGIO_MODEL_SETTINGS::getApiUrl(),
                "wordpress_home_url"     => get_home_url(),
                "wordpress_site_url"     => get_site_url(),
                "wordpress_version"      => get_bloginfo('version'),
                "wordpress_multisite"    => is_multisite() ? '1' : '0',
                "wordpress_memory_limit" => WP_MEMORY_LIMIT,
                "wordpress_debug_mode"   => (defined('WP_DEBUG') && TRUE === WP_DEBUG) ? '1' : '0',
                "language"               => get_bloginfo('language'),
                "server_info"            => sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])),
                "php_version"            => phpversion(),
                "php_post_max_size"      => ini_get('post_max_size'),
                "php_max_upload_size"    => ini_get('upload_max_filesize'),
                "php_time_limit"         => ini_get('max_execution_time'),
                "php_max_input_vars"     => ini_get('max_input_vars'),
                "php_memory_limit"       => ini_get('memory_limit'),
                "open_ssl"               => OPENSSL_VERSION_NUMBER >= 268439647 ? "1" : "0",
                "curl"                   => function_exists('curl_init') ? "1" : "0",
                "zip_archive"            => class_exists('ZipArchive') ? "1" : "0",
                "dom_document"           => class_exists('DOMDocument') ? "1" : "0",
                "wp_remote_get"          => function_exists('wp_remote_get') ? "1" : "0",
                "wp_remote_post"         => function_exists('wp_remote_post') ? "1" : "0",
            ];

            wp_send_json($xagio_output);
            wp_die();
        }

        public static function postSettings($request = null)
        {


            // Validate and sanitize the input data
            $data = !empty($request->get_param('data')) ? map_deep(wp_unslash($request->get_param('data')), 'sanitize_text_field') : null;

            if (is_null($data)) {
                xagio_json('error', 'DATA is not properly being sent.');
            } else {
                foreach ($data as $option => $val) {
                    // Sanitize option name and value before updating
                    $option = sanitize_text_field($option);
                    $val    = maybe_serialize($val); // Handles potential arrays or objects
                    update_option($option, $val);
                }
                xagio_json('success', 'DATA successfully updated.');
            }
        }

        public static function pushSchema($request = null)
        {


            $schemaIDs = !empty($request->get_param('schema_ids')) ? array_map('sanitize_text_field', explode(',', sanitize_text_field(wp_unslash($request->get_param('schema_ids'))))) : null;
            $ID        = !empty($request->get_param('id')) ? intval($request->get_param('id')) : 0;
            $TYPE      = !empty($request->get_param('type')) ? sanitize_text_field(wp_unslash($request->get_param('type'))) : 'post';

            if (!empty($schemaIDs)) {
                $xagio_output          = null;
                $renderedSchemas = XAGIO_MODEL_SCHEMA::getRemoteRenderedSchemas($schemaIDs, null, $TYPE, $xagio_output);

                if ($renderedSchemas !== false) {
                    if ($TYPE === 'post') {
                        if ($ID !== 0) {
                            if (XAGIO_MODEL_SEO::is_homepage($ID)) {
                                update_option('XAGIO_SEO_SCHEMA_META', $renderedSchemas['meta']);
                                update_option('XAGIO_SEO_SCHEMA_DATA', $renderedSchemas['data']);
                            }
                            update_post_meta($ID, 'XAGIO_SEO_SCHEMA_META', $renderedSchemas['meta']);
                            update_post_meta($ID, 'XAGIO_SEO_SCHEMA_DATA', $renderedSchemas['data']);
                        } else {
                            update_option('XAGIO_SEO_SCHEMA_META', $renderedSchemas['meta']);
                            update_option('XAGIO_SEO_SCHEMA_DATA', $renderedSchemas['data']);
                        }
                    } elseif ($TYPE === 'term') {
                        if ($ID !== 0) {
                            $tag = get_term($ID);
                            if ($tag && !is_wp_error($tag)) {
                                $id = $tag->term_id;
                                update_term_meta($id, 'XAGIO_SEO_SCHEMA_META', $renderedSchemas['meta']);
                                update_term_meta($id, 'XAGIO_SEO_SCHEMA_DATA', $renderedSchemas['data']);
                            } else {
                                xagio_json('error', 'Invalid term ID.');
                            }
                        } else {
                            // TODO: Add global term schema if needed
                        }
                    }

                    xagio_json('success', 'Operation successfully finished.');
                } else {
                    xagio_json('error', 'A problem occurred.', $xagio_output);
                }
            } else {
                if ($ID !== 0) {
                    update_post_meta($ID, 'XAGIO_SEO_SCHEMA_META', false);
                    update_post_meta($ID, 'XAGIO_SEO_SCHEMA_DATA', false);
                } else {
                    update_option('XAGIO_SEO_SCHEMA_META', false);
                    update_option('XAGIO_SEO_SCHEMA_DATA', false);
                }
                xagio_json('success', 'Operation successfully finished.');
            }
        }

        public static function getSchema($request = null)
        {


            $ID   = !empty($request->get_param('id')) && !empty($request->get_param('id')) ? intval($request->get_param('id')) : 0;
            $TYPE = !empty($request->get_param('type')) && !empty($request->get_param('type')) ? sanitize_text_field(wp_unslash($request->get_param('type'))) : 'post';

            $SCHEMA = null;

            if ($TYPE === 'post') {
                $SCHEMA = ($ID !== 0) ? get_post_meta($ID, 'XAGIO_SEO_SCHEMA_META', true) : get_option('XAGIO_SEO_SCHEMA_META');
            } elseif ($TYPE === 'term' && $ID !== 0) {
                $tag = get_term($ID);
                if ($tag && !is_wp_error($tag)) {
                    $SCHEMA = get_term_meta($tag->term_id, 'XAGIO_SEO_SCHEMA_META', true);
                }
            }

            xagio_json('success', 'Retrieved schema(s).', $SCHEMA);
        }

        public static function removeSchema($request = null)
        {


            $schema_id = !empty($request->get_param('schema_id')) && !empty($request->get_param('schema_id')) ? sanitize_text_field(wp_unslash($request->get_param('schema_id'))) : null;
            $page_ids  = !empty($request->get_param('page_ids')) && !empty($request->get_param('page_ids')) ? array_map('intval', wp_unslash($request->get_param('page_ids'))) : [];

            if (is_null($schema_id) || empty($page_ids)) {
                xagio_json('error', 'Not a valid ID or no pages selected.');
            } else {
                foreach ($page_ids as $xagio_page_id) {
                    if ($xagio_page_id === 0) {
                        self::removeSchemaFromGlobal($schema_id);
                    } else {
                        self::removeSchemaFromPage($schema_id, $xagio_page_id);
                    }
                }
                xagio_json('success', 'Removed successfully');
            }
        }

        private static function removeSchemaFromGlobal($schema_id)
        {
            $schema_meta = get_option('XAGIO_SEO_SCHEMA_META', []);

            if (!empty($schema_meta)) {
                foreach ($schema_meta as $index => $xagio_meta) {
                    if ($xagio_meta['id'] === $schema_id) {
                        unset($schema_meta[$index]);
                        update_option('XAGIO_SEO_SCHEMA_META', array_values($schema_meta));
                        break;
                    }
                }

                $schema_data = get_option('XAGIO_SEO_SCHEMA_DATA', []);
                if (!empty($schema_data[$index])) {
                    unset($schema_data[$index]);
                    update_option('XAGIO_SEO_SCHEMA_DATA', array_values($schema_data));
                }
            }
        }

        private static function removeSchemaFromPage($schema_id, $xagio_page_id)
        {
            $schema_meta = get_post_meta($xagio_page_id, 'XAGIO_SEO_SCHEMA_META', true);

            if (!empty($schema_meta)) {
                foreach ($schema_meta as $index => $xagio_meta) {
                    if ($xagio_meta['id'] === $schema_id) {
                        unset($schema_meta[$index]);
                        update_post_meta($xagio_page_id, 'XAGIO_SEO_SCHEMA_META', array_values($schema_meta));
                        break;
                    }
                }

                $schema_data = get_post_meta($xagio_page_id, 'XAGIO_SEO_SCHEMA_DATA', true);
                if (!empty($schema_data[$index])) {
                    unset($schema_data[$index]);
                    update_post_meta($xagio_page_id, 'XAGIO_SEO_SCHEMA_DATA', array_values($schema_data));
                }
            }
        }

        public static function getRenderedSchemaData($request = null)
        {
            $xagio_page_id = !empty($request->get_param('page_id')) ? intval($request->get_param('page_id')) : 0;

            if ($xagio_page_id == 0) {
                $schema = get_option('XAGIO_SEO_SCHEMA_DATA');
            } else {
                $schema = get_post_meta($xagio_page_id, 'XAGIO_SEO_SCHEMA_DATA', TRUE);
            }

            xagio_json('success', 'Retrieved schema json.', $schema);
        }


        public static function getPost($request = null)
        {


            $ID = !empty($request->get_param('id')) && !empty($request->get_param('id')) ? intval($request->get_param('id')) : 0;

            if ($ID === 0) {
                xagio_json('error', 'ID is not properly being sent.');
            } else {
                $page = get_post($ID);

                if ($page) {
                    xagio_json('success', 'Successfully retrieved post content.', $page);
                } else {
                    xagio_json('error', 'Post not found.');
                }
            }
        }

        public static function updatePost($request = null)
        {


            $DATA = !empty($request->get_param('data')) ? map_deep(wp_unslash($request->get_param('data')), 'sanitize_text_field') : null;

            if (is_null($DATA)) {
                xagio_json('error', 'DATA is not properly being sent.');
            } else {
                $DATA   = array_map('sanitize_text_field', $DATA);
                $xagio_result = wp_update_post($DATA, true);

                if (is_wp_error($xagio_result)) {
                    xagio_json('error', 'Failed to update post content.', $xagio_result->get_error_message());
                } else {
                    xagio_json('success', 'Successfully updated post content.');
                }
            }
        }

        public static function createPost($request = null)
        {
            $DATA    = !empty($request->get_param('data')) ? $request->get_param('data') : null;
            $xagio_content = $DATA["post_content"];

            if (is_null($DATA)) {
                xagio_json('error', 'DATA is not properly being sent.');
            } else {
                $DATA = map_deep($DATA, function ($xagio_value) {
                    return is_array($xagio_value) ? $xagio_value : sanitize_text_field($xagio_value);
                });

                $DATA["post_content"] = $xagio_content;

                $post_id = wp_insert_post($DATA, true);

                if (is_wp_error($post_id)) {
                    xagio_json('error', 'Failed to create new post.', $post_id->get_error_message());
                } else {
                    xagio_json('success', 'Successfully created new ' . esc_html($DATA['post_type']) . '.');
                }
            }
        }


        public static function toggleSEO($request = null)
        {
            $ID    = !empty($request->get_param('id')) ? intval($request->get_param('id')) : 0;
            $VALUE = !empty($request->get_param('value')) ? sanitize_text_field(wp_unslash($request->get_param('value'))) : '';

            if ($ID === 0) {
                xagio_json('error', 'ID is not properly being sent.');
            } else {
                update_post_meta($ID, 'XAGIO_SEO', $VALUE);
                xagio_json('success', 'Successfully toggled SEO.');
            }
        }

        public static function apiRequestUpload($apiEndpoint = null, $fileToUpload = null)
        {
            $license_email = '';
            $license_key   = '';
            if (!XAGIO_LICENSE::isLicenseSet($license_email, $license_key)) {
                return false;
            }

            if ($apiEndpoint == null || $fileToUpload == null) {
                return false;
            }

            if (!defined('XAGIO_DOMAIN') || XAGIO_DOMAIN === '') {
                return [
                    'status'  => 'error',
                    'message' => 'Required parameters are missing.'
                ];
            }

            // Set the domain name
            $domain     = XAGIO_DOMAIN;
            $user_agent = "Xagio - " . XAGIO_CURRENT_VERSION . " ($domain)";

            // Ensure the file exists
            if (!file_exists($fileToUpload)) {
                return [
                    'status'  => 'error',
                    'message' => 'File to upload does not exist.'
                ];
            }

            // Prepare the file data for multipart/form-data
            $file_name = basename($fileToUpload);
            $file_data = xagio_file_get_contents($fileToUpload);
            $boundary  = wp_generate_password(24, false); // Unique boundary string for multipart
            $body      = "--$boundary\r\n";
            $body      .= "Content-Disposition: form-data; name=\"license_email\"\r\n\r\n$license_email\r\n";
            $body      .= "--$boundary\r\n";
            $body      .= "Content-Disposition: form-data; name=\"license_key\"\r\n\r\n$license_key\r\n";
            $body      .= "--$boundary\r\n";
            $body      .= "Content-Disposition: form-data; name=\"file_contents\"; filename=\"$file_name\"\r\n";
            $body      .= "Content-Type: " . mime_content_type($fileToUpload) . "\r\n\r\n";
            $body      .= $file_data . "\r\n";
            $body      .= "--$boundary--\r\n";

            // Make the request
            $xagio_response = wp_remote_post(XAGIO_PANEL_URL . "/api/" . $apiEndpoint, [
                'method'  => 'POST',
                'timeout' => 60,
                'headers' => [
                    'User-Agent'   => $user_agent,
                    'Content-Type' => "multipart/form-data; boundary=$boundary",
                ],
                'body'    => $body,
            ]);

            // Clean up temporary file after upload
            wp_delete_file($fileToUpload);

            if (is_wp_error($xagio_response)) {
                return false;
            }

            $data = json_decode(wp_remote_retrieve_body($xagio_response), true);
            if (!$data) {
                return false;
            } else {
                return $data;
            }
        }

        public static function apiRequest($apiEndpoint = NULL, $method = 'GET', $xagio_args = [], &$xagio_http_code = FALSE, $without_license = FALSE, $download = false)
        {
            if ($apiEndpoint == NULL) {
                return FALSE;
            }

            if (!defined('XAGIO_DOMAIN') || XAGIO_DOMAIN === '') {
                wp_die('Required parameters are missing.', 'Missing Parameters', ['response' => 400]);
            }

            // Set the domain name
            $domain = XAGIO_DOMAIN;

            if (!XAGIO_LICENSE::isLicenseSet($license_email, $license_key)) {
                $http_query = [
                    'domain' => $domain,
                ];
            } else {
                $http_query = [
                    'license_email' => $license_email,
                    'license_key'   => $license_key,
                    'domain'        => $domain,
                ];
            }
            $http_query = array_merge($http_query, $xagio_args);

            $data = [
                'user-agent'  => "Xagio - " . XAGIO_CURRENT_VERSION . " ($domain)",
                'timeout'     => 30,
                'redirection' => 5,
                'httpversion' => '1.0',
                'blocking'    => TRUE,
                'method'      => $method
            ];

            if ($method !== 'POST') {
                $apiEndpoint .= '?' . http_build_query($http_query);
            } else {
                $data['body'] = $http_query;
            }

            $xagio_response = wp_remote_request(XAGIO_PANEL_URL . "/api/" . $apiEndpoint, $data);

            if (is_wp_error($xagio_response)) {
                return FALSE;
            } else {
                $xagio_http_code = $xagio_response['response']['code'];

                if (empty($xagio_response['body'])) {
                    return FALSE;
                }

                // If $download is set, save the response as a file
                if ($download !== false) {
                    $file_path = $download;

                    $dir = dirname($file_path);
                    if (!file_exists($dir)) {
                        xagio_mkdir($dir);
                    }

                    if (xagio_file_put_contents($file_path, $xagio_response['body']) === false) {
                        return FALSE; // Return false if file writing fails
                    }

                    return $file_path; // Return the path to the saved file
                }

                // Otherwise, decode JSON as usual
                $data = json_decode($xagio_response['body'], TRUE);
                if (!$data) {
                    return FALSE;
                }

                return $data;
            }
        }


        public static function syncServerAPI($request = null)
        {
            do_action('XAGIO_CHECK_LICENSE');
        }

        private static function sanitizeAgentXConfiguration($xagio_value)
        {
            if (is_array($xagio_value)) {
                $sanitized = [];
                foreach ($xagio_value as $xagio_key => $xagio_item) {
                    $sanitized_key             = is_string($xagio_key) ? sanitize_key($xagio_key) : $xagio_key;
                    $sanitized[$sanitized_key] = self::sanitizeAgentXConfiguration($xagio_item);
                }

                return $sanitized;
            }

            if (is_bool($xagio_value)) {
                return $xagio_value;
            }

            if (is_numeric($xagio_value)) {
                return strpos((string)$xagio_value, '.') !== false ? (float)$xagio_value : (int)$xagio_value;
            }

            if (is_string($xagio_value)) {
                $xagio_value = wp_unslash($xagio_value);
                $bool  = xagio_parse_bool($xagio_value);
                if (is_bool($bool)) {
                    return $bool;
                }

                return sanitize_text_field($bool);
            }

            return $xagio_value;
        }

        private static function mergeAgentXConfiguration($original, $updates)
        {
            foreach ($updates as $xagio_key => $xagio_value) {
                if (isset($original[$xagio_key]) && is_array($original[$xagio_key]) && is_array($xagio_value)) {
                    $original[$xagio_key] = self::mergeAgentXConfiguration($original[$xagio_key], $xagio_value);
                } else {
                    $original[$xagio_key] = $xagio_value;
                }
            }

            return $original;
        }

        private function removeDirectory($path)
        {
            include_once ABSPATH . 'wp-admin/includes/file.php';

            // Initialize the WP Filesystem
            global $wp_filesystem;
            if (!function_exists('WP_Filesystem')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }
            $creds = request_filesystem_credentials(site_url() . '/wp-admin/', '', false, false, []);
            if (!WP_Filesystem($creds)) {
                return false;
            }

            // Check if the directory exists
            if (!$wp_filesystem->is_dir($path)) {
                return false;
            }

            // Get the list of files in the directory
            $xagio_files = $wp_filesystem->dirlist($path);

            // Iterate through the files and delete them
            foreach ($xagio_files as $xagio_file) {
                $file_path = $path . '/' . $xagio_file['name'];
                if ($xagio_file['type'] === 'd') {
                    self::removeDirectory($file_path);
                } else {
                    $wp_filesystem->delete($file_path);
                }
            }

            // Delete the directory itself
            $wp_filesystem->rmdir($path);
            return true;
        }
    }
}

if (!class_exists('XAGIO_Captured_WP_Die_Exception')) {
    class XAGIO_Captured_WP_Die_Exception extends \RuntimeException
    {
        private $status_code;

        public function __construct($message = '', $title = '', array $xagio_args = [])
        {
            $status = 500;

            if (isset($xagio_args['response']) && is_numeric($xagio_args['response'])) {
                $status = (int)$xagio_args['response'];
            }

            $this->status_code = $status;

            parent::__construct(is_string($message) ? $message : '', 0);
        }

        public function getStatusCode()
        {
            return $this->status_code;
        }
    }
}
