<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }

/**
 * Vulnity Anti-Collapse System - Simplified Version
 * Internal system to prevent SIEM saturation during massive attacks
 * No UI, no local storage, just smart aggregation
 */

class Vulnity_Anti_Collapse_System {
    
    private static $instance = null;
    private static $alert_buffer = array();
    private static $dedup_cache = array();
    private static $rate_counter = 0;
    private static $last_reset = 0;
    private static $panic_mode = false;
    private static $panic_activated_at = 0;
    
    private $config = array(
        'enabled' => true,
        'threshold_per_minute' => 50,
        'panic_threshold' => 100,
        'aggregation_window' => 30,
        'dedup_window' => 60
    );
    
    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        add_filter('vulnity_before_send_alert', array($this, 'process_alert'), 10, 1);
        add_action('shutdown', array($this, 'flush_buffer'));
        add_action('vulnity_flush_alert_buffer', array($this, 'flush_buffer'));
        add_filter('cron_schedules', array($this, 'add_cron_interval'));
        
        if (!wp_next_scheduled('vulnity_flush_alert_buffer')) {
            wp_schedule_event(time() + 30, 'vulnity_30seconds', 'vulnity_flush_alert_buffer');
        }

        self::$last_reset = time();
    }
    
    public function add_cron_interval($schedules) {
        $schedules['vulnity_30seconds'] = array(
            'interval' => 30,
            'display' => 'Every 30 seconds'
        );
        return $schedules;
    }
    
    public function process_alert($alert) {
        if (!$this->config['enabled']) {
            return $alert;
        }
        
        $this->update_rate_counter();
        
        $current_rate = $this->get_current_rate();
        
        if ($current_rate >= $this->config['panic_threshold'] && !self::$panic_mode) {
            $this->activate_panic_mode();
        }
        
        if (self::$panic_mode) {
            if (time() - self::$panic_activated_at > 300) {
                $this->deactivate_panic_mode();
            }
        }
        
        if ($alert['severity'] === 'critical') {
            return $alert;
        }
        
        $alert_hash = $this->generate_hash($alert);
        
        if ($this->is_duplicate($alert_hash)) {
            $this->add_to_dedup($alert_hash, $alert);
            return false;
        }
        
        if ($current_rate > $this->config['threshold_per_minute'] || self::$panic_mode) {
            $this->add_to_buffer($alert);
            return false;
        }
        
        $this->mark_as_seen($alert_hash);
        
        return $alert;
    }
    
    private function update_rate_counter() {
        $current_time = time();
        
        if ($current_time - self::$last_reset >= 60) {
            self::$rate_counter = 0;
            self::$last_reset = $current_time;
        }
        
        self::$rate_counter++;
    }
    
    private function get_current_rate() {
        $elapsed = time() - self::$last_reset;

        if ($elapsed < 10) {
            return 0;
        }

        if ($elapsed === 0) {
            $elapsed = 1;
        }

        return (self::$rate_counter / $elapsed) * 60;
    }
    
    private function generate_hash($alert) {
        $key = $alert['type'] . ':';
        
        if (isset($alert['details']['ip'])) {
            $key .= $alert['details']['ip'] . ':';
        }
        if (isset($alert['details']['user_id'])) {
            $key .= $alert['details']['user_id'] . ':';
        }
        if (isset($alert['details']['action'])) {
            $key .= $alert['details']['action'];
        }
        
        return md5($key);
    }
    
    private function is_duplicate($hash) {
        if (!isset(self::$dedup_cache[$hash])) {
            return false;
        }
        
        $entry = self::$dedup_cache[$hash];
        
        if (time() - $entry['first_seen'] > $this->config['dedup_window']) {
            unset(self::$dedup_cache[$hash]);
            return false;
        }
        
        return true;
    }
    
    private function add_to_dedup($hash, $alert) {
        if (!isset(self::$dedup_cache[$hash])) {
            self::$dedup_cache[$hash] = array(
                'count' => 0,
                'first_seen' => time(),
                'last_seen' => time(),
                'sample' => $alert
            );
        }
        
        self::$dedup_cache[$hash]['count']++;
        self::$dedup_cache[$hash]['last_seen'] = time();
        
        if (self::$dedup_cache[$hash]['count'] == 10 || 
            self::$dedup_cache[$hash]['count'] == 50 || 
            self::$dedup_cache[$hash]['count'] == 100) {
            
            $this->send_dedup_summary($hash);
        }
    }
    
    private function mark_as_seen($hash) {
        self::$dedup_cache[$hash] = array(
            'count' => 1,
            'first_seen' => time(),
            'last_seen' => time()
        );
    }
    
    private function add_to_buffer($alert) {
        $type = $alert['type'];
        
        if (!isset(self::$alert_buffer[$type])) {
            self::$alert_buffer[$type] = array(
                'count' => 0,
                'first' => $alert,
                'severities' => array(),
                'ips' => array(),
                'first_time' => time()
            );
        }
        
        self::$alert_buffer[$type]['count']++;
        
        if (isset($alert['severity'])) {
            $severity = $alert['severity'];
            if (!isset(self::$alert_buffer[$type]['severities'][$severity])) {
                self::$alert_buffer[$type]['severities'][$severity] = 0;
            }
            self::$alert_buffer[$type]['severities'][$severity]++;
        }
        
        if (isset($alert['details']['ip'])) {
            self::$alert_buffer[$type]['ips'][$alert['details']['ip']] = true;
        }
    }
    
    public function flush_buffer() {
        if (empty(self::$alert_buffer)) {
            return;
        }
        
        foreach (self::$alert_buffer as $type => $data) {
            if ($data['count'] > 1) {
                $this->send_aggregated_alert($type, $data);
            } else {
                $siem = Vulnity_SIEM_Connector::get_instance();
                $siem->send_alert($data['first']);
            }
        }
        
        self::$alert_buffer = array();
        
        $this->cleanup_dedup_cache();
    }
    
    private function send_aggregated_alert($type, $data) {
        $highest_severity = 'low';
        foreach (array('critical', 'high', 'medium', 'low') as $sev) {
            if (isset($data['severities'][$sev]) && $data['severities'][$sev] > 0) {
                $highest_severity = $sev;
                break;
            }
        }
        
        $aggregated_alert = array(
            'id' => 'agg_' . time() . '_' . wp_generate_password(8, false),
            'type' => $type,
            'severity' => $highest_severity,
            'title' => sprintf('[AGGREGATED] %d %s events detected', $data['count'], $type),
            'message' => sprintf(
                'System aggregated %d %s events from %d unique sources in %d seconds',
                $data['count'],
                str_replace('_', ' ', $type),
                count($data['ips']),
                time() - $data['first_time']
            ),
            'details' => array(
                'aggregated' => true,
                'event_count' => $data['count'],
                'unique_sources' => count($data['ips']),
                'duration' => time() - $data['first_time'],
                'severity_breakdown' => $data['severities'],
                'sample_event' => $data['first']['details']
            ),
            'timestamp' => current_time('mysql'),
            'sent_to_siem' => false
        );
        
        $siem = Vulnity_SIEM_Connector::get_instance();
        $siem->send_alert($aggregated_alert);
    }
    
    private function send_dedup_summary($hash) {
        $data = self::$dedup_cache[$hash];
        
        $summary_alert = array(
            'id' => 'dedup_' . time() . '_' . substr($hash, 0, 8),
            'type' => $data['sample']['type'],
            'severity' => 'low',
            'title' => sprintf('[DEDUPLICATED] %s repeated %d times', $data['sample']['title'], $data['count']),
            'message' => sprintf(
                'Alert "%s" was triggered %d times in %d seconds and was deduplicated',
                $data['sample']['title'],
                $data['count'],
                $data['last_seen'] - $data['first_seen']
            ),
            'details' => array(
                'deduplicated' => true,
                'count' => $data['count'],
                'duration' => $data['last_seen'] - $data['first_seen'],
                'original_details' => $data['sample']['details']
            ),
            'timestamp' => current_time('mysql'),
            'sent_to_siem' => false
        );
        
        $siem = Vulnity_SIEM_Connector::get_instance();
        $siem->send_alert($summary_alert);
    }
    
    private function activate_panic_mode() {
        self::$panic_mode = true;
        self::$panic_activated_at = time();
        
        $panic_alert = array(
            'id' => 'panic_' . time(),
            'type' => 'system_panic',
            'severity' => 'critical',
            'title' => '[ANTI-COLLAPSE] Panic Mode Activated',
            'message' => sprintf(
                'Anti-collapse system activated due to extreme load (%d alerts/min). Aggregation mode enabled for 5 minutes.',
                $this->get_current_rate()
            ),
            'details' => array(
                'system_event' => true,
                'panic_mode' => true,
                'current_rate' => $this->get_current_rate(),
                'threshold' => $this->config['panic_threshold'],
                'activated_at' => current_time('mysql')
            ),
            'timestamp' => current_time('mysql'),
            'sent_to_siem' => false
        );
        
        $siem = Vulnity_SIEM_Connector::get_instance();
        $siem->send_alert($panic_alert);
        
        vulnity_log('[Vulnity Anti-Collapse] PANIC MODE ACTIVATED - Rate: ' . $this->get_current_rate() . ' alerts/min');
    }
    
    private function deactivate_panic_mode() {
        self::$panic_mode = false;
        
        $recovery_alert = array(
            'id' => 'recovery_' . time(),
            'type' => 'system_recovery',
            'severity' => 'info',
            'title' => '[ANTI-COLLAPSE] System Recovered',
            'message' => 'Anti-collapse panic mode deactivated. Normal operation resumed.',
            'details' => array(
                'system_event' => true,
                'panic_mode' => false,
                'current_rate' => $this->get_current_rate(),
                'duration' => time() - self::$panic_activated_at
            ),
            'timestamp' => current_time('mysql'),
            'sent_to_siem' => false
        );
        
        $siem = Vulnity_SIEM_Connector::get_instance();
        $siem->send_alert($recovery_alert);
        
        vulnity_log('[Vulnity Anti-Collapse] System recovered from panic mode');
    }
    
    private function cleanup_dedup_cache() {
        $current_time = time();
        
        foreach (self::$dedup_cache as $hash => $entry) {
            if ($current_time - $entry['last_seen'] > $this->config['dedup_window']) {
                unset(self::$dedup_cache[$hash]);
            }
        }
        
        if (count(self::$dedup_cache) > 1000) {
            self::$dedup_cache = array_slice(self::$dedup_cache, -500, null, true);
        }
    }
    
    public function get_stats() {
        return array(
            'enabled' => $this->config['enabled'],
            'current_rate' => $this->get_current_rate(),
            'panic_mode' => self::$panic_mode,
            'buffer_size' => count(self::$alert_buffer),
            'dedup_cache_size' => count(self::$dedup_cache)
        );
    }
    
    public function cleanup() {
        wp_clear_scheduled_hook('vulnity_flush_alert_buffer');
        self::$alert_buffer = array();
        self::$dedup_cache = array();
    }
}
