<?php
/**
 * VMPFence Firewall Options AJAX Handler
 * 
 * @package VMPFence
 * @since 2.0.0
 * @since 2.1.2 -- Rule_id column issue fix and firewall detailed summary table fixed to have responsive layout
 * @since 2.2.3 - Added enable/disable extended protection AJAX handlers
 * @since 2.2.4 - Refactored enable/disable extended protection to use WAF Optimizer class
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

class VMPFence_Firewall_Options_Ajax {
    
    public function __construct() {
        add_action('wp_ajax_vmpfence_save_brute_force_settings', array($this, 'save_brute_force_settings'));
        add_action('wp_ajax_vmpfence_restore_brute_force_defaults', array($this, 'restore_brute_force_defaults'));
        add_action('wp_ajax_vmpfence_load_brute_force_settings', array($this, 'load_brute_force_settings'));
        add_action('wp_ajax_vmpfence_enable_firewall', array($this, 'enable_firewall'));
        add_action('wp_ajax_vmpfence_load_firewall_summary', array($this, 'load_firewall_summary'));
        add_action('wp_ajax_vmpfence_get_attack_timeline', array($this, 'get_attack_timeline'));
        add_action('wp_ajax_vmpfence_enable_extended_protection', array($this, 'enable_extended_protection'));
        add_action('wp_ajax_vmpfence_disable_extended_protection', array($this, 'disable_extended_protection'));
    }
    
    /**
     * Save brute force settings
     */
    public function save_brute_force_settings() {
        // Check if VMPFence_Config class exists
        if (!class_exists('VMPFence_Config')) {
            wp_send_json_error(array(
                'message' => 'Configuration class not available'
            ));
            return;
        }
        
        // Verify nonce
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'vmpfence_firewall_options')) {
            wp_die('Security check failed');
        }
        
        try {
            $saved_count = 0;
            $failed_saves = array();
            
            // Boolean settings
            $boolean_settings = array(
                'brute_force_enabled' => filter_var($_POST['brute_force_enabled'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'lock_invalid_usernames' => filter_var($_POST['lock_invalid_usernames'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'prevent_leaked_passwords_enabled' => filter_var($_POST['prevent_leaked_passwords_enabled'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'enforce_strong_passwords' => filter_var($_POST['enforce_strong_passwords'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'dont_reveal_users' => filter_var($_POST['dont_reveal_users'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'prevent_admin_username' => filter_var($_POST['prevent_admin_username'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'prevent_username_discovery' => filter_var($_POST['prevent_username_discovery'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'disable_app_passwords' => filter_var($_POST['disable_app_passwords'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'block_post_requests' => filter_var($_POST['block_post_requests'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'check_password_strength' => filter_var($_POST['check_password_strength'] ?? false, FILTER_VALIDATE_BOOLEAN),
                'participate_security_network' => filter_var($_POST['participate_security_network'] ?? false, FILTER_VALIDATE_BOOLEAN)
            );
            
            foreach ($boolean_settings as $setting => $value) {
                $db_value = $value ? 1 : 0;
                $result = VMPFence_Config::set($setting, $db_value);
                if ($result !== false) {
                    $saved_count++;
                } else {
                    $failed_saves[] = $setting;
                }
            }
            
            // Integer settings
            $integer_settings = array(
                'max_login_attempts' => 'max_login_attempts',
                'max_forgot_password_attempts' => 'max_forgot_password_attempts',
                'count_failures_window' => 'count_failures_window',
                'lockout_duration' => 'lockout_duration',
                'permanent_ban_threshold' => 'permanent_ban_threshold'
            );
            
            foreach ($integer_settings as $post_key => $config_key) {
                if (isset($_POST[$post_key])) {
                    $value = intval(sanitize_text_field(wp_unslash($_POST[$post_key])));
                } else {
                    // Provide default values for missing fields
                    $defaults = array(
                        'permanent_ban_threshold' => 10
                    );
                    $value = isset($defaults[$config_key]) ? $defaults[$config_key] : 0;
                }
                
                $result = VMPFence_Config::set($config_key, $value);
                if ($result !== false) {
                    $saved_count++;
                } else {
                    $failed_saves[] = $config_key;
                }
            }
            
            // String settings
            $string_settings = array(
                'prevent_leaked_passwords_scope' => 'prevent_leaked_passwords_scope',
                'strong_passwords_scope' => 'strong_passwords_scope',
                'custom_block_text' => 'custom_block_text'
            );
            
            foreach ($string_settings as $post_key => $config_key) {
                if (isset($_POST[$post_key])) {
                    $value = sanitize_text_field(wp_unslash($_POST[$post_key]));
                    $result = VMPFence_Config::set($config_key, $value);
                    if ($result !== false) {
                        $saved_count++;
                    } else {
                        $failed_saves[] = $config_key;
                    }
                }
            }
            
            // Array settings (blocked usernames)
            if (isset($_POST['blocked_usernames'])) {
                $blocked_usernames = sanitize_textarea_field(wp_unslash($_POST['blocked_usernames']));
                $usernames_array = array_filter(array_map('trim', explode("\n", $blocked_usernames)));
                $result = VMPFence_Config::set('blocked_usernames', $usernames_array);
                if ($result !== false) {
                    $saved_count++;
                } else {
                    $failed_saves[] = 'blocked_usernames';
                }
            }
            
            $response_data = array(
                'message' => 'Firewall settings saved successfully',
                'saved_count' => $saved_count,
                'failed_count' => count($failed_saves),
                'failed_settings' => $failed_saves
            );
            
            wp_send_json_success($response_data);
            
        } catch (Exception $e) {
            wp_send_json_error(array(
                'message' => 'Error saving settings: ' . $e->getMessage()
            ));
        }
    }
    
    /**
     * Restore brute force defaults
     */
    public function restore_brute_force_defaults() {
        // Check if VMPFence_Config class exists
        if (!class_exists('VMPFence_Config')) {
            wp_send_json_error(array(
                'message' => 'Configuration class not available'
            ));
            return;
        }
        
        // Verify nonce
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'vmpfence_firewall_options')) {
            wp_die('Security check failed');
        }
        
        try {
            // Default values
            $defaults = array(
                'brute_force_enabled' => 1,
                'max_login_attempts' => 20,
                'max_forgot_password_attempts' => 20,
                'count_failures_window' => 240,
                'lockout_duration' => 240,
                'lock_invalid_usernames' => 0,
                'blocked_usernames' => array(),
                'prevent_leaked_passwords_enabled' => 0,
                'prevent_leaked_passwords_scope' => 'admin',
                'enforce_strong_passwords' => 1,
                'strong_passwords_scope' => 'recommended',
                'dont_reveal_users' => 1,
                'prevent_admin_username' => 1,
                'prevent_username_discovery' => 1,
                'disable_app_passwords' => 1,
                'block_post_requests' => 0,
                'custom_block_text' => '',
                'check_password_strength' => 1,
                'participate_security_network' => 1,
                'permanent_ban_threshold' => 10
            );
            
            $saved_count = 0;
            $failed_restores = array();
            
            // Save defaults to database
            foreach ($defaults as $setting => $value) {
                $result = VMPFence_Config::set($setting, $value);
                if ($result !== false) {
                    $saved_count++;
                } else {
                    $failed_restores[] = $setting;
                }
            }
            
            $response_data = array(
                'message' => 'Default brute force settings restored successfully',
                'defaults' => $defaults,
                'restored_count' => $saved_count,
                'failed_count' => count($failed_restores),
                'failed_settings' => $failed_restores
            );
            
            wp_send_json_success($response_data);
            
        } catch (Exception $e) {
            wp_send_json_error(array(
                'message' => 'Error restoring defaults: ' . $e->getMessage()
            ));
        }
    }
    
    /**
     * Load current brute force settings
     */
    public function load_brute_force_settings() {
        // Verify nonce
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'vmpfence_firewall_options')) {
            wp_die('Security check failed');
        }
        
        try {
            // Load current saved configuration values
            $settings = array(
                // Boolean settings
                'brute_force_enabled' => VMPFence_Config::get('brute_force_enabled', 1),
                'lock_invalid_usernames' => VMPFence_Config::get('lock_invalid_usernames', 0),
                'prevent_leaked_passwords_enabled' => VMPFence_Config::get('prevent_leaked_passwords_enabled', 0),
                'enforce_strong_passwords' => VMPFence_Config::get('enforce_strong_passwords', 1),
                'dont_reveal_users' => VMPFence_Config::get('dont_reveal_users', 1),
                'prevent_admin_username' => VMPFence_Config::get('prevent_admin_username', 1),
                'prevent_username_discovery' => VMPFence_Config::get('prevent_username_discovery', 1),
                'disable_app_passwords' => VMPFence_Config::get('disable_app_passwords', 1),
                'block_post_requests' => VMPFence_Config::get('block_post_requests', 0),
                'check_password_strength' => VMPFence_Config::get('check_password_strength', 1),
                'participate_security_network' => VMPFence_Config::get('participate_security_network', 1),
                
                // Integer settings
                'max_login_attempts' => VMPFence_Config::get('max_login_attempts', 20),
                'max_forgot_password_attempts' => VMPFence_Config::get('max_forgot_password_attempts', 20),
                'count_failures_window' => VMPFence_Config::get('count_failures_window', 240),
                'lockout_duration' => VMPFence_Config::get('lockout_duration', 240),
                'permanent_ban_threshold' => VMPFence_Config::get('permanent_ban_threshold', 10),
                
                // String settings
                'prevent_leaked_passwords_scope' => VMPFence_Config::get('prevent_leaked_passwords_scope', 'admin'),
                'strong_passwords_scope' => VMPFence_Config::get('strong_passwords_scope', 'recommended'),
                'custom_block_text' => VMPFence_Config::get('custom_block_text', ''),
                
                // Array settings
                'blocked_usernames' => VMPFence_Config::get('blocked_usernames', array())
            );
            
            wp_send_json_success(array(
                'message' => 'Settings loaded successfully',
                'settings' => $settings
            ));
            
        } catch (Exception $e) {
            wp_send_json_error(array(
                'message' => 'Error loading settings: ' . $e->getMessage()
            ));
        }
    }
    
    /**
     * Enable firewall
     */
    public function enable_firewall() {
        // Verify nonce
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'vmpfence_firewall_nonce')) {
            wp_die('Security check failed');
        }
        
        try {
            // Enable WAF (Web Application Firewall)
            VMPFence_Config::set('waf_enabled', 1);
            
            wp_send_json_success(array(
                'message' => 'Firewall enabled successfully'
            ));
            
        } catch (Exception $e) {
            wp_send_json_error(array(
                'message' => 'Error enabling firewall: ' . $e->getMessage()
            ));
        }
    }
    
    /**
     * Load firewall summary table data
     */
    public function load_firewall_summary() {
        // Verify nonce
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'vmpfence_firewall_nonce')) {
            wp_die('Security check failed');
        }
        
        // Get filter parameter
        $filter = isset($_POST['filter']) ? sanitize_text_field(wp_unslash($_POST['filter'])) : 'today';
        
        global $wpdb;
        $table_name = $wpdb->prefix . 'vmpfence_waf_log';
        
        // Get attack counts for stats
        $stats_today = (int) $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE action LIKE 'block%' AND attackLogTime >= UNIX_TIMESTAMP(CURDATE())");
        $stats_7days = (int) $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE action LIKE 'block%' AND attackLogTime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 7 DAY))");
        $stats_30days = (int) $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE action LIKE 'block%' AND attackLogTime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))");
        $stats_all = (int) $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE action LIKE 'block%'");
        
        // Build time condition based on filter
        $time_condition = '';
        switch ($filter) {
            case 'today':
                $time_condition = 'AND attackLogTime >= UNIX_TIMESTAMP(CURDATE())';
                break;
            case '7days':
                $time_condition = 'AND attackLogTime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 7 DAY))';
                break;
            case '30days':
                $time_condition = 'AND attackLogTime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))';
                break;
            default:
                $time_condition = '';
        }
        
        // Get recent blocked attacks from WAF log
        $recent_attacks = $wpdb->get_results(
            "SELECT 
                id,
                DATE_FORMAT(FROM_UNIXTIME(attackLogTime), '%Y-%m-%d %H:%i:%s') as created_at,
                INET6_NTOA(IP) as ip_address,
                actionDescription as attack_description,
                actionData,
                logMsg,
                action,
                severity
            FROM $table_name 
            WHERE action LIKE 'block%' {$time_condition}
            GROUP BY id
            ORDER BY attackLogTime DESC 
            LIMIT 50",
            ARRAY_A
        );
        
        // Parse violations from actionData
        foreach ($recent_attacks as &$attack) {
            $data = json_decode($attack['actionData'], true);
            if (!empty($data['violated_rules']) && is_array($data['violated_rules'])) {
                $first_violation = reset($data['violated_rules']);
                $attack['attack_type'] = isset($first_violation['category']) ? $first_violation['category'] : 'Unknown';
                $attack['rule_id'] = isset($first_violation['rule_id']) ? $first_violation['rule_id'] : 'N/A';
            } else {
                $attack['attack_type'] = 'Unknown';
                $attack['rule_id'] = 'N/A';
            }
        }
        unset($attack); // Break the reference to avoid bugs in the next foreach

        // Build HTML response
        ob_start();
        ?>
        <div style="background: #f8f9fa; padding: 15px; border-radius: 6px; margin-bottom: 20px;">
            <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; text-align: center;">
                <div>
                    <div style="font-size: 28px; font-weight: 700; color: #191970; margin-bottom: 5px;"><?php echo number_format($stats_today); ?></div>
                    <div style="font-size: 13px; color: #666;">Blocked Today</div>
                </div>
                <div>
                    <div style="font-size: 28px; font-weight: 700; color: #191970; margin-bottom: 5px;"><?php echo number_format($stats_7days); ?></div>
                    <div style="font-size: 13px; color: #666;">Last 7 Days</div>
                </div>
                <div>
                    <div style="font-size: 28px; font-weight: 700; color: #191970; margin-bottom: 5px;"><?php echo number_format($stats_30days); ?></div>
                    <div style="font-size: 13px; color: #666;">Last 30 Days</div>
                </div>
                <div>
                    <div style="font-size: 28px; font-weight: 700; color: #191970; margin-bottom: 5px;"><?php echo number_format($stats_all); ?></div>
                    <div style="font-size: 13px; color: #666;">All Time</div>
                </div>
            </div>
        </div>
        
        <table class="wp-list-table widefat striped" style="table-layout: auto;">
            <thead>
                <tr>
                    <th style="width: 140px;">Date/Time</th>
                    <th style="width: 130px;">IP Address</th>
                    <th style="width: 120px;">Attack Type</th>
                    <!-- <th style="width: 10%;">Rule ID</th> -->
                    <th style="width: auto;">Description</th>
                    <th style="width: 90px;">Status</th>
                </tr>
            </thead>
            <tbody>
                <?php if (!empty($recent_attacks)): ?>
                    <?php foreach ($recent_attacks as $attack): ?>
                    <tr>
                        <td><?php echo esc_html($attack['created_at']); ?></td>
                        <td><?php echo esc_html($attack['ip_address'] ?: 'Unknown'); ?></td>
                        <td>
                            <span class="badge badge-<?php echo esc_attr(strtolower($attack['attack_type'])); ?>">
                                <?php echo esc_html($attack['attack_type']); ?>
                            </span>
                        </td>
                        <!-- <td><code><?php echo esc_html($attack['rule_id']); ?></code></td> -->
                        <td style="word-wrap: break-word; overflow-wrap: break-word; white-space: normal; max-width: 400px;"><?php echo esc_html($attack['logMsg']); ?></td>
                        <td><span class="vmpfence-status-blocked">Blocked</span></td>
                    </tr>
                    <?php endforeach; ?>
                <?php else: ?>
                    <tr>
                        <td colspan="6" style="text-align: center; padding: 20px;">
                            <em><?php _e('No blocked attacks recorded yet. The firewall is active and monitoring your site.', 'vmpfence-security'); ?></em>
                        </td>
                    </tr>
                <?php endif; ?>
            </tbody>
        </table>
        <?php
        $html = ob_get_clean();
        
        wp_send_json_success(array(
            'html' => $html
        ));
    }
    
    /**
     * Get network-wide attack timeline for chart
     * 
     * @since 2.0.0
     */
    public function get_attack_timeline() {
        // Check user permissions
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Insufficient permissions'));
            return;
        }
        
        // Verify nonce
        $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, 'vmpfence_firewall_nonce')) {
            wp_send_json_error(array('message' => 'Security check failed'));
            return;
        }
        
        // Get period parameter
        $period = isset($_POST['period']) ? sanitize_text_field(wp_unslash($_POST['period'])) : '24h';
        
        // Validate period
        if (!in_array($period, array('24h', '30d'))) {
            wp_send_json_error(array('message' => 'Invalid period'));
            return;
        }
        
        // Get API key from config
        $api_key = VMPFence_Config::get('central_api_key', '');
        if (empty($api_key)) {
            wp_send_json_error(array('message' => 'API key not configured'));
            return;
        }
        
        // Call API
        $api_client = new VMPFence_API_Client();
        $response = $api_client->get_attack_timeline($api_key, $period);
        
        if (is_wp_error($response)) {
            wp_send_json_error(array(
                'message' => $response->get_error_message()
            ));
            return;
        }
        
        // Return timeline data
        wp_send_json_success($response);
    }
    
    /**
     * Enable Extended Protection
     * @since 2.0.0
     * @since 2.2.4 - Updated to use WAF Optimizer
     */
    public function enable_extended_protection() {        
        // Verify nonce
        check_ajax_referer('vmpfence_protection_level_nonce', 'nonce');
        
        // Check user permissions
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Unauthorized');
            return;
        }
        
        // Check if WAF Optimizer class exists
        if (!class_exists('VMPFence_WAF_Optimizer')) {
            wp_send_json_error(array(
                'message' => 'WAF Optimizer not available. Please contact support.'
            ));
            return;
        }
        
        // Call WAF Optimizer to perform optimization
        $result = VMPFence_WAF_Optimizer::optimize_firewall();
        
        if ($result['success']) {
            wp_send_json_success(array(
                'message' => $result['message'],
                'waf_file_path' => isset($result['waf_file_path']) ? $result['waf_file_path'] : ''
            ));
        } else {
            wp_send_json_error(array(
                'message' => $result['message']
            ));
        }
    }
    
    /**
     * Disable Extended Protection
     * @since 2.0.0
     * @since 2.2.4 - Updated to use WAF Optimizer
     *
     */
    public function disable_extended_protection() {        
        // Verify nonce
        check_ajax_referer('vmpfence_protection_level_nonce', 'nonce');
        
        // Check user permissions
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Unauthorized');
            return;
        }
        
        // Check if WAF Optimizer class exists
        if (!class_exists('VMPFence_WAF_Optimizer')) {
            wp_send_json_error(array(
                'message' => 'WAF Optimizer not available. Please contact support.'
            ));
            return;
        }
        
        // Call WAF Optimizer to remove optimization
        $result = VMPFence_WAF_Optimizer::remove_optimization();
        
        if ($result['success']) {
            wp_send_json_success(array(
                'message' => $result['message']
            ));
        } else {
            wp_send_json_error(array(
                'message' => $result['message']
            ));
        }
    }
}

// Initialize the AJAX handler
new VMPFence_Firewall_Options_Ajax();