<?php
defined('ABSPATH') || exit;

/**
 * WPFort Live Feed Event System
 * 
 * This file contains functions for sending live feed events to the WPFort SAAS platform
 * to provide real-time activity monitoring for WordPress sites.
 */

/**
 * Canonical event names for the live feed system
 */
class WPSEC_Events {
    // WP Core Layer events
    const CORE_REINSTALL_STARTED = 'wpcore_layer.core_reinstall.started';
    const CORE_REINSTALL_COMPLETED = 'wpcore_layer.core_reinstall.completed';
    const CORE_REINSTALL_FAILED = 'wpcore_layer.core_reinstall.failed';
    const CORE_CHECK_STARTED = 'wpcore_layer.core_check.started';
    const CORE_CHECK_COMPLETED = 'wpcore_layer.core_check.completed';

    // Filesystem Layer events
    const FILESYSTEM_SCAN_STARTED = 'filesystem_layer.filesystem_scan.started';
    const FILESYSTEM_SCAN_COMPLETED = 'filesystem_layer.filesystem_scan.completed';
    const FILESYSTEM_SCAN_FAILED = 'filesystem_layer.filesystem_scan.failed';
    const FILE_QUARANTINE_COMPLETED = 'filesystem_layer.file_quarantine.completed';
    const FILE_QUARANTINE_FAILED = 'filesystem_layer.file_quarantine.failed';
    const FILE_WHITELIST_COMPLETED = 'filesystem_layer.file_whitelist.completed';
    const FILE_WHITELIST_FAILED = 'filesystem_layer.file_whitelist.failed';
    const FILE_RESTORE_COMPLETED = 'filesystem_layer.file_restore.completed';
    const FILE_RESTORE_FAILED = 'filesystem_layer.file_restore.failed';
    const FILE_DELETE_COMPLETED = 'filesystem_layer.file_delete.completed';
    const FILE_DELETE_FAILED = 'filesystem_layer.file_delete.failed';

    // Application Layer events
    const PLUGINS_UPDATE_STARTED = 'application_layer.plugins.update.started';
    const PLUGINS_UPDATE_COMPLETED = 'application_layer.plugins.update.completed';
    const PLUGINS_UPDATE_FAILED = 'application_layer.plugins.update.failed';
    const PLUGINS_ACTIVATED = 'application_layer.plugins.activated';
    const PLUGINS_DEACTIVATED = 'application_layer.plugins.deactivated';
    const VULNERABILITIES_SCAN_STARTED = 'application_layer.vulnerabilities_scan.started';
    const VULNERABILITIES_SCAN_COMPLETED = 'application_layer.vulnerabilities_scan.completed';
    const VULNERABILITIES_SCAN_FAILED = 'application_layer.vulnerabilities_scan.failed';

    // Network/Firewall Layer events
    const ATTACKS_BLOCKED = 'network_layer.attacks.blocked';
    const FIREWALL_BLACKLIST_UPDATED = 'network_layer.firewall.blacklist.updated';
    const FIREWALL_WHITELIST_UPDATED = 'network_layer.firewall.whitelist.updated';
    const FIREWALL_TOGGLED_ON = 'network_layer.firewall.toggled.on';
    const FIREWALL_TOGGLED_OFF = 'network_layer.firewall.toggled.off';

    // Backup events
    const BACKUP_STARTED = 'backup.backup.started';
    const BACKUP_COMPLETED = 'backup.backup.completed';
    const BACKUP_FAILED = 'backup.backup.failed';
    const RESTORE_STARTED = 'backup.restore.started';
    const RESTORE_COMPLETED = 'backup.restore.completed';
    const RESTORE_FAILED = 'backup.restore.failed';

    // Operator events
    const ASSESSMENT_STARTED = 'operator.assessment.started';
    const ASSESSMENT_COMPLETED = 'operator.assessment.completed';
    const ASSESSMENT_FAILED = 'operator.assessment.failed';
    const ACTION_STARTED = 'operator.action.started';
    const ACTION_COMPLETED = 'operator.action.completed';
    const ACTION_FAILED = 'operator.action.failed';
}

/**
 * Send an event to the WPFort Live Feed
 * 
 * @param string $event_name The name of the event
 * @param string $vertical The vertical category of the event
 * @param string $status The status of the event (success/failed)
 * @param string $message User-friendly description of the event
 * @param array $metadata Optional metadata for the event
 * @return bool|WP_Error True on success, WP_Error on failure
 */
function wpsec_send_live_feed_event($event_name, $vertical, $status, $message, $metadata = array()) {
    // Get the current site domain
    $site_url = get_site_url();
    $domain = wp_parse_url($site_url, PHP_URL_HOST);
    
    // Prepare the payload
    $payload = array(
        'domain' => $domain,
        'event' => $event_name,
        'data' => array(
            'origin' => 'wpsec',
            'vertical' => $vertical,
            'status' => $status,
            'message' => $message
        )
    );
    
    // Add metadata if provided
    if (!empty($metadata)) {
        $payload['data']['metadata'] = $metadata;
    }
    
    // Log the event payload (for debugging)
    wpsec_debug_log('🔔 WPFort Live Feed: Sending event: ' . $event_name . ' - ' . $message, 'info');
    wpsec_debug_log('📦 WPFort Live Feed: Payload: ' . json_encode($payload), 'info');
    
    // Prepare the request
    $live_feed_url = 'http://62.171.130.143:3000/api/events/create';
    
    $args = [
        'method' => 'POST',
        'timeout' => 30,
        'sslverify' => false,
        'headers' => [
            'Content-Type' => 'application/json',
            'User-Agent' => 'WPFort-Security-Plugin/' . (defined('WPSEC_PLUGIN_VERSION') ? WPSEC_PLUGIN_VERSION : '1.0'),
            'x-wpfort-token' => '123123123' // Authentication token as specified by dev
        ],
        'body' => json_encode($payload)
    ];
    
    // Send the request
    $response = wp_remote_post($live_feed_url, $args);
    
    if (is_wp_error($response)) {
        wpsec_debug_log('❌ WPFort Live Feed: Failed to send event: ' . $response->get_error_message(), 'error');
        return $response;
    }
    
    $status_code = wp_remote_retrieve_response_code($response);
    $response_body = wp_remote_retrieve_body($response);
    
    if ($status_code < 200 || $status_code >= 300) {
        wpsec_debug_log('❗ WPFort Live Feed: Unexpected HTTP response code when sending event: ' . $status_code, 'info');
        wpsec_debug_log('📄 WPFort Live Feed: Response body: ' . $response_body, 'info');
        return new WP_Error('live_feed_error', 'Failed to send event. Status code: ' . $status_code);
    }
    
    wpsec_debug_log('✅ WPFort Live Feed: Successfully sent event: ' . $event_name . ' (Status: ' . $status_code . ')', 'info');
    
    return true;
}

/**
 * Hook into WordPress post-related events
 */
function wpsec_register_post_event_hooks() {
    // New post published or updated - Map to operator actions
    add_action('wp_insert_post', function($post_id, $post, $update) {
        // Skip auto-drafts, revisions, and auto-saves
        if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id) || $post->post_status === 'auto-draft') {
            return;
        }

        // For the live feed, we'll map content updates to operator actions
        $event_name = $update ? WPSEC_Events::ACTION_COMPLETED : WPSEC_Events::ACTION_COMPLETED;
        $action_text = $update ? 'updated' : 'published';
        $vertical = 'wordpress/content';
        
        // Get post author details
        $author = get_userdata($post->post_author);
        $author_username = $author ? $author->user_login : 'unknown';
        
        // Create message
        $message = sprintf('%s "%s" %s by %s', 
            ucfirst($post->post_type), 
            $post->post_title, 
            $action_text,
            $author_username
        );
        
        // Metadata
        $metadata = array(
            'post_id' => $post_id,
            'post_type' => $post->post_type,
            'author' => $author_username,
            'title' => $post->post_title,
            'status' => $post->post_status,
            'action_type' => $update ? 'update' : 'create'
        );
        
        // Send the event
        wpsec_send_live_feed_event(
            $event_name,
            $vertical,
            'success',
            $message,
            $metadata
        );
    }, 10, 3);
    
    // Post deletion - Map to file delete completed
    add_action('before_delete_post', function($post_id) {
        $post = get_post($post_id);
        
        if (!$post || wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
            return;
        }
        
        // Get post author details
        $author = get_userdata($post->post_author);
        $author_username = $author ? $author->user_login : 'unknown';
        
        // Create message
        $message = sprintf('%s "%s" deleted', 
            ucfirst($post->post_type), 
            $post->post_title
        );
        
        // For the live feed, we'll map post deletion to file delete (closest match)
        $event_name = WPSEC_Events::FILE_DELETE_COMPLETED;
        $vertical = 'wordpress/content';
        
        // Metadata
        $metadata = array(
            'post_id' => $post_id,
            'post_type' => $post->post_type,
            'author' => $author_username,
            'title' => $post->post_title
        );
        
        // Get current user (who is deleting)
        $current_user = wp_get_current_user();
        if ($current_user && $current_user->exists()) {
            $metadata['deleted_by'] = $current_user->user_login;
        }
        
        // Send the event
        wpsec_send_live_feed_event(
            $event_name,
            $vertical,
            'success',
            $message,
            $metadata
        );
    });
}

/**
 * Hook into WordPress user-related events
 */
function wpsec_register_user_event_hooks() {
    // Admin user login - Map to operator action
    add_action('wp_login', function($user_login, $user) {
        // Check if the user has admin privileges
        if (in_array('administrator', $user->roles)) {
            // Get user IP address
            $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
            
            // Create message
            $message = sprintf('Administrator "%s" logged in', $user_login);
            
            // Metadata
            $metadata = array(
                'user_id' => $user->ID,
                'username' => $user_login,
                'ip_address' => $ip,
                'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
                'action_type' => 'admin_login'
            );
            
            // Send the event using operator action completed
            wpsec_send_live_feed_event(
                WPSEC_Events::ACTION_COMPLETED,
                'operator',
                'success',
                $message,
                $metadata
            );
        }
    }, 10, 2);
    
    // New user creation - Map to operator action
    add_action('user_register', function($user_id) {
        $user = get_userdata($user_id);
        
        // Get creator info if available
        $current_user = wp_get_current_user();
        $creator = ($current_user && $current_user->exists()) ? $current_user->user_login : 'system';
        
        // Create message
        $message = sprintf('New user "%s" created with role: %s', 
            $user->user_login, 
            !empty($user->roles) ? implode(', ', $user->roles) : 'none'
        );
        
        // Metadata
        $metadata = array(
            'user_id' => $user_id,
            'username' => $user->user_login,
            'email' => $user->user_email,
            'roles' => $user->roles,
            'created_by' => $creator,
            'action_type' => 'user_creation'
        );
        
        // Send the event using operator action completed
        wpsec_send_live_feed_event(
            WPSEC_Events::ACTION_COMPLETED,
            'operator',
            'success',
            $message,
            $metadata
        );
    });
    
    // User deletion - Map to file delete
    add_action('delete_user', function($user_id) {
        $user = get_userdata($user_id);
        
        // Get deleter info
        $current_user = wp_get_current_user();
        $deleter = ($current_user && $current_user->exists()) ? $current_user->user_login : 'system';
        
        // Create message
        $message = sprintf('User "%s" deleted', $user->user_login);
        
        // Metadata
        $metadata = array(
            'user_id' => $user_id,
            'username' => $user->user_login,
            'roles' => $user->roles,
            'deleted_by' => $deleter,
            'action_type' => 'user_deletion'
        );
        
        // Send the event using file delete completed
        wpsec_send_live_feed_event(
            WPSEC_Events::FILE_DELETE_COMPLETED,
            'operator',
            'success',
            $message,
            $metadata
        );
    });
}

/**
 * Hook into firewall events
 */
function wpsec_register_firewall_event_hooks() {
    // Firewall blocking events - Use canonical event name
    add_action('wpsec_firewall_blocked', function($rule_id, $ip, $request_data) {
        // Create message
        $message = sprintf('Firewall blocked request from IP %s (Rule ID: %s)', $ip, $rule_id);
        
        // Extract request details
        $uri = !empty($request_data['uri']) ? $request_data['uri'] : 'unknown';
        $method = !empty($request_data['method']) ? $request_data['method'] : 'unknown';
        
        // Metadata
        $metadata = array(
            'rule_id' => $rule_id,
            'ip' => $ip,
            'uri' => $uri,
            'method' => $method,
            'request_details' => substr(json_encode($request_data), 0, 1000) // Limit size of request data
        );
        
        // Send the event using canonical name
        wpsec_send_live_feed_event(
            WPSEC_Events::ATTACKS_BLOCKED,
            'network_layer',
            'success',
            $message,
            $metadata
        );
    }, 10, 3);
}

/**
 * Hook into plugin-related events
 */
function wpsec_register_plugin_event_hooks() {
    // Plugin activation
    add_action('activated_plugin', function($plugin) {
        $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
        $plugin_name = $plugin_data['Name'] ?? basename($plugin, '.php');
        
        $message = sprintf('Plugin activated: %s', $plugin_name);
        
        $metadata = array(
            'plugin_file' => $plugin,
            'plugin_name' => $plugin_name,
            'plugin_version' => $plugin_data['Version'] ?? 'unknown'
        );
        
        wpsec_send_live_feed_event(
            WPSEC_Events::PLUGINS_ACTIVATED,
            'application_layer',
            'success',
            $message,
            $metadata
        );
    });
    
    // Plugin deactivation
    add_action('deactivated_plugin', function($plugin) {
        $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
        $plugin_name = $plugin_data['Name'] ?? basename($plugin, '.php');
        
        $message = sprintf('Plugin deactivated: %s', $plugin_name);
        
        $metadata = array(
            'plugin_file' => $plugin,
            'plugin_name' => $plugin_name,
            'plugin_version' => $plugin_data['Version'] ?? 'unknown'
        );
        
        wpsec_send_live_feed_event(
            WPSEC_Events::PLUGINS_DEACTIVATED,
            'application_layer',
            'success',
            $message,
            $metadata
        );
    });
}

/**
 * Hook into resource usage monitoring
 * This requires setting up a WordPress cron job to periodically check resource usage
 */
function wpsec_register_resource_monitoring() {
    // Register the cron event if not already scheduled
    if (!wp_next_scheduled('wpsec_check_resource_usage')) {
        wp_schedule_event(time(), 'hourly', 'wpsec_check_resource_usage');
    }
    
    // Handler for the resource usage check
    add_action('wpsec_check_resource_usage', function() {
        // Check memory usage
        $memory_usage = function_exists('memory_get_usage') ? round(memory_get_usage(true) / 1024 / 1024, 2) : null;
        $memory_limit = ini_get('memory_limit');
        
        // Check server load if available
        $load_average = function_exists('sys_getloadavg') ? sys_getloadavg() : null;
        $cpu_load = $load_average ? $load_average[0] : null;
        
        // Check disk space
        $disk_free_space = function_exists('disk_free_space') ? round(disk_free_space(ABSPATH) / 1024 / 1024 / 1024, 2) : null;
        $disk_total_space = function_exists('disk_total_space') ? round(disk_total_space(ABSPATH) / 1024 / 1024 / 1024, 2) : null;
        
        // Thresholds for alerts
        $memory_threshold = 0.8; // 80% of memory limit
        $cpu_threshold = 5; // Load average > 5
        $disk_threshold = 0.1; // Less than 10% free space
        
        // Calculate memory percentage if possible
        $memory_percentage = null;
        if ($memory_usage !== null && preg_match('/^(\d+)([MG])/', $memory_limit, $matches)) {
            $limit_value = (int)$matches[1];
            $limit_unit = $matches[2];
            
            // Convert to MB if in GB
            if ($limit_unit === 'G') {
                $limit_value *= 1024;
            }
            
            $memory_percentage = ($memory_usage / $limit_value);
        }
        
        // Calculate disk space percentage
        $disk_percentage = null;
        if ($disk_free_space !== null && $disk_total_space !== null) {
            $disk_percentage = 1 - ($disk_free_space / $disk_total_space);
        }
        
        // Check for resource spikes
        $spike_detected = false;
        $spike_message = '';
        $spike_details = array();
        
        // Memory spike
        if ($memory_percentage !== null && $memory_percentage > $memory_threshold) {
            $spike_detected = true;
            $spike_message = sprintf('Memory usage spike detected: %.2f%% of limit', $memory_percentage * 100);
            $spike_details['memory'] = array(
                'usage' => $memory_usage . 'MB',
                'limit' => $memory_limit,
                'percentage' => round($memory_percentage * 100, 2) . '%'
            );
        }
        
        // CPU spike
        if ($cpu_load !== null && $cpu_load > $cpu_threshold) {
            $spike_detected = true;
            
            if (!empty($spike_message)) {
                $spike_message .= ' and ';
            }
            
            $spike_message .= sprintf('CPU load spike detected: %.2f', $cpu_load);
            $spike_details['cpu'] = array(
                'load' => $cpu_load,
                'load_5min' => $load_average[1],
                'load_15min' => $load_average[2]
            );
        }
        
        // Disk space issue
        if ($disk_percentage !== null && $disk_percentage > (1 - $disk_threshold)) {
            $spike_detected = true;
            
            if (!empty($spike_message)) {
                $spike_message .= ' and ';
            }
            
            $spike_message .= sprintf('Low disk space detected: %.2f%% used', $disk_percentage * 100);
            $spike_details['disk'] = array(
                'free' => $disk_free_space . 'GB',
                'total' => $disk_total_space . 'GB',
                'percentage_used' => round($disk_percentage * 100, 2) . '%'
            );
        }
        
        // If any spike is detected, send an event
        if ($spike_detected) {
            // Collect all resource info for metadata
            $metadata = array(
                'memory_usage' => $memory_usage !== null ? $memory_usage . 'MB' : 'unknown',
                'memory_limit' => $memory_limit,
                'cpu_load' => $cpu_load !== null ? $cpu_load : 'unknown',
                'disk_free' => $disk_free_space !== null ? $disk_free_space . 'GB' : 'unknown',
                'spike_details' => $spike_details,
                'php_version' => PHP_VERSION,
                'wordpress_version' => get_bloginfo('version')
            );
            
            // Send the event
            wpsec_send_live_feed_event(
                'resource_usage_spike',
                'wordpress/performance',
                'warning',
                $spike_message,
                $metadata
            );
        }
    });
}

/**
 * Initialize all live feed event hooks
 */
function wpsec_initialize_live_feed() {
    wpsec_register_post_event_hooks();
    wpsec_register_user_event_hooks();
    wpsec_register_firewall_event_hooks();
    wpsec_register_plugin_event_hooks();
    wpsec_register_resource_monitoring();
}

/**
 * Test function to verify the live feed system works
 * Call this function from your admin panel or via AJAX to test
 */
function wpsec_test_live_feed() {
    $test_events = array(
        array(
            'event' => WPSEC_Events::ATTACKS_BLOCKED,
            'vertical' => 'network_layer',
            'message' => 'Test firewall block event',
            'metadata' => array(
                'ip' => '192.168.1.100',
                'rule_id' => 'test_rule_001',
                'test' => true
            )
        ),
        array(
            'event' => WPSEC_Events::PLUGINS_ACTIVATED,
            'vertical' => 'application_layer',
            'message' => 'Test plugin activation event',
            'metadata' => array(
                'plugin_name' => 'Test Plugin',
                'test' => true
            )
        ),
        array(
            'event' => WPSEC_Events::ACTION_COMPLETED,
            'vertical' => 'operator',
            'message' => 'Test operator action completed',
            'metadata' => array(
                'action_type' => 'test_action',
                'test' => true
            )
        )
    );
    
    $results = array();
    
    foreach ($test_events as $test) {
        $result = wpsec_send_live_feed_event(
            $test['event'],
            $test['vertical'],
            'success',
            $test['message'],
            $test['metadata']
        );
        
        $results[] = array(
            'event' => $test['event'],
            'success' => !is_wp_error($result),
            'error' => is_wp_error($result) ? $result->get_error_message() : null
        );
    }
    
    return $results;
}

// Initialize the live feed system
add_action('init', 'wpsec_initialize_live_feed', 20);
