<?php
/**
 * Advanced Adaptive Protection System for BotFend Anti-Bot Firewall
 * ENHANCED VERSION with Predictive Analytics, Pattern Recognition, and Auto-Optimization
 *
 * @package BotFend\Adaptive
 * @since 4.0.0
 * @version 4.8.3 - Rebranded from SafeBot, external services disabled by default, file storage fixed
 */

namespace BotFend\Adaptive;

use BotFend\Core\Config;

defined('ABSPATH') || exit;

/**
 * Class Adaptive
 *
 * Advanced adaptive protection with predictive analytics and pattern recognition
 */
class Adaptive {
    
    private $config;
    private $modes = [];
    private $current_mode = 'balanced';
    private $mode_history = [];
    private $attack_log = [];
    private $attack_level = 0;
    private $predictive_risk = 0;
    private $mode_effectiveness = [];
    private $calculating = false;
    private $calculation_start_time = 0;
    private $calculation_timeout = 30; // 30 seconds timeout
    private $wpdb;
    
    /**
     * Cache table existence to prevent repeated slow SHOW TABLES queries
     */
    private $tables_verified = [];
    
    /**
     * Cache for SHOW TABLES results
     */
    private static $global_table_cache = [];
    
    public function __construct() {
        global $wpdb;
        $this->wpdb = $wpdb;
        $this->config = Config::get_instance();
        
        $this->modes = [
            'learning' => [
                'block_score' => 9,
                'challenge_score' => 7,
                'rate_limit' => 200,
                'sampling_rate' => 0.1,
                'description' => esc_html__('Learning mode: Minimum protection, maximum data collection', 'botfend-anti-bot-firewall')
            ],
            'balanced' => [
                'block_score' => 8,
                'challenge_score' => 6,
                'rate_limit' => 100,
                'sampling_rate' => 0.3,
                'description' => esc_html__('Balanced mode: Standard protection for most websites', 'botfend-anti-bot-firewall')
            ],
            'aggressive' => [
                'block_score' => 6,
                'challenge_score' => 4,
                'rate_limit' => 50,
                'sampling_rate' => 0.7,
                'description' => esc_html__('Aggressive mode: High protection for targeted attacks', 'botfend-anti-bot-firewall')
            ],
            'emergency' => [
                'block_score' => 4,
                'challenge_score' => 2,
                'rate_limit' => 20,
                'sampling_rate' => 1.0,
                'description' => esc_html__('Emergency mode: Maximum protection during attacks', 'botfend-anti-bot-firewall')
            ]
        ];
        
        add_filter('cron_schedules', [$this, 'add_cron_schedules']);
        $this->load_settings();
        
        // Use unique hook name to avoid conflicts
        add_action('botfend_adaptive_calculate_attack_level', [$this, 'scheduled_calculate_enhanced_attack_level']);
        
        // FIXED: Check if schedule exists before scheduling to prevent "invalid_schedule" error
        $this->schedule_cron_event();
        
        $this->calculate_enhanced_attack_level();
        $this->analyze_mode_patterns();
        $this->optimize_mode_selection();
    }
    
    /**
     * Schedule cron event with proper schedule existence check
     * Prevents "invalid_schedule" error during plugin activation/deactivation
     *
     * @since 4.8.4
     * @return void
     */
    private function schedule_cron_event(): void {
        // Get available schedules
        $schedules = wp_get_schedules();
        
        // Check if five_minutes schedule exists (it should, after add_filter)
        if (isset($schedules['five_minutes'])) {
            $schedule_name = 'five_minutes';
        } else {
            // Fallback to 'hourly' if custom schedule not yet registered
            $schedule_name = 'hourly';
            
            // Log fallback usage only in debug mode
            if (defined('WP_DEBUG') && WP_DEBUG && $this->config->get_bool('debug_mode', false)) {
                error_log('BotFend Adaptive: Five minutes schedule not available, falling back to hourly');
            }
        }
        
        // Only schedule if not already scheduled
        if (!wp_next_scheduled('botfend_adaptive_calculate_attack_level')) {
            wp_schedule_event(time(), $schedule_name, 'botfend_adaptive_calculate_attack_level');
        }
    }
    
    public function add_cron_schedules($schedules) {
        $schedules['five_minutes'] = [
            'interval' => 300,
            'display' => esc_html__('Every 5 minutes', 'botfend-anti-bot-firewall')
        ];
        return $schedules;
    }
    
    public function scheduled_calculate_enhanced_attack_level() {
        $this->calculate_enhanced_attack_level();
        $this->analyze_mode_patterns();
        $this->optimize_mode_selection();
    }
    
    private function load_settings() {
        $saved_mode = $this->config->get_string('adaptive_mode', 'balanced');
        if (isset($this->modes[$saved_mode])) {
            $this->current_mode = $saved_mode;
        }
        $this->mode_history = get_option('botfend_mode_history', []);
        $this->attack_log = get_option('botfend_attack_log', []);
        $this->mode_effectiveness = get_option('botfend_mode_effectiveness', []);
    }
    
    /**
     * Check if table exists (Optimized with global cache)
     * FIXED: Caches results to prevent repeated SHOW TABLES queries
     */
    private function table_exists($table_name) {
        // Check global cache first (persists across instances)
        if (isset(self::$global_table_cache[$table_name])) {
            return self::$global_table_cache[$table_name];
        }
        
        // Check instance cache
        if (isset($this->tables_verified[$table_name])) {
            return $this->tables_verified[$table_name];
        }
        
        try {
            // Use esc_like for safety
            $like = $this->wpdb->esc_like($table_name);
            $result = $this->wpdb->get_var(
                $this->wpdb->prepare("SHOW TABLES LIKE %s", $like)
            );
            $exists = ($result === $table_name);
            
            // Cache in both levels
            $this->tables_verified[$table_name] = $exists;
            self::$global_table_cache[$table_name] = $exists;
            
            return $exists;
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: Error checking table existence - " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get safe data directory path using WordPress uploads directory
     * FIXED: No longer uses WP_CONTENT_DIR directly
     *
     * @return string
     */
    private function get_data_dir(): string {
        $upload_dir = wp_upload_dir();
        $plugin_dir = $upload_dir['basedir'] . '/botfend-anti-bot-firewall/';
        
        if (!file_exists($plugin_dir)) {
            wp_mkdir_p($plugin_dir);
            
            // Add index.php for security
            if (!file_exists($plugin_dir . 'index.php')) {
                $index_content = "<?php\n// Silence is golden.\n";
                file_put_contents($plugin_dir . 'index.php', $index_content);
            }
            
            // Add .htaccess to prevent direct access
            if (!file_exists($plugin_dir . '.htaccess')) {
                $htaccess_content = "Deny from all\n";
                file_put_contents($plugin_dir . '.htaccess', $htaccess_content);
            }
        }
        
        return $plugin_dir;
    }
    
    /**
     * Get safe server value with validation
     */
    private function get_server_value($key, $default = '') {
        if (!isset($_SERVER[$key])) {
            return $default;
        }
        return sanitize_text_field(wp_unslash($_SERVER[$key]));
    }
    
    private function calculate_enhanced_attack_level() {
        // Prevent infinite loops with timeout
        if ($this->calculating) {
            // Check if stuck - force release after timeout
            if ($this->calculation_start_time > 0 && (time() - $this->calculation_start_time) > $this->calculation_timeout) {
                $this->calculating = false;
                error_log("BotFend Adaptive: Force released stuck calculation lock");
            } else {
                return;
            }
        }
        
        $this->calculating = true;
        $this->calculation_start_time = time();
        
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            $this->attack_level = 0;
            $this->predictive_risk = 0;
            $this->calculating = false;
            $this->calculation_start_time = 0;
            return;
        }
        
        $cache_key = 'botfend_enhanced_calc';
        $cached_data = get_transient($cache_key);
        
        if ($cached_data !== false && is_array($cached_data) && 
            isset($cached_data['attack_level']) && isset($cached_data['predictive_risk'])) {
            $this->attack_level = $cached_data['attack_level'];
            $this->predictive_risk = $cached_data['predictive_risk'];
            $this->calculating = false;
            $this->calculation_start_time = 0;
            return;
        }
        
        $stats = null;
        $current_level = 0;
        $error_occurred = false;
        
        try {
            $stats = $this->wpdb->get_row("
                SELECT
                    COUNT(*) as total_requests,
                    SUM(CASE WHEN score >= 8 THEN 1 ELSE 0 END) as high_score,
                    SUM(CASE WHEN action = 'blocked' THEN 1 ELSE 0 END) as blocked,
                    SUM(CASE WHEN action = 'challenged' THEN 1 ELSE 0 END) as challenged,
                    COUNT(DISTINCT ip) as unique_ips
                FROM `{$logs_table}`
                WHERE created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 5 MINUTE)
            ");
            
            if (!$stats || 0 === (int) $stats->total_requests) {
                $current_level = 0;
            } else {
                $request_rate = (int) $stats->total_requests / 300;
                $block_rate = (int) $stats->blocked / max(1, (int) $stats->total_requests);
                $challenge_rate = (int) $stats->challenged / max(1, (int) $stats->total_requests);
                $high_score_rate = (int) $stats->high_score / max(1, (int) $stats->total_requests);
                
                $current_level = min(100, max(0,
                    ($request_rate * 0.3) +
                    ($block_rate * 100 * 0.25) +
                    ($challenge_rate * 100 * 0.25) +
                    ($high_score_rate * 100 * 0.2)
                ));
            }
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error calculating current attack level - " . $e->getMessage());
            $error_occurred = true;
        }
        
        $this->predictive_risk = $error_occurred ? 0 : $this->calculate_predictive_risk();
        
        if (!$error_occurred) {
            $this->attack_level = $this->exponential_smoothing(
                $this->attack_level,
                ($current_level * 0.7) + ($this->predictive_risk * 0.3),
                0.3
            );
        } else {
            $this->attack_level = $this->exponential_smoothing($this->attack_level, 0, 0.1);
        }
        
        if (!$error_occurred) {
            set_transient($cache_key, [
                'attack_level' => $this->attack_level,
                'predictive_risk' => $this->predictive_risk
            ], 4 * MINUTE_IN_SECONDS);
        }
        
        $this->auto_adjust_mode_enhanced();
        
        $this->calculating = false;
        $this->calculation_start_time = 0;
    }
    
    private function calculate_predictive_risk() {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            return 0;
        }
        
        $current_hour = (int) current_time('H');
        $current_day = (int) current_time('w');
        
        $hourly_risk = 0;
        $daily_risk = 0;
        $trend_risk = 0;
        
        try {
            $hourly_pattern = $this->wpdb->get_row($this->wpdb->prepare(
                "SELECT
                    COUNT(*) as attack_count,
                    AVG(score) as avg_score
                 FROM `{$logs_table}`
                 WHERE score >= 7
                   AND HOUR(created_at) = %d
                   AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 30 DAY)",
                $current_hour
            ));
            
            $daily_pattern = $this->wpdb->get_row($this->wpdb->prepare(
                "SELECT
                    COUNT(*) as attack_count,
                    AVG(score) as avg_score
                 FROM `{$logs_table}`
                 WHERE score >= 7
                   AND DAYOFWEEK(created_at) = %d
                   AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 90 DAY)",
                $current_day
            ));
            
            $trend = $this->wpdb->get_row("
                SELECT
                    SUM(CASE WHEN created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 3 HOUR) THEN 1 ELSE 0 END) as recent_attacks,
                    SUM(CASE WHEN created_at BETWEEN DATE_SUB(UTC_TIMESTAMP(), INTERVAL 6 HOUR) AND DATE_SUB(UTC_TIMESTAMP(), INTERVAL 3 HOUR) THEN 1 ELSE 0 END) as previous_attacks
                FROM `{$logs_table}`
                WHERE score >= 7
                  AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 6 HOUR)
            ");
            
            $hourly_risk = $hourly_pattern ? min(100, max(0, ($hourly_pattern->attack_count / 50) * 100)) : 0;
            $daily_risk = $daily_pattern ? min(100, max(0, ($daily_pattern->attack_count / 200) * 100)) : 0;
            
            if ($trend && isset($trend->previous_attacks) && $trend->previous_attacks > 0) {
                $growth_rate = ($trend->recent_attacks - $trend->previous_attacks) / $trend->previous_attacks;
                $trend_risk = min(100, max(0, 50 + ($growth_rate * 50)));
            } elseif ($trend && isset($trend->recent_attacks) && $trend->recent_attacks > 0) {
                $trend_risk = 75;
            }
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error calculating predictive risk - " . $e->getMessage());
            return 0;
        }
        
        $predictive_risk = min(100, max(0,
            ($hourly_risk * 0.4) +
            ($daily_risk * 0.3) +
            ($trend_risk * 0.3)
        ));
        
        return $predictive_risk;
    }
    
    private function exponential_smoothing($old_value, $new_value, $alpha) {
        return ($alpha * $new_value) + ((1 - $alpha) * $old_value);
    }
    
    private function auto_adjust_mode_enhanced() {
        if (!$this->config->get_bool('enable_adaptive', true)) {
            return;
        }
        if ($this->config->get_bool('adaptive_mode_manual', false)) {
            return;
        }
        
        $old_mode = $this->current_mode;
        
        $rule_based_mode = $this->get_rule_based_mode();
        $pattern_based_mode = $this->get_pattern_based_mode();
        $predictive_mode = $this->get_predictive_mode();
        
        $mode_scores = [];
        $modes = array_keys($this->modes);
        
        foreach ($modes as $mode) {
            $score = 0;
            if ($mode === $rule_based_mode) $score += 0.4;
            if ($mode === $pattern_based_mode) $score += 0.3;
            if ($mode === $predictive_mode) $score += 0.3;
            $mode_scores[$mode] = $score;
        }
        
        arsort($mode_scores);
        $new_mode = key($mode_scores);
        
        $params = get_option('botfend_algorithm_params', [
            'mode_change_threshold' => 0.2,
            'smoothing_factor' => 0.3,
            'predictive_weight' => 0.3,
            'pattern_weight' => 0.3
        ]);
        
        $current_score = $mode_scores[$old_mode] ?? 0;
        $new_score = $mode_scores[$new_mode] ?? 0;
        
        $threshold = isset($params['mode_change_threshold']) ? (float) $params['mode_change_threshold'] : 0.2;
        $significant_change = ($new_mode !== $old_mode) && (($new_score - $current_score) >= $threshold);
        
        if ($this->is_more_aggressive_than($new_mode, $old_mode)) {
            $hysteresis_up = 0.05;
            $significant_change = $significant_change && (($new_score - $current_score) >= ($threshold + $hysteresis_up));
        }
        
        if ($significant_change) {
            $this->set_protection_mode($new_mode, 'auto_adjust_enhanced');
            $this->log_effectiveness($old_mode, $new_mode);
        }
    }
    
    private function is_more_aggressive_than($mode_a, $mode_b) {
        $order = ['learning', 'balanced', 'aggressive', 'emergency'];
        $index_a = array_search($mode_a, $order);
        $index_b = array_search($mode_b, $order);
        return $index_a !== false && $index_b !== false && $index_a > $index_b;
    }
    
    private function get_rule_based_mode() {
        if ($this->attack_level >= 80) return 'emergency';
        if ($this->attack_level >= 60) return 'aggressive';
        if ($this->attack_level >= 30) return 'balanced';
        return 'learning';
    }
    
    private function get_pattern_based_mode() {
        if (empty($this->mode_effectiveness)) {
            return $this->get_rule_based_mode();
        }
        
        $attack_range = floor($this->attack_level / 20) * 20;
        $attack_range = max(0, min(100, $attack_range));
        
        $best_mode = 'balanced';
        $best_score = 0;
        
        foreach ($this->mode_effectiveness as $record) {
            if (isset($record['attack_range']) && $record['attack_range'] == $attack_range) {
                $effectiveness = isset($record['effectiveness']) ? (float) $record['effectiveness'] : 0;
                if ($effectiveness > $best_score) {
                    $best_score = $effectiveness;
                    $best_mode = isset($record['mode']) ? $record['mode'] : 'balanced';
                }
            }
        }
        return $best_mode;
    }
    
    private function get_predictive_mode() {
        $combined_risk = ($this->predictive_risk + $this->attack_level) / 2;
        if ($combined_risk >= 70) return 'aggressive';
        if ($combined_risk >= 50) return 'balanced';
        return 'learning';
    }
    
    private function analyze_mode_patterns() {
        if (empty($this->mode_history) || count($this->mode_history) < 10) {
            return;
        }
        
        $effectiveness_data = [];
        
        foreach ($this->mode_history as $change) {
            if (!is_array($change)) {
                continue;
            }
            
            $reason = isset($change['reason']) ? $change['reason'] : '';
            if ($reason === 'auto_adjust' || $reason === 'auto_adjust_enhanced') {
                $attack_level = isset($change['attack_level']) ? (float) $change['attack_level'] : 0;
                $attack_range = floor($attack_level / 20) * 20;
                $new_mode = isset($change['new_mode']) ? $change['new_mode'] : 'balanced';
                
                $key = $attack_range . '_' . $new_mode;
                
                if (!isset($effectiveness_data[$key])) {
                    $effectiveness_data[$key] = [
                        'attack_range' => $attack_range,
                        'mode' => $new_mode,
                        'successes' => 0,
                        'attempts' => 0
                    ];
                }
                $effectiveness_data[$key]['attempts']++;
                
                if ($this->was_mode_change_successful($change)) {
                    $effectiveness_data[$key]['successes']++;
                }
            }
        }
        
        $this->mode_effectiveness = [];
        foreach ($effectiveness_data as $data) {
            if ($data['attempts'] >= 3) {
                $effectiveness = $data['successes'] / $data['attempts'];
                $this->mode_effectiveness[] = [
                    'attack_range' => $data['attack_range'],
                    'mode' => $data['mode'],
                    'effectiveness' => $effectiveness,
                    'samples' => $data['attempts']
                ];
            }
        }
        update_option('botfend_mode_effectiveness', $this->mode_effectiveness);
    }
    
    private function was_mode_change_successful($mode_change) {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!isset($mode_change['timestamp'])) {
            return false;
        }
        
        $change_time = strtotime($mode_change['timestamp']);
        
        if ($change_time === false || $change_time <= 0) {
            return false;
        }
        
        $before_start = gmdate('Y-m-d H:i:s', $change_time - 1800);
        $before_end = gmdate('Y-m-d H:i:s', $change_time);
        $after_start = gmdate('Y-m-d H:i:s', $change_time);
        $after_end = gmdate('Y-m-d H:i:s', $change_time + 1800);
        
        $before_attacks = 0;
        $after_attacks = 0;
        
        try {
            $before_attacks = (int) $this->wpdb->get_var($this->wpdb->prepare(
                "SELECT COUNT(*) FROM `{$logs_table}`
                 WHERE created_at BETWEEN %s AND %s
                   AND score >= 7",
                $before_start,
                $before_end
            ));
            
            $after_attacks = (int) $this->wpdb->get_var($this->wpdb->prepare(
                "SELECT COUNT(*) FROM `{$logs_table}`
                 WHERE created_at BETWEEN %s AND %s
                   AND score >= 7",
                $after_start,
                $after_end
            ));
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error checking mode effectiveness - " . $e->getMessage());
            return false;
        }
        
        if ($before_attacks > 0) {
            $reduction = ($before_attacks - $after_attacks) / $before_attacks;
            return $reduction >= 0.2;
        }
        return $after_attacks === 0;
    }
    
    private function log_effectiveness($old_mode, $new_mode) {
        $effectiveness_entry = [
            'timestamp' => current_time('mysql', true),
            'old_mode' => $old_mode,
            'new_mode' => $new_mode,
            'attack_level' => $this->attack_level,
            'predictive_risk' => $this->predictive_risk
        ];
        
        $effectiveness_log = get_option('botfend_effectiveness_log', []);
        if (!is_array($effectiveness_log)) {
            $effectiveness_log = [];
        }
        $effectiveness_log[] = $effectiveness_entry;
        
        if (count($effectiveness_log) > 1000) {
            $effectiveness_log = array_slice($effectiveness_log, -1000);
        }
        update_option('botfend_effectiveness_log', $effectiveness_log);
    }
    
    private function optimize_mode_selection() {
        $last_optimization = get_option('botfend_last_optimization', 0);
        $current_time = time();
        
        if ($current_time - $last_optimization > 86400) {
            $this->run_optimization_cycle();
            update_option('botfend_last_optimization', $current_time);
        }
    }
    
    private function run_optimization_cycle() {
        $performance_data = $this->analyze_performance_data();
        $this->adjust_algorithm_parameters($performance_data);
        $this->cleanup_old_data();
    }
    
    private function analyze_performance_data() {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        $data = [
            'total_requests' => 0,
            'blocked_requests' => 0,
            'challenged_requests' => 0,
            'false_positives' => 0,
            'mode_changes' => is_array($this->mode_history) ? count($this->mode_history) : 0
        ];
        
        if ($this->table_exists($logs_table)) {
            try {
                $stats = $this->wpdb->get_row("
                    SELECT
                        COUNT(*) as total_requests,
                        SUM(CASE WHEN action = 'blocked' THEN 1 ELSE 0 END) as blocked,
                        SUM(CASE WHEN action = 'challenged' THEN 1 ELSE 0 END) as challenged
                    FROM `{$logs_table}`
                    WHERE created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR)
                ");
                
                if ($stats) {
                    $data['total_requests'] = (int) $stats->total_requests;
                    $data['blocked_requests'] = (int) $stats->blocked;
                    $data['challenged_requests'] = (int) $stats->challenged;
                    
                    $passed_challenges = $this->wpdb->get_var("
                        SELECT COUNT(DISTINCT ip) FROM `{$logs_table}`
                         WHERE action = 'challenged'
                           AND ip NOT IN (
                             SELECT DISTINCT ip FROM `{$logs_table}`
                             WHERE action = 'blocked'
                               AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 1 HOUR)
                           )
                           AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR)
                    ");
                    $data['false_positives'] = (int) $passed_challenges;
                }
            } catch (\Exception $e) {
                error_log("BotFend Adaptive: DB Error analyzing performance - " . $e->getMessage());
            }
        }
        return $data;
    }
    
    private function adjust_algorithm_parameters($performance_data) {
        $current_params = get_option('botfend_algorithm_params', [
            'mode_change_threshold' => 0.2,
            'smoothing_factor' => 0.3,
            'predictive_weight' => 0.3,
            'pattern_weight' => 0.3
        ]);
        
        if (!is_array($current_params)) {
            $current_params = [];
        }
        
        $fp_rate = $performance_data['total_requests'] > 0 ?
            $performance_data['false_positives'] / $performance_data['total_requests'] : 0;
        
        if ($fp_rate > 0.1) {
            $current_params['mode_change_threshold'] = min(0.3, ($current_params['mode_change_threshold'] ?? 0.2) + 0.05);
            $current_params['predictive_weight'] = max(0.2, ($current_params['predictive_weight'] ?? 0.3) - 0.05);
        } elseif ($fp_rate < 0.01) {
            $current_params['mode_change_threshold'] = max(0.1, ($current_params['mode_change_threshold'] ?? 0.2) - 0.05);
            $current_params['predictive_weight'] = min(0.4, ($current_params['predictive_weight'] ?? 0.3) + 0.05);
        }
        
        update_option('botfend_algorithm_params', $current_params);
    }
    
    private function cleanup_old_data() {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if ($this->table_exists($logs_table)) {
            try {
                $this->wpdb->query("
                    DELETE FROM `{$logs_table}`
                    WHERE created_at < DATE_SUB(UTC_TIMESTAMP(), INTERVAL 90 DAY)
                ");
            } catch (\Exception $e) {
                error_log("BotFend Adaptive: DB Error cleaning up logs - " . $e->getMessage());
            }
        }
        
        $effectiveness_log = get_option('botfend_effectiveness_log', []);
        if (is_array($effectiveness_log) && count($effectiveness_log) > 1000) {
            $effectiveness_log = array_slice($effectiveness_log, -1000);
            update_option('botfend_effectiveness_log', $effectiveness_log);
        }
        
        if (is_array($this->mode_history) && count($this->mode_history) > 100) {
            $this->mode_history = array_slice($this->mode_history, -100);
            update_option('botfend_mode_history', $this->mode_history);
        }
        
        if (is_array($this->attack_log) && count($this->attack_log) > 1000) {
            $this->attack_log = array_slice($this->attack_log, -1000);
            update_option('botfend_attack_log', $this->attack_log);
        }
    }
    
    public function get_current_settings_enhanced() {
        $settings = $this->modes[$this->current_mode];
        $settings['mode'] = $this->current_mode;
        $settings['attack_level'] = round($this->attack_level, 1);
        $settings['predictive_risk'] = round($this->predictive_risk, 1);
        $settings['combined_risk'] = round(($this->attack_level + $this->predictive_risk) / 2, 1);
        $settings['enabled'] = $this->config->get_bool('enable_adaptive', true);
        $settings['manual'] = $this->config->get_bool('adaptive_mode_manual', false);
        $settings['algorithm_params'] = get_option('botfend_algorithm_params', []);
        
        return $settings;
    }
    
    public function get_predictive_insights() {
        return [
            'next_high_risk_period' => $this->get_next_high_risk_period(),
            'peak_attack_hours' => $this->get_peak_attack_hours(),
            'common_attack_types' => $this->get_common_attack_types(),
            'attack_trend' => $this->get_attack_trend(),
            'effectiveness_scores' => $this->get_mode_effectiveness_scores()
        ];
    }
    
    private function get_next_high_risk_period() {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            return ['hour' => 'N/A', 'probability' => 0];
        }
        
        try {
            $risky_hours = $this->wpdb->get_results("
                SELECT
                    HOUR(created_at) as hour,
                    COUNT(*) as attack_count,
                    COUNT(*) / (SELECT COUNT(*) FROM `{$logs_table}` WHERE score >= 7 AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 30 DAY)) as probability
                FROM `{$logs_table}`
                WHERE score >= 7
                  AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 30 DAY)
                GROUP BY HOUR(created_at)
                HAVING attack_count > 10
                ORDER BY attack_count DESC
                LIMIT 3
            ");
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error getting next high risk period - " . $e->getMessage());
            return ['hour' => 'N/A', 'probability' => 0];
        }
        
        if (empty($risky_hours) || !is_array($risky_hours)) {
            return ['hour' => 'N/A', 'probability' => 0];
        }
        
        $current_hour = (int) current_time('H');
        foreach ($risky_hours as $hour_data) {
            if (isset($hour_data->hour) && (int)$hour_data->hour > $current_hour) {
                $probability = isset($hour_data->probability) ? (float) $hour_data->probability : 0;
                return [
                    'hour' => $hour_data->hour . ':00',
                    'probability' => round($probability * 100, 1)
                ];
            }
        }
        
        $first_hour = isset($risky_hours[0]->hour) ? $risky_hours[0]->hour : 'N/A';
        $first_probability = isset($risky_hours[0]->probability) ? (float) $risky_hours[0]->probability : 0;
        
        return [
            'hour' => $first_hour . ':00',
            'probability' => round($first_probability * 100, 1)
        ];
    }
    
    private function get_peak_attack_hours() {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            return 'N/A';
        }
        
        try {
            $peak_hours = $this->wpdb->get_results("
                SELECT
                    HOUR(created_at) as hour,
                    COUNT(*) as attack_count
                FROM `{$logs_table}`
                WHERE score >= 7
                  AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 7 DAY)
                GROUP BY HOUR(created_at)
                ORDER BY attack_count DESC
                LIMIT 3
            ");
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error getting peak attack hours - " . $e->getMessage());
            return 'N/A';
        }
        
        if (empty($peak_hours) || !is_array($peak_hours)) {
            return 'N/A';
        }
        
        $hours = [];
        foreach ($peak_hours as $hour) {
            if (isset($hour->hour) && isset($hour->attack_count)) {
                $hours[] = $hour->hour . ':00 (' . $hour->attack_count . ' attacks)';
            }
        }
        return !empty($hours) ? implode(', ', $hours) : 'N/A';
    }
    
    private function get_common_attack_types() {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            return 'N/A';
        }
        
        try {
            $attack_types = $this->wpdb->get_results("
                SELECT
                    SUBSTRING_INDEX(SUBSTRING_INDEX(reason, ':', 1), '(', 1) as type,
                    COUNT(*) as count
                FROM `{$logs_table}`
                WHERE action = 'blocked'
                  AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 7 DAY)
                GROUP BY SUBSTRING_INDEX(SUBSTRING_INDEX(reason, ':', 1), '(', 1)
                ORDER BY count DESC
                LIMIT 5
            ");
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error getting common attack types - " . $e->getMessage());
            return 'N/A';
        }
        
        if (empty($attack_types) || !is_array($attack_types)) {
            return 'N/A';
        }
        
        $types = [];
        foreach ($attack_types as $type) {
            if (isset($type->type) && isset($type->count)) {
                $types[] = $type->type . ' (' . $type->count . ')';
            }
        }
        return !empty($types) ? implode(', ', $types) : 'N/A';
    }
    
    private function get_attack_trend() {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            return 'stable';
        }
        
        try {
            $trend_data = $this->wpdb->get_row("
                SELECT
                    SUM(CASE WHEN created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR) THEN 1 ELSE 0 END) as last_24h,
                    SUM(CASE WHEN created_at BETWEEN DATE_SUB(UTC_TIMESTAMP(), INTERVAL 48 HOUR) AND DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR) THEN 1 ELSE 0 END) as previous_24h
                FROM `{$logs_table}`
                WHERE score >= 7
                  AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 48 HOUR)
            ");
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error getting attack trend - " . $e->getMessage());
            return 'stable';
        }
        
        if (!$trend_data || !isset($trend_data->previous_24h) || 0 === (int) $trend_data->previous_24h) {
            return 'stable';
        }
        
        $last_24h = isset($trend_data->last_24h) ? (int) $trend_data->last_24h : 0;
        $previous_24h = (int) $trend_data->previous_24h;
        
        $change = (($last_24h - $previous_24h) / $previous_24h) * 100;
        if ($change > 20) return 'increasing';
        if ($change < -20) return 'decreasing';
        return 'stable';
    }
    
    public function get_attack_timeline($period = '24 hours') {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            return [];
        }
        
        $interval = 'HOUR';
        $format = '%H:00';
        $points = 24;
        
        switch ($period) {
            case '24 hours':
                $interval = 'HOUR';
                $format = '%H:00';
                $points = 24;
                break;
            case '7 days':
                $interval = 'DAY';
                $format = '%Y-%m-%d';
                $points = 7;
                break;
            case '30 days':
                $interval = 'DAY';
                $format = '%Y-%m-%d';
                $points = 30;
                break;
            default:
                $interval = 'HOUR';
                $format = '%H:00';
                $points = 24;
                break;
        }
        
        // Validate interval to prevent SQL injection
        $allowed_intervals = ['HOUR', 'DAY'];
        if (!in_array($interval, $allowed_intervals)) {
            $interval = 'HOUR';
        }
        
        try {
            // FIXED: Use proper prepared statement with validated interval
            $sql = $this->wpdb->prepare(
                "SELECT
                    DATE_FORMAT(created_at, %s) as time_period,
                    COUNT(*) as total_requests,
                    SUM(CASE WHEN score >= 7 THEN 1 ELSE 0 END) as attacks,
                    SUM(CASE WHEN action = 'blocked' THEN 1 ELSE 0 END) as blocked,
                    AVG(score) as avg_score
                FROM `{$logs_table}`
                WHERE created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d {$interval})
                GROUP BY DATE_FORMAT(created_at, %s)
                ORDER BY time_period",
                $format, $points, $format
            );
            
            $timeline_data = $this->wpdb->get_results($sql);
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error getting attack timeline - " . $e->getMessage());
            return [];
        }
        
        $formatted_data = [];
        if (is_array($timeline_data)) {
            foreach ($timeline_data as $data) {
                if (isset($data->time_period)) {
                    $formatted_data[$data->time_period] = [
                        'requests' => isset($data->total_requests) ? (int) $data->total_requests : 0,
                        'attacks' => isset($data->attacks) ? (int) $data->attacks : 0,
                        'blocked' => isset($data->blocked) ? (int) $data->blocked : 0,
                        'avg_score' => isset($data->avg_score) ? round((float) $data->avg_score, 2) : 0
                    ];
                }
            }
        }
        return $formatted_data;
    }
    
    public function get_mode_effectiveness_scores() {
        $scores = [];
        $modes = array_keys($this->modes);
        
        foreach ($modes as $mode) {
            $scores[$mode] = 0;
            if (!is_array($this->mode_effectiveness)) {
                continue;
            }
            
            $mode_effectiveness = array_filter($this->mode_effectiveness, function($record) use ($mode) {
                return isset($record['mode']) && $record['mode'] === $mode;
            });
            
            if (!empty($mode_effectiveness)) {
                $total_effectiveness = 0;
                $total_samples = 0;
                foreach ($mode_effectiveness as $record) {
                    $effectiveness = isset($record['effectiveness']) ? (float) $record['effectiveness'] : 0;
                    $samples = isset($record['samples']) ? (int) $record['samples'] : 0;
                    $total_effectiveness += $effectiveness * $samples;
                    $total_samples += $samples;
                }
                $scores[$mode] = $total_samples > 0 ? $total_effectiveness / $total_samples : 0;
            }
        }
        return $scores;
    }
    
    public function set_protection_mode($mode, $reason = 'manual') {
        if (!isset($this->modes[$mode])) {
            return false;
        }
        
        // Add nonce verification for manual mode changes
        if ($reason === 'manual' && defined('DOING_AJAX') && DOING_AJAX) {
            if (!check_ajax_referer('botfend_adaptive_mode', 'nonce', false)) {
                return false;
            }
        }
        
        $old_mode = $this->current_mode;
        $this->current_mode = $mode;
        $this->config->set('adaptive_mode', $mode);
        
        if ($reason === 'manual') {
            $this->config->set('adaptive_mode_manual', true);
        } else {
            $this->config->set('adaptive_mode_manual', false);
        }
        
        $this->log_mode_change($old_mode, $mode, $reason);
        return true;
    }
    
    public function log_mode_change($old_mode, $new_mode, $reason = 'manual') {
        // Anonymize IP for privacy
        $ip = $this->get_client_ip();
        $anonymized_ip = !empty($ip) ? substr($ip, 0, strrpos($ip, '.')) . '.xxx' : '0.0.0.0';
        
        $log_entry = [
            'timestamp' => current_time('mysql', true),
            'old_mode' => $old_mode,
            'new_mode' => $new_mode,
            'reason' => $reason,
            'attack_level' => $this->get_attack_level(),
            'predictive_risk' => $this->predictive_risk,
            'ip_address' => $anonymized_ip,
            'user_agent' => $this->get_server_value('HTTP_USER_AGENT', '')
        ];
        
        $sanitized_entry = $this->sanitize_log_entry($log_entry);
        
        if (!is_array($this->mode_history)) {
            $this->mode_history = [];
        }
        $this->mode_history[] = $sanitized_entry;
        
        if (count($this->mode_history) > 100) {
            $this->mode_history = array_slice($this->mode_history, -100);
        }
        
        update_option('botfend_mode_history', $this->mode_history);
        $this->log_to_file($sanitized_entry);
        
        if ($this->config->get_bool('botfend_notify_admin', false)) {
            $this->send_mode_change_notification($old_mode, $new_mode, $reason);
        }
    }
    
    private function send_mode_change_notification($old_mode, $new_mode, $reason) {
        $admin_email = get_option('admin_email');
        if (!$admin_email) {
            return;
        }
        
        $subject = sprintf(
            '[BotFend] Protection mode changed: %s → %s',
            ucfirst($old_mode),
            ucfirst($new_mode)
        );
        
        $message = "BotFend Anti-Bot Firewall has changed protection mode:\n";
        $message .= sprintf("Old Mode: %s\n", ucfirst($old_mode));
        $message .= sprintf("New Mode: %s\n", ucfirst($new_mode));
        $message .= sprintf("Attack Level: %.1f%%\n", $this->get_attack_level());
        $message .= sprintf("Predictive Risk: %.1f%%\n", $this->predictive_risk);
        $message .= sprintf("Reason: %s\n", ucfirst(str_replace('_', ' ', $reason)));
        $message .= sprintf("Time: %s\n", current_time('mysql'));
        
        $new_settings = isset($this->modes[$new_mode]) ? $this->modes[$new_mode] : [];
        $message .= "New Settings:\n";
        $message .= sprintf("- Block Score: %d/10\n", isset($new_settings['block_score']) ? $new_settings['block_score'] : 8);
        $message .= sprintf("- Challenge Score: %d/10\n", isset($new_settings['challenge_score']) ? $new_settings['challenge_score'] : 6);
        $message .= sprintf("- Rate Limit: %d requests/min\n", isset($new_settings['rate_limit']) ? $new_settings['rate_limit'] : 100);
        $message .= "\nPredictive Insights:\n";
        
        $insights = $this->get_predictive_insights();
        if (isset($insights['next_high_risk_period']['probability']) && $insights['next_high_risk_period']['probability'] > 30) {
            $message .= sprintf("- Next high-risk period: %s (%s%% probability)\n",
                $insights['next_high_risk_period']['hour'],
                $insights['next_high_risk_period']['probability']);
        }
        $message .= sprintf("- Attack trend: %s\n", ucfirst($insights['attack_trend']));
        $message .= "\nYou can review this in your BotFend Anti-Bot Firewall settings.\n";
        
        wp_mail($admin_email, $subject, $message);
    }
    
    private function sanitize_log_entry($entry) {
        return [
            'timestamp' => sanitize_text_field($entry['timestamp']),
            'old_mode' => sanitize_text_field($entry['old_mode']),
            'new_mode' => sanitize_text_field($entry['new_mode']),
            'reason' => sanitize_text_field($entry['reason']),
            'attack_level' => floatval($entry['attack_level']),
            'predictive_risk' => floatval($entry['predictive_risk']),
            'ip_address' => sanitize_text_field($entry['ip_address']),
            'user_agent' => $this->sanitize_user_agent($entry['user_agent'])
        ];
    }
    
    private function sanitize_user_agent($user_agent) {
        if (empty($user_agent)) {
            return '';
        }
        $clean_agent = wp_strip_all_tags($user_agent);
        return substr($clean_agent, 0, 255);
    }
    
    /**
     * Log to file using WordPress uploads directory (not plugin folder)
     * FIXED: No longer writes to WP_CONTENT_DIR directly
     */
    private function log_to_file($entry) {
        $log_dir = $this->get_data_dir() . 'logs/';
        
        if (!file_exists($log_dir)) {
            wp_mkdir_p($log_dir);
            
            // Add protection to prevent public access
            if (!file_exists($log_dir . '.htaccess')) {
                $htaccess_content = "Deny from all\n";
                file_put_contents($log_dir . '.htaccess', $htaccess_content);
            }
            if (!file_exists($log_dir . 'index.php')) {
                $index_content = "<?php\n// Silence is golden.\n";
                file_put_contents($log_dir . 'index.php', $index_content);
            }
        }
        
        $log_file = $log_dir . 'mode-changes.log';
        
        // Rotate log if too large (10MB)
        if (file_exists($log_file) && filesize($log_file) > 10 * 1024 * 1024) {
            $backup = $log_file . '.1';
            if (file_exists($backup)) {
                unlink($backup);
            }
            rename($log_file, $backup);
        }
        
        $log_line = sprintf(
            "[%s] Mode changed: %s -> %s (Reason: %s, Attack Level: %.1f%%, Predictive: %.1f%%, IP: %s)\n",
            $entry['timestamp'],
            $entry['old_mode'],
            $entry['new_mode'],
            $entry['reason'],
            $entry['attack_level'],
            $entry['predictive_risk'],
            $entry['ip_address']
        );
        
        @file_put_contents($log_file, $log_line, FILE_APPEND | LOCK_EX);
    }
    
    private function get_client_ip() {
        $ip = '';
        
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = sanitize_text_field(wp_unslash($_SERVER['HTTP_CLIENT_IP']));
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip_list = explode(',', sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR'])));
            $ip = trim($ip_list[0]);
        } else {
            $ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
        }
        
        return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '0.0.0.0';
    }
    
    public function log_attack($type, $score, $details = []) {
        $attack_entry = [
            'timestamp' => time(),
            'type' => $type,
            'score' => min(10, max(0, $score)),
            'ip' => $this->get_client_ip(),
            'details' => $details
        ];
        
        if (!is_array($this->attack_log)) {
            $this->attack_log = [];
        }
        $this->attack_log[] = $attack_entry;
        
        if (count($this->attack_log) > 1000) {
            $this->attack_log = array_slice($this->attack_log, -1000);
        }
        
        update_option('botfend_attack_log', $this->attack_log);
        $this->calculate_enhanced_attack_level();
    }
    
    public function get_mode_history($limit = 10) {
        $history = is_array($this->mode_history) ? array_reverse($this->mode_history) : [];
        return array_slice($history, 0, $limit);
    }
    
    public function get_mode_statistics() {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            return [
                'total_requests' => 0,
                'blocked_requests' => 0,
                'challenged_requests' => 0,
                'average_score' => 0
            ];
        }
        
        try {
            $stats = [
                'total_requests' => (int) $this->wpdb->get_var("
                    SELECT COUNT(*) FROM `{$logs_table}`
                    WHERE created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR)
                "),
                'blocked_requests' => (int) $this->wpdb->get_var("
                    SELECT COUNT(*) FROM `{$logs_table}`
                    WHERE action = 'blocked'
                      AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR)
                "),
                'challenged_requests' => (int) $this->wpdb->get_var("
                    SELECT COUNT(*) FROM `{$logs_table}`
                    WHERE action = 'challenged'
                      AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR)
                "),
                'average_score' => round((float) $this->wpdb->get_var("
                    SELECT AVG(score) FROM `{$logs_table}`
                    WHERE created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 24 HOUR)
                "), 2)
            ];
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error getting mode stats - " . $e->getMessage());
            return [
                'total_requests' => 0,
                'blocked_requests' => 0,
                'challenged_requests' => 0,
                'average_score' => 0
            ];
        }
        
        return $stats;
    }
    
    public function evaluate_request($request_data) {
        $score = 0;
        $score += $this->check_threat_intel($request_data);
        $score += $this->check_signatures($request_data);
        $score += $this->check_rate_limit($request_data);
        $score += $this->check_behavior($request_data);
        return min(10, max(0, $score));
    }
    
    private function check_threat_intel($request_data) {
        $score = 0;
        // Threat intel is disabled by default (opt-in required)
        $threat_intel_enabled = $this->config->get_bool('enable_threat_intel', false);
        
        if ($threat_intel_enabled) {
            $known_threats = get_option('botfend_known_threats', []);
            if (!is_array($known_threats)) {
                $known_threats = [];
            }
            $ip = $this->get_client_ip();
            if (in_array($ip, $known_threats)) {
                $score += 4;
            }
        }
        return $score;
    }
    
    private function check_signatures($request_data) {
        $score = 0;
        $signatures_enabled = $this->config->get_bool('enable_signatures', true);
        
        if (!$signatures_enabled) {
            return $score;
        }
        
        $signatures = [
            ['pattern' => '<script>', 'score' => 2],
            ['pattern' => 'union select', 'score' => 3],
            ['pattern' => '../etc/passwd', 'score' => 3],
            ['pattern' => 'eval(', 'score' => 2],
            ['pattern' => 'base64_decode', 'score' => 1],
        ];
        
        if (!is_array($request_data)) {
            return $score;
        }
        
        foreach ($signatures as $signature) {
            foreach ($request_data as $key => $value) {
                if (is_string($value) && stripos($value, $signature['pattern']) !== false) {
                    $score += $signature['score'];
                    break;
                }
            }
        }
        
        return min(4, $score);
    }
    
    private function check_rate_limit($request_data) {
        $ip = $this->get_client_ip();
        $current_time = time();
        
        $rate_data = get_transient("botfend_rate_$ip");
        if (!is_array($rate_data)) {
            $rate_data = [
                'count' => 0,
                'timestamp' => $current_time
            ];
        }
        
        if ($current_time - $rate_data['timestamp'] > 60) {
            $rate_data = [
                'count' => 0,
                'timestamp' => $current_time
            ];
        }
        
        $rate_data['count']++;
        set_transient("botfend_rate_$ip", $rate_data, 60);
        
        $current_settings = $this->get_current_settings_enhanced();
        $rate_limit = isset($current_settings['rate_limit']) ? $current_settings['rate_limit'] : 100;
        
        if ($rate_data['count'] > $rate_limit) {
            return 3;
        }
        return 0;
    }
    
    private function check_behavior($request_data) {
        $score = 0;
        
        $user_agent = $this->get_server_value('HTTP_USER_AGENT', '');
        if (!empty($user_agent) && is_string($user_agent)) {
            $ua = strtolower($user_agent);
            $suspicious_patterns = [
                '/bot/' => 2,
                '/crawler/' => 2,
                '/spider/' => 2,
                '/scraper/' => 2,
                '/headless/' => 3,
                '/phantom/' => 3,
                '/selenium/' => 3,
                '/python-requests/' => 2,
                '/curl/' => 1,
                '/wget/' => 1,
            ];
            
            foreach ($suspicious_patterns as $pattern => $pattern_score) {
                if (preg_match($pattern, $ua)) {
                    $score += $pattern_score;
                    break;
                }
            }
            
            if (empty($user_agent)) {
                $score += 2;
            }
        }
        
        return min(3, $score);
    }
    
    public function should_sample_request() {
        $current_settings = $this->get_current_settings_enhanced();
        $sampling_rate = isset($current_settings['sampling_rate']) ? $current_settings['sampling_rate'] : 0.3;
        return (mt_rand(0, 100) / 100) <= $sampling_rate;
    }
    
    public function get_request_decision($request_score) {
        $current_settings = $this->get_current_settings_enhanced();
        
        $block_score = isset($current_settings['block_score']) ? $current_settings['block_score'] : 8;
        $challenge_score = isset($current_settings['challenge_score']) ? $current_settings['challenge_score'] : 6;
        
        if ($request_score >= $block_score) {
            return 'block';
        } elseif ($request_score >= $challenge_score) {
            return 'challenge';
        } else {
            return 'allow';
        }
    }
    
    public function should_check_request($ip) {
        if (!$this->config->get_bool('enable_adaptive', true)) {
            return true;
        }
        
        $settings = $this->get_current_settings_enhanced();
        
        if ($this->is_high_risk_ip($ip)) {
            return true;
        }
        
        $sampling_rate = isset($settings['sampling_rate']) ? $settings['sampling_rate'] : 0.3;
        $hash = crc32($ip . gmdate('Y-m-d-H'));
        $sample_value = ($hash % 100) / 100;
        return $sample_value <= $sampling_rate;
    }
    
    private function is_high_risk_ip($ip) {
        $logs_table = $this->wpdb->prefix . 'botfend_logs';
        
        if (!$this->table_exists($logs_table)) {
            return false;
        }
        
        try {
            $high_score_count = (int) $this->wpdb->get_var($this->wpdb->prepare(
                "SELECT COUNT(*) FROM `{$logs_table}`
                 WHERE ip = %s AND score >= 7
                   AND created_at > DATE_SUB(UTC_TIMESTAMP(), INTERVAL 1 HOUR)",
                $ip
            ));
            return $high_score_count > 5;
        } catch (\Exception $e) {
            error_log("BotFend Adaptive: DB Error checking high risk IP - " . $e->getMessage());
            return false;
        }
    }
    
    public function get_available_modes() {
        return $this->modes;
    }
    
    public function reset_to_default() {
        $this->set_protection_mode('balanced', 'reset');
        delete_option('botfend_attack_log');
        delete_option('botfend_mode_history');
        delete_option('botfend_mode_effectiveness');
        delete_option('botfend_effectiveness_log');
        delete_option('botfend_algorithm_params');
        delete_option('botfend_last_optimization');
        
        $this->config->set('adaptive_mode_manual', false);
        
        $this->attack_log = [];
        $this->mode_history = [];
        $this->mode_effectiveness = [];
        $this->attack_level = 0;
        $this->predictive_risk = 0;
        
        delete_transient('botfend_enhanced_calc');
    }
    
    public function get_attack_level() {
        return round($this->attack_level, 1);
    }
    
    public function get_protection_mode() {
        return $this->current_mode;
    }
    
    public function get_current_settings() {
        return $this->get_current_settings_enhanced();
    }
}