<?php
/**
 * пїЅпїЅпїЅпїЅпїЅ RLS_Admin_Pages
 * пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ, пїЅпїЅпїЅпїЅ, пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅ AJAX-пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
 * пїЅпїЅпїЅпїЅпїЅпїЅ 1.6.0 (Complete: Quarantine Init included)
 *
 * @package RybinskLabSecurity
 */

if ( ! defined( 'WPINC' ) ) {
    die;
}

class RLS_Admin_Pages {

    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
     */
    public function init() {
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        add_action( 'admin_menu', [ $this, 'setup_admin_menu' ] );
        
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_assets' ] );
        
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ
        add_action( 'admin_init', [ $this, 'initialize_settings' ] );
        add_action( 'admin_init', [ $this, 'maybe_redirect_after_activation' ] );
        
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ "пїЅ пїЅпїЅпїЅ" пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        add_action( 'admin_init', [ $this, 'check_and_send_heartbeat_on_visit' ] );
        
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ (пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ)
        add_action( 'admin_init', [ $this, 'check_and_fix_base_signatures' ] );

        // пїЅпїЅпїЅпїЅпїЅ HTML пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ (пїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ)
        add_action( 'admin_footer', [ $this, 'render_deactivation_modal' ] );

        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ (пїЅпїЅпїЅпїЅпїЅ)
        if ( class_exists( 'RLS_Quarantine' ) ) {
            $quarantine = new RLS_Quarantine();
            $quarantine->init();
        }

        // --- AJAX пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ ---

        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        add_action( 'wp_ajax_rls_save_uninstall_pref', [ $this, 'ajax_save_uninstall_pref' ] );

        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ IP
        add_action( 'wp_ajax_rls_add_ip_list', [ $this, 'ajax_add_ip_list' ] );
        add_action( 'wp_ajax_rls_delete_ip_list', [ $this, 'ajax_delete_ip_list' ] );
        add_action( 'wp_ajax_rls_unblock_ip', [ $this, 'ajax_unblock_ip' ] );

        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        add_action( 'wp_ajax_rls_add_signature', [ $this, 'ajax_add_signature' ] );
        add_action( 'wp_ajax_rls_delete_signature', [ $this, 'ajax_delete_signature' ] );
        
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ
        add_action( 'wp_ajax_rls_add_login_question', [ $this, 'ajax_add_login_question' ] );
        add_action( 'wp_ajax_rls_delete_login_question', [ $this, 'ajax_delete_login_question' ] );
        
        // AI пїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ (пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ)
        add_action( 'wp_ajax_rls_neutralize_file', [ $this, 'ajax_neutralize_file' ] );
        
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        add_action( 'wp_ajax_rls_sync_stats', [ $this, 'ajax_sync_stats' ] );
        add_action( 'wp_ajax_rls_clear_attack_logs', [ $this, 'ajax_clear_attack_logs' ] );
    }
    
    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ Heartbeat пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
     */
    public function check_and_send_heartbeat_on_visit() {
        if ( isset( $_GET['page'] ) && strpos( $_GET['page'], 'rls-' ) === 0 ) {
            $last_admin_ping = get_transient( 'rls_admin_heartbeat_sent' );
            if ( ! $last_admin_ping ) {
                if ( class_exists( 'RLS_API_Client' ) ) {
                    RLS_API_Client::send_heartbeat(); 
                    set_transient( 'rls_admin_heartbeat_sent', 1, 300 ); // 300 пїЅпїЅпїЅ = 5 пїЅпїЅпїЅ
                }
            }
        }
    }
    
    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
     */
    public function check_and_fix_base_signatures() {
        $current_base = get_option( 'rls_base_signatures', [] );
        if ( empty( $current_base ) || count( $current_base ) < 5 ) {
            if ( class_exists( 'RLS_Activator' ) ) {
                update_option( 'rls_base_signatures', RLS_Activator::BASE_SIGNATURES );
            }
        }
    }

    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
     */
    public function setup_admin_menu() {
        add_menu_page( 
            'Rybinsk Lab Security', 
            'RL Security', 
            'manage_options', 
            'rls-scanner', 
            [ $this, 'render_scanner_page' ], 
            'dashicons-shield-alt', 
            26 
        );
        
        add_submenu_page( 
            'rls-scanner', 
            'Сканер', 
            'Сканер', 
            'manage_options', 
            'rls-scanner', 
            [ $this, 'render_scanner_page' ] 
        );
        
        add_submenu_page( 
            'rls-scanner', 
            'Настройки', 
            'Настройки', 
            'manage_options', 
            'rls-settings', 
            [ $this, 'render_settings_page' ] 
        );
    }
    
    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ CSS пїЅ JS пїЅпїЅпїЅпїЅпїЅпїЅ.
     */
    public function enqueue_admin_assets( $hook_suffix ) {
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ (пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ)
        if ( strpos( $hook_suffix, 'rls-' ) === false && $hook_suffix !== 'plugins.php' ) {
            return;
        }
        
        wp_enqueue_style( 'rls-admin-styles', plugin_dir_url( RLS_PLUGIN_FILE ) . 'assets/css/admin.css', [], RLS_VERSION );

        // пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ (пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ + пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ)
        if ( $hook_suffix === 'rl-security_page_rls-settings' || $hook_suffix === 'plugins.php' ) {
            wp_enqueue_script( 'rls-admin-script', plugin_dir_url( RLS_PLUGIN_FILE ) . 'assets/js/admin.js', [ 'jquery' ], RLS_VERSION, true );
            wp_localize_script( 'rls-admin-script', 'rls_admin_data', [
                'ajax_url'         => admin_url( 'admin-ajax.php' ), 
                'settings_nonce'   => wp_create_nonce( 'rls_settings_nonce' ),
                'sync_nonce'       => wp_create_nonce( 'rls_sync_nonce' ),
                'questions_nonce'  => wp_create_nonce( 'rls_login_questions_nonce' ),
                'signatures_nonce' => wp_create_nonce( 'rls_signatures_nonce' )
            ]);
        }
        
        // пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        if ( $hook_suffix === 'toplevel_page_rls-scanner' || $hook_suffix === 'rl-security_page_rls-scanner' ) {
            wp_enqueue_script( 'rls-scanner-script', plugin_dir_url( RLS_PLUGIN_FILE ) . 'assets/js/scanner.js', [ 'jquery' ], RLS_VERSION, true );
            wp_localize_script( 'rls-scanner-script', 'rls_scanner_data', [
                'ajax_url'        => admin_url( 'admin-ajax.php' ),
                'nonce'           => wp_create_nonce( 'rls_scanner_nonce' ),
                'snapshot_exists' => ( get_option( 'rls_snapshot_time', 0 ) > 0 )
            ]);
        }
    }
    
    // пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ
    public function render_scanner_page() {
        require_once RLS_PLUGIN_PATH . 'includes/admin/views/scanner-page.php'; 
    }
    
    public function render_settings_page() {
        require_once RLS_PLUGIN_PATH . 'includes/admin/views/settings-page.php'; 
    }

    public function maybe_redirect_after_activation() {
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }

        if ( wp_doing_ajax() || is_network_admin() ) {
            return;
        }

        if ( ! get_transient( 'rls_activation_redirect' ) ) {
            return;
        }

        delete_transient( 'rls_activation_redirect' );

        if ( isset( $_GET['activate-multi'] ) ) {
            return;
        }

        wp_safe_redirect( admin_url( 'admin.php?page=rls-settings&rls-setup=1' ) );
        exit;
    }

    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅ HTML пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
     */
        public function render_deactivation_modal() {
        $screen = get_current_screen();
        if ( ! $screen || $screen->id !== 'plugins' ) {
            return;
        }
        ?>
        <div id="rls-deactivation-modal" style="display:none;">
            <div class="rls-modal-overlay"></div>
            <div class="rls-modal-content">
                <div id="rls-step-1">
                    <div class="rls-modal-header">
                        <span class="dashicons dashicons-shield-alt" style="color:#2271b1; font-size:40px; width:40px; height:40px;"></span>
                        <h2 style="margin:0; margin-left:15px;">Точно отключить защиту сайта?</h2>
                    </div>
                    <p style="font-size:14px; color:#555; margin-bottom:20px;">Если отключить <strong>Rybinsk Lab Security</strong>, сайт останется без активного WAF, защиты входа и других защитных модулей. Вы уверены, что хотите оставить сайт без защиты?</p>
                    <div style="padding:12px 14px; border:1px solid #f0c36d; background:#fff8e5; border-radius:8px; margin-bottom:20px; color:#7a4b00;">
                        Если передумаете, нажмите «Нет, оставить защиту» и плагин продолжит работать без изменений.
                    </div>

                    <div class="rls-modal-footer">
                        <button class="button button-large rls-cancel-btn">Нет, оставить защиту</button>
                        <button class="button button-primary button-large rls-next-btn">Да, отключить</button>
                    </div>
                </div>

                <div id="rls-step-2" style="display:none;">
                    <div class="rls-modal-header">
                        <span class="dashicons dashicons-database-remove" style="color:#d63638; font-size:40px; width:40px; height:40px;"></span>
                        <h2 style="margin:0; margin-left:15px;">Что делать с данными плагина?</h2>
                    </div>
                    <p style="margin-top:15px; font-size:14px;">Выберите, нужно ли очистить настройки, лицензию, карантин, журналы и локальные данные или оставить их для возможного возврата.</p>

                    <div class="rls-options">
                        <label class="rls-opt">
                            <input type="radio" name="rls_wipe_choice" value="keep" checked>
                            <div>
                                <strong>Оставить данные в памяти (рекомендуется)</strong>
                                <span class="desc">Сохранятся лицензия, настройки, карантин, журналы и другие локальные данные. Это удобно, если вы планируете включить плагин снова.</span>
                            </div>
                        </label>
                        <label class="rls-opt warning">
                            <input type="radio" name="rls_wipe_choice" value="wipe">
                            <div>
                                <strong>Очистить все данные плагина</strong>
                                <span class="desc">Будут удалены настройки, лицензия, карантин, GeoIP-база и журналы. После повторной активации плагин начнет работу как после первой установки.</span>
                            </div>
                        </label>
                    </div>

                    <div class="rls-modal-footer">
                        <button class="button button-large rls-back-btn">Назад</button>
                        <button class="button button-link-delete rls-final-deactivate-btn" style="color:#a00;">Отключить плагин</button>
                    </div>
                </div>
            </div>
        </div>
        <?php
    }

    public function initialize_settings() { 
        register_setting( 'rls_settings_group', 'rls_settings', [ $this, 'sanitize_settings_array' ] );
        register_setting( 'rls_settings_group', 'rls_auto_scan_frequency', [ 'sanitize_callback' => 'sanitize_text_field' ] );
    }
    
    /**
     * пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
     */
    public function sanitize_settings_array( $input ) {
        $old_settings = get_option( 'rls_settings', [] );
        $sanitized_input = $old_settings;

        $protection_mode = sanitize_key( (string) ( $input['protection_mode'] ?? ( $old_settings['protection_mode'] ?? 'full' ) ) );
        $sanitized_input['protection_mode'] = in_array( $protection_mode, [ 'light', 'full', 'scanner_only' ], true ) ? $protection_mode : 'full';
        
        $sanitized_input['enable_firewall'] = ( isset( $input['enable_firewall'] ) && $input['enable_firewall'] == 1 ) ? 1 : 0;
        $sanitized_input['disable_xmlrpc'] = ( isset( $input['disable_xmlrpc'] ) && $input['disable_xmlrpc'] == 1 ) ? 1 : 0;
        $sanitized_input['trust_cloudflare'] = ( isset( $input['trust_cloudflare'] ) && $input['trust_cloudflare'] == 1 ) ? 1 : 0;
        $sanitized_input['enable_login_security'] = ( isset( $input['enable_login_security'] ) && $input['enable_login_security'] == 1 ) ? 1 : 0;
        $sanitized_input['blacklists_enabled'] = ( isset( $input['blacklists_enabled'] ) && $input['blacklists_enabled'] == 1 ) ? 1 : 0;
        $sanitized_input['global_blacklist_enabled'] = ( isset( $input['global_blacklist_enabled'] ) && $input['global_blacklist_enabled'] == 1 ) ? 1 : 0;
        
        if ( isset( $input['login_questions_count'] ) ) { 
            $sanitized_input['login_questions_count'] = intval( $input['login_questions_count'] ); 
        }
        
        if ( isset( $input['license_key'] ) ) { 
            $sanitized_input['license_key'] = sanitize_text_field( strtoupper( trim( $input['license_key'] ) ) ); 

            $old_license_key = (string) ( $old_settings['license_key'] ?? '' );
            if ( $sanitized_input['license_key'] !== $old_license_key ) {
                rls_store_license_meta( '' );
                update_option( 'rls_premium_signatures', [] );
            }
        }
        
        $sanitized_input['allow_googlebot'] = ( isset( $input['allow_googlebot'] ) && $input['allow_googlebot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_yandexbot'] = ( isset( $input['allow_yandexbot'] ) && $input['allow_yandexbot'] == 1 ) ? 1 : 0;
        $sanitized_input['soft_search_bot_mode'] = ( isset( $input['soft_search_bot_mode'] ) && $input['soft_search_bot_mode'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_mailru_bot'] = ( isset( $input['allow_mailru_bot'] ) && $input['allow_mailru_bot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_bingbot']   = ( isset( $input['allow_bingbot'] ) && $input['allow_bingbot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_duckduckbot']   = ( isset( $input['allow_duckduckbot'] ) && $input['allow_duckduckbot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_baiduspider']   = ( isset( $input['allow_baiduspider'] ) && $input['allow_baiduspider'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_applebot']      = ( isset( $input['allow_applebot'] ) && $input['allow_applebot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_gptbot']        = ( isset( $input['allow_gptbot'] ) && $input['allow_gptbot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_chatgpt_user']  = ( isset( $input['allow_chatgpt_user'] ) && $input['allow_chatgpt_user'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_claudebot']     = ( isset( $input['allow_claudebot'] ) && $input['allow_claudebot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_perplexitybot'] = ( isset( $input['allow_perplexitybot'] ) && $input['allow_perplexitybot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_ccbot']         = ( isset( $input['allow_ccbot'] ) && $input['allow_ccbot'] == 1 ) ? 1 : 0;
        $sanitized_input['allow_bytespider']    = ( isset( $input['allow_bytespider'] ) && $input['allow_bytespider'] == 1 ) ? 1 : 0;

        if ( isset( $input['ssl_verify_api'] ) ) {
            $sanitized_input['ssl_verify_api'] = ( $input['ssl_verify_api'] == 1 ) ? 1 : 0;
        }
        $sanitized_input['captcha_enabled_admin'] = ( isset( $input['captcha_enabled_admin'] ) && $input['captcha_enabled_admin'] == 1 ) ? 1 : 0;
        $sanitized_input['captcha_enabled_users'] = ( isset( $input['captcha_enabled_users'] ) && $input['captcha_enabled_users'] == 1 ) ? 1 : 0;
        if ( isset( $input['captcha_client_key'] ) ) {
            $sanitized_input['captcha_client_key'] = sanitize_text_field( trim( $input['captcha_client_key'] ) );
        }
        if ( isset( $input['captcha_server_key'] ) ) {
            $sanitized_input['captcha_server_key'] = sanitize_text_field( trim( $input['captcha_server_key'] ) );
        }

        $is_premium = ( get_option( 'rls_license_status' ) === 'valid' );
        $sanitized_input['language_filter_enabled'] = ( isset( $input['language_filter_enabled'] ) && $input['language_filter_enabled'] == 1 ) ? 1 : 0;
        if ( isset( $input['language_mode'] ) ) {
            $language_mode = sanitize_text_field( $input['language_mode'] );
            $sanitized_input['language_mode'] = in_array( $language_mode, [ 'allow', 'block' ], true ) ? $language_mode : 'allow';
        }
        if ( isset( $input['language_codes'] ) ) {
            $raw = is_array( $input['language_codes'] ) ? $input['language_codes'] : explode( ',', (string) $input['language_codes'] );
            $codes = [];
            foreach ( $raw as $code ) {
                $lang = strtolower( preg_replace( '/[^a-z]/i', '', (string) $code ) );
                if ( preg_match( '/^[a-z]{2,3}$/', $lang ) ) {
                    $codes[] = $lang;
                }
            }
            $sanitized_input['language_codes'] = array_values( array_unique( $codes ) );
        }

        $sanitized_input['geo_blocking_enabled'] = ( isset( $input['geo_blocking_enabled'] ) && $input['geo_blocking_enabled'] == 1 ) ? 1 : 0;
        if ( isset( $input['geo_mode'] ) ) {
            $mode = sanitize_text_field( $input['geo_mode'] );
            $sanitized_input['geo_mode'] = in_array( $mode, [ 'allow', 'block' ], true ) ? $mode : 'block';
        }
        if ( isset( $input['geo_countries'] ) ) {
            $raw = is_array( $input['geo_countries'] ) ? $input['geo_countries'] : explode( ',', (string) $input['geo_countries'] );
            $countries = [];
            foreach ( $raw as $country ) {
                $code = strtoupper( preg_replace( '/[^A-Z]/i', '', (string) $country ) );
                if ( preg_match( '/^[A-Z]{2}$/', $code ) ) {
                    $countries[] = $code;
                }
            }
            $sanitized_input['geo_countries'] = array_values( array_unique( $countries ) );
        }
        if ( isset( $input['geo_countries_allow'] ) ) {
            $raw = is_array( $input['geo_countries_allow'] ) ? $input['geo_countries_allow'] : explode( ',', (string) $input['geo_countries_allow'] );
            $countries = [];
            foreach ( $raw as $country ) {
                $code = strtoupper( preg_replace( '/[^A-Z]/i', '', (string) $country ) );
                if ( preg_match( '/^[A-Z]{2}$/', $code ) ) {
                    $countries[] = $code;
                }
            }
            $countries = array_values( array_unique( $countries ) );
            if ( ! $is_premium ) {
                $countries = array_slice( $countries, 0, 3 );
            }
            $sanitized_input['geo_countries_allow'] = $countries;
        }
        if ( isset( $input['geo_countries_block'] ) ) {
            $raw = is_array( $input['geo_countries_block'] ) ? $input['geo_countries_block'] : explode( ',', (string) $input['geo_countries_block'] );
            $countries = [];
            foreach ( $raw as $country ) {
                $code = strtoupper( preg_replace( '/[^A-Z]/i', '', (string) $country ) );
                if ( preg_match( '/^[A-Z]{2}$/', $code ) ) {
                    $countries[] = $code;
                }
            }
            $countries = array_values( array_unique( $countries ) );
            if ( ! $is_premium ) {
                $countries = array_slice( $countries, 0, 5 );
            }
            $sanitized_input['geo_countries_block'] = $countries;
        }

        // Backward-compat поле синхронизируем с актуальными списками,
        // чтобы поведение GeoIP было предсказуемым при миграции настроек.
        $allow_sync = array_values( (array) ( $sanitized_input['geo_countries_allow'] ?? [] ) );
        $block_sync = array_values( (array) ( $sanitized_input['geo_countries_block'] ?? [] ) );
        $sanitized_input['geo_countries'] = array_values( array_unique( array_merge( $allow_sync, $block_sync ) ) );

        if ( isset( $input['rls_setup_completed'] ) && (int) $input['rls_setup_completed'] === 1 ) {
            update_option( 'rls_setup_completed', 1 );
        }

        return $sanitized_input;
    }

    // --- AJAX пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ ---

    public function ajax_save_uninstall_pref() {
        if ( ! current_user_can( 'activate_plugins' ) ) wp_send_json_error();
        if ( ! check_ajax_referer( 'rls_settings_nonce', 'nonce', false ) ) wp_send_json_error();

        $wipe = ( isset($_POST['wipe']) && $_POST['wipe'] === 'true' );
        update_option( 'rls_wipe_data_on_uninstall', $wipe );
        wp_send_json_success();
    }

    // --- пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ (AI + CHECKSUMS + SIZE CHECK) ---
    public function ajax_neutralize_file() {
        check_ajax_referer('rls_scanner_nonce', 'nonce'); 
        if (!current_user_can('manage_options')) wp_send_json_error('Доступ запрещен.');
        
        // пїЅпїЅпїЅпїЅпїЅ: пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ wp_normalize_path пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ
        $filepath = wp_normalize_path( trim(stripslashes($_POST['filepath'] ?? '')) ); 
        $signature = trim(stripslashes($_POST['signature'] ?? ''));
        
        if (empty($filepath) || !file_exists($filepath) || !is_readable($filepath)) wp_send_json_error('Файл недоступен.');
        
        // 1. пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ WP
        require_once( ABSPATH . 'wp-admin/includes/update.php' );
        
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ (пїЅпїЅ пїЅпїЅпїЅпїЅпїЅ WP)
        $relative = str_replace( wp_normalize_path(ABSPATH), '', $filepath );
        
        global $wp_version;
        $checksums = get_core_checksums( $wp_version, get_locale() );
        
        if ( is_array($checksums) && isset( $checksums[$relative] ) ) {
            if ( md5_file($filepath) === $checksums[$relative] ) {
                $this->add_to_whitelist($filepath);
                wp_send_json_success(['result' => 'whitelisted']); 
                return;
            }
        }

        // 2. пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ
        $filesize = @filesize($filepath);
        if ( $filesize > 204800 ) { // > 100 пїЅпїЅ
            wp_send_json_success(['result' => 'too_large']);
            return;
        }

        // 3. пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        $lines = file($filepath, FILE_IGNORE_NEW_LINES); 
        $snip = "";
        $found_sig = false;

        // пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ, пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        if ( !empty($signature) ) {
            foreach($lines as $k=>$l) {
                if(strpos($l, $signature) !== false) { 
                    $start = max(0, $k-3); 
                    $end = min(count($lines)-1, $k+3);
                    for($i=$start; $i<=$end; $i++) $snip.="L".($i+1).": ".$lines[$i]."\n"; 
                    $found_sig = true;
                    break; 
                }
            }
        }
        
        // пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ (пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ, пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ), пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ
        if ( !$found_sig ) {
            $content = file_get_contents($filepath);
            $snip = substr($content, 0, 1500); 
        }
        
        if(!$snip) wp_send_json_error('Не удалось подготовить фрагмент кода.');
        
        // 4. пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅ AI
        if ( class_exists('RLS_API_Client') ) {
            $ai = RLS_API_Client::analyze_code_snippet($snip);
            
            if(!is_wp_error($ai) && isset($ai['data']['verdict'])) {
                if($ai['data']['verdict'] === 'Virus') {
                    wp_send_json_success(['result' => 'ai_virus', 'snippet' => $snip]);
                } else { 
                    $this->add_to_whitelist($filepath); 
                    wp_send_json_success(['result' => 'ai_legitimate']); 
                }
            } else {
                wp_send_json_error('Не удалось выполнить AI-анализ.');
            }
        } else {
            wp_send_json_error('API недоступно.');
        }
    }

    private function add_to_whitelist( $filepath ) {
        // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
        $filepath = wp_normalize_path( $filepath );
        $w = get_option('rls_whitelist', []); 
        $w[$filepath] = [
            'hash'  => md5_file($filepath),
            'mtime' => (int) @filemtime($filepath),
        ];
        update_option('rls_whitelist', $w, false); 
    }

    public function ajax_add_ip_list() {
        check_ajax_referer( 'rls_settings_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Доступ запрещен.' );

        $ip = sanitize_text_field( $_POST['ip'] );
        $list_type = sanitize_text_field( $_POST['list'] ); 

        if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) wp_send_json_error( 'Некорректный IP.' );

        $opt_name = ( $list_type === 'white' ) ? 'rls_ip_whitelist' : 'rls_manual_blacklist';
        $list = get_option( $opt_name, [] );

        if ( ! in_array( $ip, $list ) ) {
            $list[] = $ip;
            update_option( $opt_name, $list );
            
            if ( $list_type === 'black' && class_exists('RLS_API_Client') ) {
                RLS_API_Client::submit_banned_ip( $ip, 'Manual Ban by Admin' );
            }
        }

        wp_send_json_success( [ 'ip' => $ip, 'list' => $list_type ] );
    }

    public function ajax_delete_ip_list() {
        check_ajax_referer( 'rls_settings_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Доступ запрещен.' );

        $ip = sanitize_text_field( $_POST['ip'] );
        $list_type = sanitize_text_field( $_POST['list'] );
        
        $opt_name = ( $list_type === 'white' ) ? 'rls_ip_whitelist' : 'rls_manual_blacklist';
        $list = get_option( $opt_name, [] );
        
        $key = array_search( $ip, $list );
        if ( $key !== false ) {
            unset( $list[$key] );
            update_option( $opt_name, array_values( $list ) );
        }
        wp_send_json_success();
    }

    public function ajax_unblock_ip() {
        check_ajax_referer( 'rls_settings_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Доступ запрещен.' );

        $ip = sanitize_text_field( $_POST['ip'] ?? '' );
        if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
            wp_send_json_error( 'Некорректный IP.' );
        }

        $changed = false;

        $blocked = get_option( 'rls_blocked_ips', [] );
        if ( is_array( $blocked ) && isset( $blocked[ $ip ] ) ) {
            unset( $blocked[ $ip ] );
            update_option( 'rls_blocked_ips', $blocked, false );
            $changed = true;
        }

        $locked = get_option( 'rls_locked_ips', [] );
        if ( is_array( $locked ) && isset( $locked[ $ip ] ) ) {
            unset( $locked[ $ip ] );
            update_option( 'rls_locked_ips', $locked );
            $changed = true;
        }

        wp_send_json_success( [ 'removed' => $changed ] );
    }

    public function ajax_add_signature() {
        check_ajax_referer( 'rls_signatures_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Доступ запрещен.' );
        $signature = trim( stripslashes( $_POST['signature'] ?? '' ) );
        if ( empty( $signature ) ) wp_send_json_error( 'Введите сигнатуру.' );
        $custom = get_option( 'rls_custom_signatures', [] );
        if ( ! in_array( $signature, $custom ) ) {
            $custom[] = $signature;
            update_option( 'rls_custom_signatures', $custom );
            try { RLS_API_Client::submit_suggestion( $signature ); } catch ( Exception $e ) {}
        }
        wp_send_json_success( [ 'signature' => esc_html( $signature ) ] );
    }
    
    public function ajax_delete_signature() {
        check_ajax_referer( 'rls_signatures_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Доступ запрещен.' );
        $signature = trim( stripslashes( $_POST['signature'] ?? '' ) );
        $custom = get_option( 'rls_custom_signatures', [] );
        $key = array_search( $signature, $custom );
        if ( $key !== false ) {
            unset( $custom[ $key ] );
            update_option( 'rls_custom_signatures', array_values( $custom ) );
        }
        wp_send_json_success();
    }

    public function ajax_add_login_question() {
        check_ajax_referer('rls_login_questions_nonce', 'nonce'); 
        if(!current_user_can('manage_options')) wp_send_json_error();
        
        $q = trim(stripslashes($_POST['question'] ?? '')); 
        $a = trim(stripslashes($_POST['answer'] ?? ''));
        
        if($q && $a) { 
            $qs = get_option('rls_login_questions', []); 
            $qs[] = ['q' => $q, 'a' => password_hash($a, PASSWORD_DEFAULT)]; 
            update_option('rls_login_questions', $qs); 
            wp_send_json_success(['key' => count($qs)-1, 'q' => esc_html($q)]); 
        } 
        wp_send_json_error();
    }
    
    public function ajax_delete_login_question() {
        check_ajax_referer('rls_login_questions_nonce', 'nonce'); 
        if(!current_user_can('manage_options')) wp_send_json_error();
        
        $key = intval($_POST['key']); 
        $qs = get_option('rls_login_questions', []); 
        
        if(isset($qs[$key])) { 
            unset($qs[$key]); 
            update_option('rls_login_questions', array_values($qs)); 
        } 
        wp_send_json_success();
    }
    
    public function ajax_sync_stats() { 
        wp_send_json_success(); 
    }

    public function ajax_clear_attack_logs() {
        check_ajax_referer( 'rls_settings_nonce', 'nonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( 'Доступ запрещен.' );
        }

        if ( ! class_exists( 'RLS_Logger' ) ) {
            wp_send_json_error( 'Логгер недоступен.' );
        }

        $deleted_count = RLS_Logger::clear_logs();

        if ( class_exists( 'RLS_API_Client' ) ) {
            RLS_API_Client::report_attack_log_cleanup( $deleted_count );
        }

        wp_send_json_success( [ 'deleted_count' => (int) $deleted_count ] );
    }
}



