<?php
/**
 * Audit Log Management Class
 *
 * @package VMPFence
 * @since 1.0.0
 * @since 2.2.5 -- Added more event types and translations in generate_message() method, and enhanced logging for all critical actions across the plugin
 * @since 2.2.6 -- Added Custom Pattern block to FIrewall, Custom Pattern Block Message Updated
 */

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

/**
 * VMPFence Audit Log Class
 *
 * @since 1.0.0
 */
class VMPFence_Audit_Log {

    /** @var int|null Per-request ID (all events in one HTTP request share this). */
    private static $request_id = null;

    /**
     * Get (or generate) the request ID for the current HTTP request.
     * Uses atomic increment on wp_options to avoid race conditions.
     *
     * @since 2.2.5
     * @return int
     */
    private static function get_request_id() {
        if (self::$request_id === null) {
            global $wpdb;
            $option_name = 'vmpfence_audit_request_number';
            $wpdb->query($wpdb->prepare(
                "INSERT INTO {$wpdb->options} (option_name, option_value, autoload) VALUES (%s, 1, 'no') ON DUPLICATE KEY UPDATE option_value = option_value + 1",
                $option_name
            ));
            self::$request_id = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s",
                $option_name
            ));
        }
        return self::$request_id;
    }

    /**
     * Group flat entries by request ID (stored in the `action` column).
     * Old rows with a non-numeric action become standalone groups.
     *
     * @since 2.2.5
     * @param array $entries Flat list ordered by time DESC.
     * @return array Array of groups, each with 'primary' (first entry) and 'entries'.
     */
    public static function group_entries($entries) {
        $groups = array();
        $current = null;

        foreach ($entries as $entry) {
            $rid = $entry['action'];
            if ($current !== null && is_numeric($rid) && $current['request_id'] === $rid) {
                $current['entries'][] = $entry;
            } else {
                if ($current !== null) {
                    $groups[] = $current;
                }
                $current = array(
                    'request_id' => $rid,
                    'primary'    => $entry,
                    'entries'    => array($entry),
                );
            }
        }
        if ($current !== null) {
            $groups[] = $current;
        }
        return $groups;
    }

    /**
     * Log an event
     *
     * @since 1.0.0
     * @since 2.2.2 - Avoid logging if tables are being deleted on deactivation
     * @since 2.2.5 - Stores per-request ID in the action column for grouping
     * @param string $event_type Event type
     * @param array $data Event data
     * @return bool
     */
    public static function log_event($event_type, $data = array()) {
        // Check if audit log is enabled (default: true)
        $enabled = get_option('vmpfence_enable_audit_log', true);
        if (!$enabled) {
            return false;
        }

        global $wpdb;

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        
        // Check if we're deleting tables during deactivation
        $enable_deactivation_choice = get_option('vmpfence_enable_deactivation_choice', 0);
        if ($enable_deactivation_choice) {
            $data_action = get_transient('vmpfence_deactivation_data_action');
            if ($data_action === 'delete') {
                return false; // Skip logging when deleting all tables during deactivation
            }
        }
        
        // Ensure table exists before inserting (self-healing)
        $table_exists = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table_name));
        if ($table_exists !== $table_name) {
            // Table missing - recreate it
            if (class_exists('VMPFence_Database')) {
                VMPFence_Database::create_tables();
            }
        }
        
        // Get current user info
        $current_user = wp_get_current_user();
        $user_id = $current_user->ID ?? 0;
        $username = $current_user->user_login ?? '';
        $user_role = '';
        
        if ($current_user->exists()) {
            $user_role = implode(', ', $current_user->roles);
        }

        // Get request info
        $ip = class_exists('VMPFence_Utils') ? VMPFence_Utils::get_real_ip() : (
            !empty($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : ''
        );
        
        // Convert IP to binary format for storage (varbinary(16) supports both IPv4 and IPv6)
        $ip_binary = null;
        if (!empty($ip) && filter_var($ip, FILTER_VALIDATE_IP)) {
            $ip_binary = @inet_pton($ip);
        }
        
        $user_agent = sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'] ?? ''));

        // Prepare event data
        $event_data = array(
            'time' => microtime(true),
            'event_type' => sanitize_text_field($event_type),
            'user_id' => $user_id,
            'username' => $username,
            'user_role' => $user_role,
            'source_ip' => $ip_binary,
            'user_agent' => $user_agent,
            'object_type' => $data['object_type'] ?? null,
            'object_id' => $data['object_id'] ?? null,
            'object_name' => $data['object_name'] ?? null,
            'action' => (string) self::get_request_id(),
            'message' => $data['message'] ?? self::generate_message($event_type, $data),
            'old_value' => isset($data['old_value']) ? maybe_serialize($data['old_value']) : null,
            'new_value' => isset($data['new_value']) ? maybe_serialize($data['new_value']) : null,
            'additional_info' => maybe_serialize($data)
        );

        // Insert into database - %s for binary data is correct per WordPress Codex
        $result = $wpdb->insert(
            $table_name,
            $event_data,
            array('%f', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s')
        );

        // Send to central management if enabled
        if (get_option('vmpfence_central_management_enabled', false)) {
            self::send_to_central($event_data);
        }

        return $result !== false;
    }

    /**
     * Get audit log entries
     *
     * @since 1.0.0
     * @param array $args Query arguments
     * @return array
     */
    public static function get_entries($args = array()) {
        global $wpdb;

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        
        // Default arguments
        $defaults = array(
            'limit' => 50,
            'offset' => 0,
            'event_type' => '',
            'user_id' => 0,
            'date_from' => '',
            'date_to' => '',
            'search' => '',
            'order_by' => 'time',
            'order' => 'DESC'
        );

        $args = wp_parse_args($args, $defaults);

        // Build WHERE clause
        $where_conditions = array('1=1');
        $where_values = array();

        if (!empty($args['event_type'])) {
            $where_conditions[] = 'event_type = %s';
            $where_values[] = $args['event_type'];
        }

        if (!empty($args['user_id'])) {
            $where_conditions[] = 'user_id = %d';
            $where_values[] = $args['user_id'];
        }

        if (!empty($args['date_from'])) {
            $where_conditions[] = 'time >= %f';
            $where_values[] = strtotime($args['date_from']);
        }

        if (!empty($args['date_to'])) {
            $where_conditions[] = 'time <= %f';
            $where_values[] = strtotime($args['date_to']) + 86399; // End of day
        }

        if (!empty($args['search'])) {
            $where_conditions[] = '(message LIKE %s OR username LIKE %s OR object_name LIKE %s)';
            $search_term = '%' . $wpdb->esc_like($args['search']) . '%';
            $where_values[] = $search_term;
            $where_values[] = $search_term;
            $where_values[] = $search_term;
        }

        $where_clause = implode(' AND ', $where_conditions);

        // Validate order by
        $allowed_order_by = array('time', 'event_type', 'username', 'source_ip');
        if (!in_array($args['order_by'], $allowed_order_by)) {
            $args['order_by'] = 'time';
        }

        // Validate order
        $args['order'] = strtoupper($args['order']) === 'ASC' ? 'ASC' : 'DESC';

        // Build query
        // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared -- Table name properly escaped via VMPFence_Constants
        $query = "SELECT * FROM $table_name WHERE $where_clause ORDER BY {$args['order_by']} {$args['order']} LIMIT %d OFFSET %d";
        $where_values[] = $args['limit'];
        $where_values[] = $args['offset'];

        if (!empty($where_values)) {
            $query = $wpdb->prepare($query, $where_values);
        }

        $results = $wpdb->get_results($query, ARRAY_A);
        // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared

        // Process results
        foreach ($results as &$result) {
            $result['additional_info'] = maybe_unserialize($result['additional_info']);
            $result['old_value'] = maybe_unserialize($result['old_value']);
            $result['new_value'] = maybe_unserialize($result['new_value']);
            $result['time_formatted'] = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), (int)$result['time']);
            $result['ip_formatted'] = self::format_ip_address($result['source_ip']);
        }

        return $results;
    }

    /**
     * Get audit log count
     *
     * @since 1.0.0
     * @param array $args Query arguments
     * @return int
     */
    public static function get_count($args = array()) {
        global $wpdb;

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        
        // Build WHERE clause (same as get_entries)
        $where_conditions = array('1=1');
        $where_values = array();

        if (!empty($args['event_type'])) {
            $where_conditions[] = 'event_type = %s';
            $where_values[] = $args['event_type'];
        }

        if (!empty($args['user_id'])) {
            $where_conditions[] = 'user_id = %d';
            $where_values[] = $args['user_id'];
        }

        if (!empty($args['date_from'])) {
            $where_conditions[] = 'time >= %f';
            $where_values[] = strtotime($args['date_from']);
        }

        if (!empty($args['date_to'])) {
            $where_conditions[] = 'time <= %f';
            $where_values[] = strtotime($args['date_to']) + 86399;
        }

        if (!empty($args['search'])) {
            $where_conditions[] = '(message LIKE %s OR username LIKE %s OR object_name LIKE %s)';
            $search_term = '%' . $wpdb->esc_like($args['search']) . '%';
            $where_values[] = $search_term;
            $where_values[] = $search_term;
            $where_values[] = $search_term;
        }

        $where_clause = implode(' AND ', $where_conditions);
        // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared -- Table name properly escaped via VMPFence_Constants
        $query = "SELECT COUNT(*) FROM $table_name WHERE $where_clause";

        if (!empty($where_values)) {
            $query = $wpdb->prepare($query, $where_values);
        }

        return (int) $wpdb->get_var($query);
        // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
    }

    /**
     * Delete old audit log entries
     *
     * @since 1.0.0
     * @return int Number of deleted entries
     */
    public static function cleanup_old_entries() {
        global $wpdb;

        $retention_days = get_option('vmpfence_audit_log_retention_days', 90);
        $cutoff_time = time() - ($retention_days * 86400);

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        
        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $deleted = $wpdb->query($wpdb->prepare(
            "DELETE FROM `{$table_name}` WHERE time < %f",
            $cutoff_time
        ));
        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

        // Note: Don't log cleanup event here to avoid potential recursion
        // The cleanup is a maintenance task and doesn't need audit logging

        return $deleted;
    }

    /**
     * Export audit log
     *
     * @since 1.0.0
     * @param array $args Export arguments
     * @return string CSV content
     */
    public static function export_csv($args = array()) {
        $entries = self::get_entries(array_merge($args, array('limit' => 10000)));
        
        $csv_data = array();
        $csv_data[] = array(
            'Time',
            'Event Type',
            'User',
            'User Role',
            'Source IP',
            'Action',
            'Object Type',
            'Object Name',
            'Message'
        );

        foreach ($entries as $entry) {
            $csv_data[] = array(
                $entry['time_formatted'],
                $entry['event_type'],
                $entry['username'],
                $entry['user_role'],
                $entry['ip_formatted'],
                $entry['action'],
                $entry['object_type'],
                $entry['object_name'],
                $entry['message']
            );
        }

        // Convert to CSV
        $output = fopen('php://temp', 'r+');
        foreach ($csv_data as $row) {
            fputcsv($output, $row);
        }
        rewind($output);
        $csv_string = stream_get_contents($output);
        fclose($output);

        return $csv_string;
    }

    /**
     * Get recent audit log entries since a specific time
     *
     * @since 2.0.0
     * @param float $since_time Unix timestamp (with microseconds)
     * @param int $limit Maximum number of entries
     * @return array
     */
    public static function get_recent_entries($since_time = 0, $limit = 20) {
        global $wpdb;

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        
        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $results = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM `{$table_name}` WHERE time > %f ORDER BY time DESC LIMIT %d",
            $since_time,
            $limit
        ), ARRAY_A);
        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

        // Process results
        foreach ($results as &$result) {
            $result['additional_info'] = maybe_unserialize($result['additional_info']);
            $result['old_value'] = maybe_unserialize($result['old_value']);
            $result['new_value'] = maybe_unserialize($result['new_value']);
            $result['time_formatted'] = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), (int)$result['time']);
            $result['ip_formatted'] = self::format_ip_address($result['source_ip']);
        }

        return $results;
    }

    /**
     * Format IP address for display
     *
     * @since 2.0.0
     * @param mixed $ip IP address in various formats
     * @return string Formatted IP address
     */
    private static function format_ip_address($ip) {
        if (empty($ip)) {
            return 'N/A';
        }

        // If it's already a string IP, return it
        if (filter_var($ip, FILTER_VALIDATE_IP)) {
            return $ip;
        }

        // If it's binary format (4 bytes for IPv4, 16 bytes for IPv6), convert it
        if (is_string($ip) && (strlen($ip) === 4 || strlen($ip) === 16)) {
            $formatted = @inet_ntop($ip);
            if ($formatted !== false) {
                return $formatted;
            }
        }

        // If it's a numeric value, treat as IPv4 integer (legacy support)
        if (is_numeric($ip) && $ip <= 4294967295) {
            $formatted = @long2ip((int)$ip);
            if ($formatted && $formatted !== '0.0.0.0') {
                return $formatted;
            }
        }

        return 'N/A';
    }

    /**
     * Get event type statistics
     *
     * @since 1.0.0
     * @param int $days Number of days to analyze
     * @return array
     */
    public static function get_event_statistics($days = 30) {
        global $wpdb;

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        $cutoff_time = time() - ($days * 86400);

        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $results = $wpdb->get_results($wpdb->prepare(
            "SELECT event_type, COUNT(*) as count FROM `{$table_name}` WHERE time >= %f GROUP BY event_type ORDER BY count DESC",
            $cutoff_time
        ), ARRAY_A);
        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

        return $results;
    }

    /**
     * Get user activity statistics
     *
     * @since 1.0.0
     * @param int $days Number of days to analyze
     * @return array
     */
    public static function get_user_statistics($days = 30) {
        global $wpdb;

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        $cutoff_time = time() - ($days * 86400);

        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $results = $wpdb->get_results($wpdb->prepare(
            "SELECT username, user_role, COUNT(*) as count FROM `{$table_name}` WHERE time >= %f AND user_id > 0 GROUP BY username, user_role ORDER BY count DESC LIMIT 20",
            $cutoff_time
        ), ARRAY_A);
        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

        return $results;
    }

    /**
     * Get IP activity statistics
     *
     * @since 1.0.0
     * @param int $days Number of days to analyze
     * @return array
     */
    public static function get_ip_statistics($days = 30) {
        global $wpdb;

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        $cutoff_time = time() - ($days * 86400);

        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $results = $wpdb->get_results($wpdb->prepare(
            "SELECT source_ip, COUNT(*) as count FROM `{$table_name}` WHERE time >= %f GROUP BY source_ip ORDER BY count DESC LIMIT 20",
            $cutoff_time
        ), ARRAY_A);
        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

        // Format IP addresses (source_ip is varbinary, convert to readable format)
        foreach ($results as &$result) {
            if (is_string($result['source_ip']) && (strlen($result['source_ip']) === 4 || strlen($result['source_ip']) === 16)) {
                $result['ip_formatted'] = @inet_ntop($result['source_ip']) ?: $result['source_ip'];
            } else {
                $result['ip_formatted'] = $result['source_ip'];
            }
        }

        return $results;
    }

    /**
     * Get daily activity chart data
     *
     * @since 1.0.0
     * @param int $days Number of days
     * @return array
     */
    public static function get_daily_activity($days = 30) {
        global $wpdb;

        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_AUDIT_LOG);
        $cutoff_time = time() - ($days * 86400);

        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $results = $wpdb->get_results($wpdb->prepare(
            "SELECT DATE(FROM_UNIXTIME(time)) as date, COUNT(*) as count FROM `{$table_name}` WHERE time >= %f GROUP BY DATE(FROM_UNIXTIME(time)) ORDER BY date",
            $cutoff_time
        ), ARRAY_A);
        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

        // Fill in missing dates with zero counts
        $activity = array();
        for ($i = $days - 1; $i >= 0; $i--) {
            $date = gmdate('Y-m-d', time() - ($i * 86400));
            $activity[$date] = 0;
        }

        foreach ($results as $result) {
            $activity[$result['date']] = (int) $result['count'];
        }

        return $activity;
    }

    /**
     * Generate message for event type
     *
     * @since 1.0.0
     * @since 2.2.5 Added more event types and translations
     * @param string $event_type Event type
     * @param array $data Event data
     * @return string
     */
    private static function generate_message($event_type, $data) {
        switch ($event_type) {
            case VMPFence_Constants::EVENT_LOGIN_SUCCESS:
                /* translators: %s: username */
                return sprintf(__('User %s logged in successfully', 'vmpfence-security'), $data['username'] ?? 'unknown');

            case VMPFence_Constants::EVENT_LOGIN_FAILURE:
                /* translators: %s: username */
                return sprintf(__('Failed login attempt for user %s', 'vmpfence-security'), $data['username'] ?? 'unknown');

            case VMPFence_Constants::EVENT_LOGIN_BLOCKED:
                /* translators: %s: IP address */
                return sprintf(__('Login attempt blocked for IP %s', 'vmpfence-security'), $data['ip'] ?? 'unknown');

            case VMPFence_Constants::EVENT_SCAN_STARTED:
                /* translators: %s: scan type */
                return sprintf(__('Security scan started (%s)', 'vmpfence-security'), $data['scan_type'] ?? 'standard');

            case VMPFence_Constants::EVENT_SCAN_COMPLETED:
                /* translators: %d: number of threats found */
                return sprintf(__('Security scan completed (%d threats found)', 'vmpfence-security'), $data['threats_found'] ?? 0);

            case VMPFence_Constants::EVENT_THREAT_DETECTED:
                /* translators: %s: threat type */
                return sprintf(__('Security threat detected: %s', 'vmpfence-security'), $data['threat_type'] ?? 'unknown');

            case VMPFence_Constants::EVENT_IP_BLOCKED:
                /* translators: %1$s: IP address, %2$s: reason for blocking */
                return sprintf(__('IP address %1$s blocked (%2$s)', 'vmpfence-security'), $data['ip'] ?? 'unknown', $data['reason'] ?? 'unknown');

            case VMPFence_Constants::EVENT_WAF_BLOCKED:
                /* translators: %s: IP address */
                return sprintf(__('WAF blocked attack from %s', 'vmpfence-security'), $data['ip'] ?? 'unknown');

            case VMPFence_Constants::EVENT_CONFIG_CHANGED:
                /* translators: %s: configuration setting name */
                return sprintf(__('Configuration setting %s changed', 'vmpfence-security'), $data['key'] ?? 'unknown');

            case 'plugin_activated':
                /* translators: %s: plugin name */
                return sprintf(__('Plugin activated: %s', 'vmpfence-security'), $data['plugin'] ?? 'unknown');

            case 'plugin_deactivated':
                /* translators: %s: plugin name */
                return sprintf(__('Plugin deactivated: %s', 'vmpfence-security'), $data['plugin'] ?? 'unknown');

            case 'theme_changed':
                /* translators: %s: theme name */
                return sprintf(__('Theme changed to: %s', 'vmpfence-security'), $data['new_theme'] ?? 'unknown');

            case 'user_registered':
                /* translators: %s: username */
                return sprintf(__('New user registered: %s', 'vmpfence-security'), $data['username'] ?? 'unknown');

            case 'post_saved':
                /* translators: %s: post title */
                return sprintf(__('Post saved: %s', 'vmpfence-security'), $data['post_title'] ?? 'unknown');

            case 'post_deleted':
                /* translators: %s: post title */
                return sprintf(__('Post deleted: %s', 'vmpfence-security'), $data['post_title'] ?? 'unknown');

            case 'file_uploaded':
                /* translators: %s: file name */
                return sprintf(__('File uploaded: %s', 'vmpfence-security'), $data['file_name'] ?? 'unknown');

            // --- User events (Observer_User) ---
            case 'user_role_changed':
                return sprintf(__('User role changed for %s: %s → %s', 'vmpfence-security'),
                    $data['username'] ?? '', $data['old_role'] ?? '', $data['new_role'] ?? '');
            case 'user_deleted':
                return sprintf(__('User deleted: %s (ID: %d)', 'vmpfence-security'),
                    $data['username'] ?? '', $data['user_id'] ?? 0);
            case 'user_logout':
                return sprintf(__('User %s logged out', 'vmpfence-security'), $data['username'] ?? 'unknown');
            case 'user_profile_updated':
                return sprintf(__('Profile updated for user: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'password_reset':
                return sprintf(__('Password reset for user: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'password_reset_requested':
                return sprintf(__('Password reset requested for: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'auth_cookie_set':
                return sprintf(__('Auth cookie set for user: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'app_password_created':
                return sprintf(__('Application password created: %s', 'vmpfence-security'), $data['name'] ?? '');
            case 'app_password_deleted':
                return sprintf(__('Application password deleted for user: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'app_password_used':
                return sprintf(__('Application password used by: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'user_capabilities_changed':
                return sprintf(__('Capabilities changed for user: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'user_level_changed':
                return sprintf(__('User level changed for: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'user_marked_spam':
                return sprintf(__('User marked as spam: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'user_unmarked_spam':
                return sprintf(__('User unmarked as spam: %s', 'vmpfence-security'), $data['username'] ?? '');

            // --- Content events (Observer_Content) ---
            case 'post_published':
                return sprintf(__('Post published: %s', 'vmpfence-security'), $data['post_title'] ?? '');
            case 'post_draft_created':
                return sprintf(__('Draft created: %s', 'vmpfence-security'), $data['post_title'] ?? '');
            case 'post_updated':
                return sprintf(__('Post updated: %s', 'vmpfence-security'), $data['post_title'] ?? '');
            case 'post_trashed':
                return sprintf(__('Post trashed: %s', 'vmpfence-security'), $data['post_title'] ?? '');
            case 'post_restored':
                return sprintf(__('Post restored from trash: %s', 'vmpfence-security'), $data['post_title'] ?? '');
            case 'comment_posted':
                return sprintf(__('Comment posted by %s on post #%d', 'vmpfence-security'),
                    $data['author'] ?? '', $data['post_id'] ?? 0);
            case 'comment_approved':
                return sprintf(__('Comment approved on post #%d', 'vmpfence-security'), $data['post_id'] ?? 0);
            case 'comment_spam':
                return sprintf(__('Comment marked as spam on post #%d', 'vmpfence-security'), $data['post_id'] ?? 0);
            case 'comment_trashed':
                return sprintf(__('Comment trashed on post #%d', 'vmpfence-security'), $data['post_id'] ?? 0);
            case 'comment_deleted':
                return sprintf(__('Comment deleted on post #%d', 'vmpfence-security'), $data['post_id'] ?? 0);
            case 'media_uploaded':
                return sprintf(__('Media uploaded: %s', 'vmpfence-security'), $data['filename'] ?? '');
            case 'media_edited':
                return sprintf(__('Media edited: %s', 'vmpfence-security'), $data['filename'] ?? '');
            case 'media_deleted':
                return sprintf(__('Media deleted: %s', 'vmpfence-security'), $data['filename'] ?? '');
            case 'term_created':
                return sprintf(__('Term created: %s (%s)', 'vmpfence-security'),
                    $data['name'] ?? '', $data['taxonomy'] ?? '');
            case 'term_edited':
                return sprintf(__('Term edited: %s (%s)', 'vmpfence-security'),
                    $data['name'] ?? '', $data['taxonomy'] ?? '');
            case 'term_deleted':
                return sprintf(__('Term deleted: %s (%s)', 'vmpfence-security'),
                    $data['name'] ?? '', $data['taxonomy'] ?? '');

            // --- Site events (Observer_Site) ---
            case 'option_siteurl_changed':
                return sprintf(__('Site URL changed from %s to %s', 'vmpfence-security'),
                    $data['old_value'] ?? '', $data['new_value'] ?? '');
            case 'option_home_changed':
                return sprintf(__('Home URL changed from %s to %s', 'vmpfence-security'),
                    $data['old_value'] ?? '', $data['new_value'] ?? '');
            case 'option_admin_email_changed':
                return sprintf(__('Admin email changed from %s to %s', 'vmpfence-security'),
                    $data['old_value'] ?? '', $data['new_value'] ?? '');
            case 'option_default_role_changed':
                return sprintf(__('Default user role changed to: %s', 'vmpfence-security'), $data['new_value'] ?? '');
            case 'option_registration_changed':
                return sprintf(__('User registration setting changed', 'vmpfence-security'));
            case 'option_blogname_changed':
                return sprintf(__('Site title changed to: %s', 'vmpfence-security'), $data['new_value'] ?? '');
            case 'option_description_changed':
                return sprintf(__('Site tagline changed', 'vmpfence-security'));
            case 'option_permalink_changed':
                return sprintf(__('Permalink structure changed', 'vmpfence-security'));
            case 'option_search_visibility_changed':
                return sprintf(__('Search engine visibility changed', 'vmpfence-security'));
            case 'plugin_installed':
                return sprintf(__('Plugin installed: %s', 'vmpfence-security'), $data['plugin'] ?? '');
            case 'plugin_updated':
                return sprintf(__('Plugin updated: %s', 'vmpfence-security'), $data['plugin'] ?? '');
            case 'plugin_deleted':
                return sprintf(__('Plugin deleted: %s', 'vmpfence-security'), $data['plugin'] ?? '');
            case 'theme_installed':
                return sprintf(__('Theme installed: %s', 'vmpfence-security'), $data['theme'] ?? '');
            case 'theme_updated':
                return sprintf(__('Theme updated: %s', 'vmpfence-security'), $data['theme'] ?? '');
            case 'theme_deleted':
                return sprintf(__('Theme deleted: %s', 'vmpfence-security'), $data['theme'] ?? '');
            case 'core_updated':
                return sprintf(__('WordPress core updated to %s', 'vmpfence-security'), $data['new_version'] ?? '');
            case 'auto_updates_completed':
                return sprintf(__('Auto-updates completed (%d items)', 'vmpfence-security'), $data['count'] ?? 0);
            case 'menu_created':
                return sprintf(__('Menu created: %s', 'vmpfence-security'), $data['menu_name'] ?? '');
            case 'menu_updated':
                return sprintf(__('Menu updated: %s', 'vmpfence-security'), $data['menu_name'] ?? '');
            case 'menu_deleted':
                return sprintf(__('Menu deleted: %s', 'vmpfence-security'), $data['menu_name'] ?? '');
            case 'customizer_saved':
                return __('Customizer settings saved', 'vmpfence-security');
            case 'file_editor_used':
                return sprintf(__('File edited via built-in editor: %s', 'vmpfence-security'), $data['file'] ?? '');
            case 'role_capabilities_changed':
                return sprintf(__('Role capabilities changed: %s', 'vmpfence-security'), $data['role'] ?? '');
            case 'recovery_key_generated':
                return __('Recovery mode key generated', 'vmpfence-security');
            case 'mail_sent':
                return sprintf(__('Email sent to: %s', 'vmpfence-security'), $data['to'] ?? '');
            case 'mail_failed':
                return sprintf(__('Email failed to: %s', 'vmpfence-security'), $data['to'] ?? '');

            // --- VMPFence events (Observer_VMPFence) ---
            case 'vmpfence_waf_mode_changed':
                return sprintf(__('Web Application Firewall (WAF) %s', 'vmpfence-security'),
                    !empty($data['new_value']) ? 'Enabled' : 'Disabled');
            case 'vmpfence_waf_protection_level_changed':
                $level = strtolower((string)($data['new_value'] ?? ''));
                $state = ($level === 'extended') ? __('Enabled', 'vmpfence-security') : __('Disabled', 'vmpfence-security');
                return sprintf(__('WAF Extended Protection %s', 'vmpfence-security'), $state);
            case 'vmpfence_brute_force_toggled':
                return sprintf(__('Brute Force Protection %s', 'vmpfence-security'),
                    !empty($data['new_value']) ? 'Enabled' : 'Disabled');
            case 'brute_force_lockout':
                return sprintf(__('IP %s locked out (%s)', 'vmpfence-security'),
                    $data['ip'] ?? '', !empty($data['permanent']) ? 'permanent' : ($data['duration'] ?? '0') . ' min');
            case 'vmpfence_audit_log_mode_changed':
                return sprintf(__('Audit log mode changed from %s to %s', 'vmpfence-security'),
                    $data['old_mode'] ?? '', $data['new_mode'] ?? '');
            case 'vmpfence_license_changed':
                return __('License key changed', 'vmpfence-security');

            // --- Blocking / Unblocking events ---
            case 'vmpfence_ip_unblocked':
                return sprintf(__('IP: %s Unblocked', 'vmpfence-security'), $data['ip'] ?? 'unknown');
            case 'vmpfence_country_blocked':
                $cname = $data['country_name'] ?? $data['country'] ?? 'unknown';
                return sprintf(__('Country blocked: %s (%s)', 'vmpfence-security'), $cname, $data['country'] ?? '');
            case 'vmpfence_country_unblocked':
                $cname = $data['country_name'] ?? $data['country'] ?? 'unknown';
                return sprintf(__('Country unblocked: %s (%s)', 'vmpfence-security'), $cname, $data['country'] ?? '');
            case 'vmpfence_custom_pattern_added':
                $rules = $data['rules'] ?? array();
                if (!empty($rules)) {
                    $rule_parts = array();
                    $type_labels = array('hostname' => 'Hostname', 'user_agent' => 'User Agent', 'referrer' => 'Referrer', 'ip_range' => 'IP Range');
                    foreach ($rules as $r) {
                        $label = $type_labels[$r['type'] ?? ''] ?? ucfirst($r['type'] ?? '');
                        $rule_parts[] = $label . ': ' . ($r['value'] ?? '');
                    }
                    return sprintf(__('Custom pattern blocked (%d rules): %s', 'vmpfence-security'),
                        count($rules), implode(', ', $rule_parts));
                }
                return sprintf(__('Custom pattern blocked (%d rules)', 'vmpfence-security'), $data['count'] ?? 0);
            case 'vmpfence_custom_pattern_deleted':
                $rules = $data['rules'] ?? array();
                if (!empty($rules)) {
                    $rule_parts = array();
                    $type_labels = array('hostname' => 'Hostname', 'user_agent' => 'User Agent', 'referrer' => 'Referrer', 'ip_range' => 'IP Range');
                    foreach ($rules as $r) {
                        $label = $type_labels[$r['type'] ?? ''] ?? ucfirst($r['type'] ?? '');
                        $rule_parts[] = $label . ': ' . ($r['value'] ?? '');
                    }
                    return sprintf(__('Custom pattern unblocked (%d rules): %s', 'vmpfence-security'),
                        count($rules), implode(', ', $rule_parts));
                }
                return sprintf(__('Custom pattern unblocked', 'vmpfence-security'));
            case 'vmpfence_custom_pattern_toggled':
                return sprintf(__('Custom Pattern: %s %s', 'vmpfence-security'),
                    $data['pattern_id'] ?? 'unknown',
                    !empty($data['enabled']) ? 'Enabled' : 'Disabled');

            case 'config_imported':
                return sprintf(__('Configuration imported (%s)', 'vmpfence-security'),
                    is_array($data['sections'] ?? null) ? implode(', ', $data['sections']) : '');
            case 'config_exported':
                return __('Configuration exported', 'vmpfence-security');
            case 'config_reset':
                return __('Configuration reset to defaults', 'vmpfence-security');
            case 'config_deleted':
                return sprintf(__('Configuration key deleted: %s', 'vmpfence-security'), $data['key'] ?? '');
            case 'backup_created':
                return sprintf(__('Backup created: %s', 'vmpfence-security'), $data['backup_id'] ?? '');
            case 'backup_restored':
                return sprintf(__('Backup restored: %s', 'vmpfence-security'), $data['backup_id'] ?? '');
            case 'backup_deleted':
                return sprintf(__('Backup deleted: %s', 'vmpfence-security'), $data['backup_id'] ?? '');
            case 'database_updated':
                return sprintf(__('Database updated from v%s to v%s', 'vmpfence-security'),
                    $data['from_version'] ?? '', $data['to_version'] ?? '');
            case 'database_cleanup':
                return sprintf(__('Database cleanup completed (%d records removed)', 'vmpfence-security'),
                    $data['deleted_by_days'] ?? 0);
            case 'support_ticket_submitted':
                return sprintf(__('Support ticket submitted: %s', 'vmpfence-security'), $data['subject'] ?? '');
            case 'feedback_submitted':
                return sprintf(__('Feedback submitted (rating: %s)', 'vmpfence-security'), $data['rating'] ?? '');
            case 'xmlrpc_call':
                return sprintf(__('XML-RPC call: %s', 'vmpfence-security'), $data['method'] ?? '');
            case 'rest_api_access':
                return sprintf(__('REST API access: %s', 'vmpfence-security'), $data['route'] ?? '');
            case 'wp_die_called':
                return sprintf(__('wp_die() triggered: %s', 'vmpfence-security'), $data['message'] ?? '');
            case 'scheduled_scan_started':
                return __('Scheduled scan started', 'vmpfence-security');

            // --- Multisite events (Observer_Multisite) ---
            case 'multisite_site_created':
                return sprintf(__('Site created: %s', 'vmpfence-security'), $data['domain'] ?? '');
            case 'multisite_site_deleted':
                return sprintf(__('Site deleted: #%d', 'vmpfence-security'), $data['blog_id'] ?? 0);
            case 'multisite_super_admin_granted':
                return sprintf(__('Super admin granted to: %s', 'vmpfence-security'), $data['username'] ?? '');
            case 'multisite_super_admin_revoked':
                return sprintf(__('Super admin revoked from: %s', 'vmpfence-security'), $data['username'] ?? '');

            // Rate limiting — human-readable messages
            case 'vmpfence_global_rate_limit_changed':
            case 'vmpfence_crawler_rate_limit_changed':
            case 'vmpfence_crawler_404_limit_changed':
            case 'vmpfence_human_rate_limit_changed':
            case 'vmpfence_human_404_limit_changed':
                $labels = array(
                    'vmpfence_global_rate_limit_changed'  => 'Anyone\'s requests',
                    'vmpfence_crawler_rate_limit_changed'  => 'Crawler page views',
                    'vmpfence_crawler_404_limit_changed'   => 'Crawler 404s',
                    'vmpfence_human_rate_limit_changed'    => 'Human page views',
                    'vmpfence_human_404_limit_changed'     => 'Human 404s',
                );
                $label = $labels[$event_type] ?? 'Rate limit';
                $val = $data['new_value'] ?? '';
                $display = strtolower((string)$val) === 'unlimited' ? 'Unlimited' : $val . '/min';
                return sprintf(__('%s limit changed to: %s', 'vmpfence-security'), $label, $display);

            case 'vmpfence_global_rate_action_changed':
            case 'vmpfence_crawler_rate_action_changed':
            case 'vmpfence_crawler_404_action_changed':
            case 'vmpfence_human_rate_action_changed':
            case 'vmpfence_human_404_action_changed':
                $labels = array(
                    'vmpfence_global_rate_action_changed'  => 'Anyone exceeds limit',
                    'vmpfence_crawler_rate_action_changed'  => 'Crawler exceeds limit',
                    'vmpfence_crawler_404_action_changed'   => 'Crawler 404 exceeds limit',
                    'vmpfence_human_rate_action_changed'    => 'Human exceeds limit',
                    'vmpfence_human_404_action_changed'     => 'Human 404 exceeds limit',
                );
                $label = $labels[$event_type] ?? 'Rate action';
                $val = ucfirst((string)($data['new_value'] ?? ''));
                return sprintf(__('%s action: %s', 'vmpfence-security'), $label, $val);

            case 'vmpfence_rate_block_duration_changed':
                $secs = intval($data['new_value'] ?? 0);
                if ($secs >= 86400) {
                    $display = round($secs / 86400) . ' day(s)';
                } elseif ($secs >= 3600) {
                    $display = round($secs / 3600) . ' hour(s)';
                } elseif ($secs >= 60) {
                    $display = round($secs / 60) . ' minute(s)';
                } else {
                    $display = $secs . ' seconds';
                }
                return sprintf(__('Rate limit block duration changed to: %s', 'vmpfence-security'), $display);

            case 'vmpfence_throttle_behavior_changed':
                $val = $data['new_value'] ?? '';
                $display = ($val === 'show_503') ? 'Show 503 page' : 'Slow down responses';
                return sprintf(__('Throttle behavior changed to: %s', 'vmpfence-security'), $display);

            case 'vmpfence_throttle_delay_changed':
                return sprintf(__('Throttle delay changed to: %s seconds', 'vmpfence-security'), $data['new_value'] ?? '');

            case 'vmpfence_google_crawler_treatment_changed':
                $treatments = array(
                    'verified_google'    => 'Verified Google crawlers',
                    'no_verification'    => 'No verification',
                    'treat_as_crawler'   => 'Treat as regular crawler',
                );
                $val = $data['new_value'] ?? '';
                $display = $treatments[$val] ?? ucwords(str_replace('_', ' ', $val));
                return sprintf(__('Google crawler treatment changed to: %s', 'vmpfence-security'), $display);

            case 'vmpfence_delay_ip_blocking_toggled':
                $state = !empty($data['new_value']) ? __('Enabled', 'vmpfence-security') : __('Disabled', 'vmpfence-security');
                return sprintf(__('Delay IP blocking: %s', 'vmpfence-security'), $state);

            // WAF allowlist entry — created / deleted / toggled
            case 'vmpfence_waf_allow_entry_created':
                return __('WAF Allowlist Entry Created', 'vmpfence-security');

            case 'vmpfence_waf_allow_entry_deleted':
                return __('WAF Allowlist Entry Deleted', 'vmpfence-security');

            case 'vmpfence_waf_allow_entry_toggled':
                $state = !empty($data['enabled']) ? __('Enabled', 'vmpfence-security') : __('Disabled', 'vmpfence-security');
                return sprintf(__('WAF Allowlist Entry %s', 'vmpfence-security'), $state);

            // WAF rule toggled — individual rule enable/disable
            case 'vmpfence_waf_rule_toggled':
                $rule_name = $data['rule_name'] ?? ('Rule #' . ($data['rule_id'] ?? '?'));
                $state = !empty($data['enabled']) ? __('Enabled', 'vmpfence-security') : __('Disabled', 'vmpfence-security');
                return sprintf(__('WAF rule %s: %s', 'vmpfence-security'), $state, $rule_name);

            // WAF category toggled — all rules in a category
            case 'vmpfence_waf_category_toggled':
                $category = $data['category'] ?? __('Unknown', 'vmpfence-security');
                $category = strtoupper(str_replace('_', ' ', $category));
                $state = !empty($data['enabled']) ? __('Enabled', 'vmpfence-security') : __('Disabled', 'vmpfence-security');
                return sprintf(__('WAF category %s: %s', 'vmpfence-security'), $state, $category);

            // Allowlisted services — human-readable message
            case 'vmpfence_allowlisted_services_updated':
                $service_labels = array(
                    'sucuri' => 'Sucuri', 'facebook' => 'Facebook', 'uptime' => 'Uptime Robot',
                    'statuscake' => 'StatusCake', 'managewp' => 'ManageWP',
                    'seznam' => 'Seznam', 'google' => 'Google',
                );
                $new_raw = $data['new_value'] ?? '{}';
                $new_services = is_array($new_raw) ? $new_raw : (json_decode($new_raw, true) ?: array());
                $old_raw = $data['old_value'] ?? '{}';
                $old_services = is_array($old_raw) ? $old_raw : (json_decode($old_raw, true) ?: array());
                $enabled = array();
                $disabled = array();
                foreach ($service_labels as $key => $name) {
                    $was_on = !empty($old_services[$key]);
                    $is_on  = !empty($new_services[$key]);
                    if ($is_on && !$was_on) { $enabled[] = $name; }
                    if (!$is_on && $was_on) { $disabled[] = $name; }
                }
                $parts = array();
                if (!empty($enabled))  { $parts[] = 'Enabled: ' . implode(', ', $enabled); }
                if (!empty($disabled)) { $parts[] = 'Disabled: ' . implode(', ', $disabled); }
                if (!empty($parts)) {
                    return implode(' | ', $parts);
                }
                // No diff detectable — list all currently enabled
                $active = array();
                foreach ($service_labels as $key => $name) {
                    if (!empty($new_services[$key])) { $active[] = $name; }
                }
                return !empty($active)
                    ? __('Active services: ', 'vmpfence-security') . implode(', ', $active)
                    : __('All services disabled', 'vmpfence-security');

            // Custom scan type — individual option changes
            case 'vmpfence_scan_option_changed':
                $label = isset($data['label']) ? $data['label'] : ucwords(str_replace('_', ' ', $data['key'] ?? ''));
                $new_val = $data['new_value'] ?? '';
                // Boolean-style toggles (0/1)
                if ($new_val === '1' || $new_val === 1 || $new_val === true) {
                    return sprintf(__('%s Enabled', 'vmpfence-security'), $label);
                }
                if ($new_val === '0' || $new_val === 0 || $new_val === false || $new_val === '') {
                    return sprintf(__('%s Disabled', 'vmpfence-security'), $label);
                }
                return sprintf(__('%s changed to: %s', 'vmpfence-security'), $label, $new_val);

            default:
                // Smart fallback for vmpfence_* config events from observer
                if (strpos($event_type, 'vmpfence_') === 0) {
                    // Strip prefix and humanize: vmpfence_strong_passwords_toggled → Strong Passwords
                    $label = str_replace('vmpfence_', '', $event_type);
                    $label = str_replace(array('_toggled', '_changed', '_updated'), '', $label);
                    $label = ucwords(str_replace('_', ' ', $label));

                    // Toggle events (ends with _toggled)
                    if (substr($event_type, -8) === '_toggled') {
                        return sprintf(__('%s %s', 'vmpfence-security'), $label,
                            !empty($data['new_value']) ? 'Enabled' : 'Disabled');
                    }
                    // Changed/updated events
                    if (isset($data['new_value'])) {
                        $display_val = is_array($data['new_value']) ? wp_json_encode($data['new_value']) : $data['new_value'];
                        // Empty or whitespace-only value → show "(cleared)"
                        if ((string)$display_val === '' || trim((string)$display_val) === '') {
                            return sprintf(__('%s cleared', 'vmpfence-security'), $label);
                        }
                        if (strlen((string)$display_val) > 80) {
                            $display_val = substr((string)$display_val, 0, 77) . '...';
                        }
                        // Capitalize simple string values (e.g. "standard" → "Standard")
                        if (is_string($display_val) && preg_match('/^[a-z_]+$/', $display_val)) {
                            $display_val = ucwords(str_replace('_', ' ', $display_val));
                        }
                        return sprintf(__('%s changed to: %s', 'vmpfence-security'), $label, $display_val);
                    }
                    return sprintf(__('%s updated', 'vmpfence-security'), $label);
                }

                /* translators: %s: event type */
                return $data['message'] ?? sprintf(__('Event: %s', 'vmpfence-security'), $event_type);
        }
    }

    /**
     * Send audit log entry to central management
     *
     * @since 1.0.0
     * @param array $event_data Event data
     * @return void
     */
    private static function send_to_central($event_data) {
        // This would send the audit log entry to a central management server
        // Implementation depends on the central management API
        
        $api_key = get_option('vmpfence_central_api_key', '');
        if (empty($api_key)) {
            return;
        }

        // Queue for background sending to avoid blocking the request
        wp_schedule_single_event(time() + 5, 'vmpfence_send_audit_to_central', array($event_data));
    }

    /**
     * Get audit log viewer URL
     *
     * @since 1.0.0
     * @param array $args URL arguments
     * @return string
     */
    public static function get_viewer_url($args = array()) {
        $base_url = admin_url('admin.php?page=vmpfence-tools&tab=audit-log');
        
        if (!empty($args)) {
            $base_url .= '&' . http_build_query($args);
        }

        return $base_url;
    }

    /**
     * Check if current user can view audit logs
     *
     * @since 1.0.0
     * @return bool
     */
    public static function can_view_logs() {
        return current_user_can('vmpfence_admin') || current_user_can('vmpfence_view');
    }

    /**
     * Get event type display name
     *
     * @since 1.0.0
     * @since 2.2.5 Added more event types and translations
     * @param string $event_type Event type
     * @return string
     */
    public static function get_event_type_name($event_type) {
        $names = array(
            // Authentication / User events
            VMPFence_Constants::EVENT_LOGIN_SUCCESS  => __('Login Success', 'vmpfence-security'),
            VMPFence_Constants::EVENT_LOGIN_FAILURE  => __('Login Failure', 'vmpfence-security'),
            VMPFence_Constants::EVENT_LOGIN_BLOCKED  => __('Login Blocked', 'vmpfence-security'),
            'user_logout'                => __('User Logout', 'vmpfence-security'),
            'user_registered'            => __('User Registered', 'vmpfence-security'),
            'user_deleted'               => __('User Deleted', 'vmpfence-security'),
            'user_role_changed'          => __('User Role Changed', 'vmpfence-security'),
            'user_profile_updated'       => __('Profile Updated', 'vmpfence-security'),
            'user_capabilities_changed'  => __('Capabilities Changed', 'vmpfence-security'),
            'user_level_changed'         => __('User Level Changed', 'vmpfence-security'),
            'user_marked_spam'           => __('User Marked Spam', 'vmpfence-security'),
            'user_unmarked_spam'         => __('User Unmarked Spam', 'vmpfence-security'),
            'password_reset'             => __('Password Reset', 'vmpfence-security'),
            'password_reset_requested'   => __('Password Reset Requested', 'vmpfence-security'),
            'auth_cookie_set'            => __('Auth Cookie Set', 'vmpfence-security'),
            'app_password_created'       => __('App Password Created', 'vmpfence-security'),
            'app_password_deleted'       => __('App Password Deleted', 'vmpfence-security'),
            'app_password_used'          => __('App Password Used', 'vmpfence-security'),

            // Content events
            'post_saved'             => __('Post Saved', 'vmpfence-security'),
            'post_deleted'           => __('Post Deleted', 'vmpfence-security'),
            'post_published'         => __('Post Published', 'vmpfence-security'),
            'post_draft_created'     => __('Draft Created', 'vmpfence-security'),
            'post_updated'           => __('Post Updated', 'vmpfence-security'),
            'post_trashed'           => __('Post Trashed', 'vmpfence-security'),
            'post_restored'          => __('Post Restored', 'vmpfence-security'),
            'comment_posted'         => __('Comment Posted', 'vmpfence-security'),
            'comment_approved'       => __('Comment Approved', 'vmpfence-security'),
            'comment_spam'           => __('Comment Spam', 'vmpfence-security'),
            'comment_trashed'        => __('Comment Trashed', 'vmpfence-security'),
            'comment_deleted'        => __('Comment Deleted', 'vmpfence-security'),
            'media_uploaded'         => __('Media Uploaded', 'vmpfence-security'),
            'media_edited'           => __('Media Edited', 'vmpfence-security'),
            'media_deleted'          => __('Media Deleted', 'vmpfence-security'),
            'file_uploaded'          => __('File Uploaded', 'vmpfence-security'),
            'term_created'           => __('Term Created', 'vmpfence-security'),
            'term_edited'            => __('Term Edited', 'vmpfence-security'),
            'term_deleted'           => __('Term Deleted', 'vmpfence-security'),

            // Site / lifecycle events
            'plugin_activated'       => __('Plugin Activated', 'vmpfence-security'),
            'plugin_deactivated'     => __('Plugin Deactivated', 'vmpfence-security'),
            'plugin_installed'       => __('Plugin Installed', 'vmpfence-security'),
            'plugin_updated'         => __('Plugin Updated', 'vmpfence-security'),
            'plugin_deleted'         => __('Plugin Deleted', 'vmpfence-security'),
            'theme_changed'          => __('Theme Changed', 'vmpfence-security'),
            'theme_installed'        => __('Theme Installed', 'vmpfence-security'),
            'theme_updated'          => __('Theme Updated', 'vmpfence-security'),
            'theme_deleted'          => __('Theme Deleted', 'vmpfence-security'),
            'core_updated'           => __('Core Updated', 'vmpfence-security'),
            'auto_updates_completed' => __('Auto Updates Completed', 'vmpfence-security'),
            'menu_created'           => __('Menu Created', 'vmpfence-security'),
            'menu_updated'           => __('Menu Updated', 'vmpfence-security'),
            'menu_deleted'           => __('Menu Deleted', 'vmpfence-security'),
            'customizer_saved'       => __('Customizer Saved', 'vmpfence-security'),
            'file_editor_used'       => __('File Editor Used', 'vmpfence-security'),
            'role_capabilities_changed' => __('Role Capabilities Changed', 'vmpfence-security'),
            'recovery_key_generated' => __('Recovery Key Generated', 'vmpfence-security'),
            'mail_sent'              => __('Email Sent', 'vmpfence-security'),
            'mail_failed'            => __('Email Failed', 'vmpfence-security'),

            // Site option changes
            'option_siteurl_changed'          => __('Site URL Changed', 'vmpfence-security'),
            'option_home_changed'             => __('Home URL Changed', 'vmpfence-security'),
            'option_admin_email_changed'      => __('Admin Email Changed', 'vmpfence-security'),
            'option_default_role_changed'     => __('Default Role Changed', 'vmpfence-security'),
            'option_registration_changed'     => __('Registration Setting Changed', 'vmpfence-security'),
            'option_blogname_changed'         => __('Site Title Changed', 'vmpfence-security'),
            'option_description_changed'      => __('Tagline Changed', 'vmpfence-security'),
            'option_permalink_changed'        => __('Permalink Changed', 'vmpfence-security'),
            'option_search_visibility_changed' => __('Search Visibility Changed', 'vmpfence-security'),
            'option_timezone_changed'         => __('Timezone Changed', 'vmpfence-security'),
            'option_date_format_changed'      => __('Date Format Changed', 'vmpfence-security'),
            'option_time_format_changed'      => __('Time Format Changed', 'vmpfence-security'),
            'option_start_of_week_changed'    => __('Start of Week Changed', 'vmpfence-security'),
            'option_language_changed'         => __('Language Changed', 'vmpfence-security'),
            'option_comments_changed'         => __('Comments Setting Changed', 'vmpfence-security'),
            'option_uploads_changed'          => __('Uploads Setting Changed', 'vmpfence-security'),

            // Security / Scanner events
            VMPFence_Constants::EVENT_SCAN_STARTED   => __('Scan Started', 'vmpfence-security'),
            VMPFence_Constants::EVENT_SCAN_COMPLETED => __('Scan Completed', 'vmpfence-security'),
            VMPFence_Constants::EVENT_THREAT_DETECTED => __('Threat Detected', 'vmpfence-security'),
            VMPFence_Constants::EVENT_IP_BLOCKED     => __('Manual Block (IP)', 'vmpfence-security'),
            VMPFence_Constants::EVENT_WAF_BLOCKED    => __('WAF Block', 'vmpfence-security'),
            'brute_force_lockout'    => __('Brute Force Lockout', 'vmpfence-security'),
            'scheduled_scan_started' => __('Scheduled Scan Started', 'vmpfence-security'),
            'xmlrpc_call'            => __('XML-RPC Call', 'vmpfence-security'),
            'rest_api_access'        => __('REST API Access', 'vmpfence-security'),
            'wp_die_called'          => __('WP Die Called', 'vmpfence-security'),

            // VMPFence config events
            VMPFence_Constants::EVENT_CONFIG_CHANGED      => __('Config Changed', 'vmpfence-security'),
            'config_imported'                => __('Config Imported', 'vmpfence-security'),
            'config_exported'                => __('Config Exported', 'vmpfence-security'),
            'config_reset'                   => __('Config Reset', 'vmpfence-security'),
            'config_deleted'                 => __('Config Deleted', 'vmpfence-security'),
            'vmpfence_waf_mode_changed'      => __('WAF Mode Changed', 'vmpfence-security'),
            'vmpfence_waf_protection_level_changed' => __('WAF Protection Level Changed', 'vmpfence-security'),
            'vmpfence_waf_blocklist_toggled'  => __('WAF Blocklist Toggled', 'vmpfence-security'),
            'vmpfence_waf_auto_update_toggled' => __('WAF Auto-Update Toggled', 'vmpfence-security'),
            'vmpfence_waf_rule_created'      => __('WAF Rule Created', 'vmpfence-security'),
            'vmpfence_waf_rule_deleted'      => __('WAF Rule Deleted', 'vmpfence-security'),
            'vmpfence_waf_rule_toggled'      => __('WAF Rule Toggled', 'vmpfence-security'),
            'vmpfence_waf_category_toggled'  => __('WAF Category Toggled', 'vmpfence-security'),
            'vmpfence_waf_allow_entry_created' => __('WAF Allowlist Entry', 'vmpfence-security'),
            'vmpfence_waf_allow_entry_deleted' => __('WAF Allowlist Entry', 'vmpfence-security'),
            'vmpfence_waf_allow_entry_toggled' => __('WAF Allowlist Entry', 'vmpfence-security'),
            'vmpfence_brute_force_toggled'   => __('Brute Force Toggled', 'vmpfence-security'),
            'vmpfence_login_threshold_changed' => __('Login Threshold Changed', 'vmpfence-security'),
            'vmpfence_forgot_password_threshold_changed' => __('Forgot Password Threshold Changed', 'vmpfence-security'),
            'vmpfence_login_security_period_changed' => __('Login Security Period Changed', 'vmpfence-security'),
            'vmpfence_lockout_duration_changed' => __('Lockout Duration Changed', 'vmpfence-security'),
            'vmpfence_block_duration_changed' => __('Block Duration Changed', 'vmpfence-security'),
            'vmpfence_custom_block_text_changed' => __('Custom Block Text Changed', 'vmpfence-security'),
            'vmpfence_lock_invalid_usernames_toggled' => __('Lock Invalid Usernames Toggled', 'vmpfence-security'),
            'vmpfence_banned_usernames_updated' => __('Banned Usernames Updated', 'vmpfence-security'),
            'vmpfence_breached_passwords_toggled' => __('Breached Passwords Check Toggled', 'vmpfence-security'),
            'vmpfence_strong_passwords_toggled' => __('Strong Passwords Toggled', 'vmpfence-security'),
            'vmpfence_mask_login_errors_toggled' => __('Mask Login Errors Toggled', 'vmpfence-security'),
            'vmpfence_prevent_admin_username_toggled' => __('Prevent Admin Username Toggled', 'vmpfence-security'),
            'vmpfence_block_author_scan_toggled' => __('Block Author Scan Toggled', 'vmpfence-security'),
            'vmpfence_app_passwords_toggled' => __('App Passwords Toggled', 'vmpfence-security'),
            'vmpfence_block_bad_post_toggled' => __('Block Bad POST Toggled', 'vmpfence-security'),
            'vmpfence_check_password_strength_toggled' => __('Password Strength Check Toggled', 'vmpfence-security'),
            'vmpfence_security_network_toggled' => __('Security Network Toggled', 'vmpfence-security'),
            'vmpfence_rate_limiting_toggled'  => __('Rate Limiting Toggled', 'vmpfence-security'),
            'vmpfence_google_crawler_treatment_changed' => __('Google Crawler Treatment Changed', 'vmpfence-security'),
            'vmpfence_global_rate_limit_changed' => __('Global Rate Limit Changed', 'vmpfence-security'),
            'vmpfence_global_rate_action_changed' => __('Global Rate Action Changed', 'vmpfence-security'),
            'vmpfence_crawler_rate_limit_changed' => __('Crawler Rate Limit Changed', 'vmpfence-security'),
            'vmpfence_crawler_rate_action_changed' => __('Crawler Rate Action Changed', 'vmpfence-security'),
            'vmpfence_crawler_404_limit_changed' => __('Crawler 404 Limit Changed', 'vmpfence-security'),
            'vmpfence_crawler_404_action_changed' => __('Crawler 404 Action Changed', 'vmpfence-security'),
            'vmpfence_human_rate_limit_changed' => __('Human Rate Limit Changed', 'vmpfence-security'),
            'vmpfence_human_rate_action_changed' => __('Human Rate Action Changed', 'vmpfence-security'),
            'vmpfence_human_404_limit_changed' => __('Human 404 Limit Changed', 'vmpfence-security'),
            'vmpfence_human_404_action_changed' => __('Human 404 Action Changed', 'vmpfence-security'),
            'vmpfence_rate_block_duration_changed' => __('Rate Block Duration Changed', 'vmpfence-security'),
            'vmpfence_throttle_behavior_changed' => __('Throttle Behavior Changed', 'vmpfence-security'),
            'vmpfence_throttle_delay_changed' => __('Throttle Delay Changed', 'vmpfence-security'),
            'vmpfence_allowlisted_404_urls_updated' => __('Allowlisted 404 URLs Updated', 'vmpfence-security'),
            'vmpfence_ip_source_changed'     => __('IP Detection Changed', 'vmpfence-security'),
            'vmpfence_trusted_proxies_changed' => __('Trusted Proxies Changed', 'vmpfence-security'),
            'vmpfence_trusted_proxy_preset_changed' => __('Trusted Proxy Preset Changed', 'vmpfence-security'),
            'vmpfence_allowed_ips_updated'   => __('Allowed IPs Updated', 'vmpfence-security'),
            'vmpfence_banned_urls_updated'   => __('Banned URLs Updated', 'vmpfence-security'),
            'vmpfence_allowlisted_services_updated' => __('Allowlisted Services Updated', 'vmpfence-security'),
            'vmpfence_delay_ip_blocking_toggled' => __('Delay IP Blocking Toggled', 'vmpfence-security'),
            'vmpfence_ignored_ips_waf_updated' => __('Ignored IPs for WAF Alerts Updated', 'vmpfence-security'),
            'vmpfence_country_block_action_changed' => __('Country Block Action Changed', 'vmpfence-security'),
            'vmpfence_country_block_logged_in_changed' => __('Country Block Logged-in Changed', 'vmpfence-security'),
            'vmpfence_country_blocked'       => __('Manual Block (Country)', 'vmpfence-security'),
            'vmpfence_country_unblocked'     => __('Manual Block Deleted (Country)', 'vmpfence-security'),
            'vmpfence_scan_type_changed'     => __('Scan Type Changed', 'vmpfence-security'),
            'vmpfence_scan_option_changed'   => __('Scan Option Changed', 'vmpfence-security'),
            'vmpfence_scan_schedule_toggled' => __('Scan Schedule Toggled', 'vmpfence-security'),
            'vmpfence_scan_schedule_changed' => __('Scan Schedule Changed', 'vmpfence-security'),
            'vmpfence_scan_low_resource_toggled' => __('Low Resource Scan Toggled', 'vmpfence-security'),
            'vmpfence_2fa_required_roles_changed' => __('2FA Required Roles Changed', 'vmpfence-security'),
            'vmpfence_2fa_grace_period_changed' => __('2FA Grace Period Changed', 'vmpfence-security'),
            'vmpfence_2fa_remember_device_toggled' => __('2FA Remember Device Toggled', 'vmpfence-security'),
            'vmpfence_xmlrpc_2fa_toggled'    => __('XML-RPC 2FA Toggled', 'vmpfence-security'),
            'vmpfence_xmlrpc_toggled'        => __('XML-RPC Auth Toggled', 'vmpfence-security'),
            'vmpfence_woocommerce_2fa_toggled' => __('WooCommerce 2FA Toggled', 'vmpfence-security'),
            'vmpfence_2fa_shortcode_toggled' => __('2FA Shortcode Toggled', 'vmpfence-security'),
            'vmpfence_captcha_toggled'       => __('CAPTCHA Toggled', 'vmpfence-security'),
            'vmpfence_captcha_threshold_changed' => __('CAPTCHA Threshold Changed', 'vmpfence-security'),
            'vmpfence_2fa_bypass_ips_changed' => __('2FA Bypass IPs Changed', 'vmpfence-security'),
            'vmpfence_api_key_changed'       => __('API Key Changed', 'vmpfence-security'),
            'vmpfence_custom_pattern_added'  => __('Manual Block (Custom Pattern)', 'vmpfence-security'),
            'vmpfence_custom_pattern_deleted' => __('Manual Block Deleted (Pattern)', 'vmpfence-security'),
            'vmpfence_custom_pattern_toggled' => __('Custom Pattern Toggled', 'vmpfence-security'),
            'vmpfence_ip_unblocked'          => __('Manual Block Deleted (IP)', 'vmpfence-security'),
            'ip_deleted'                     => __('IP Deleted', 'vmpfence-security'),
            'vmpfence_traffic_logging_mode_changed' => __('Traffic Logging Mode Changed', 'vmpfence-security'),
            'vmpfence_traffic_ignore_setting_changed' => __('Traffic Ignore Setting Changed', 'vmpfence-security'),
            'vmpfence_traffic_limit_changed' => __('Traffic Limit Changed', 'vmpfence-security'),
            'vmpfence_country_block_redirect_changed' => __('Country Block Redirect Changed', 'vmpfence-security'),
            'vmpfence_country_bypass_changed' => __('Country Bypass Changed', 'vmpfence-security'),
            'vmpfence_deactivation_choice_changed' => __('Deactivation Choice Changed', 'vmpfence-security'),
            'vmpfence_data_preservation_changed' => __('Data Preservation Changed', 'vmpfence-security'),
            'vmpfence_api_key_option_changed' => __('API Key Changed', 'vmpfence-security'),
            'vmpfence_license_email_changed' => __('License Email Changed', 'vmpfence-security'),
            'vmpfence_license_key_option_changed' => __('License Key Changed', 'vmpfence-security'),
            'vmpfence_license_type_changed'  => __('License Type Changed', 'vmpfence-security'),
            'vmpfence_central_api_key_changed' => __('Central API Key Changed', 'vmpfence-security'),
            'vmpfence_email_alerts_toggled'  => __('Email Alerts Toggled', 'vmpfence-security'),
            'vmpfence_scan_perf_options_changed' => __('Scan Performance Options Changed', 'vmpfence-security'),
            'vmpfence_yara_whitelist_changed' => __('YARA Whitelist Changed', 'vmpfence-security'),
            'vmpfence_yara_threats_changed'  => __('YARA Threats Changed', 'vmpfence-security'),
            'vmpfence_scan_issues_ignored'   => __('Scan Issues Ignored', 'vmpfence-security'),
            'vmpfence_scan_issues_fixed'     => __('Scan Issues Fixed', 'vmpfence-security'),
            'vmpfence_config_changed'        => __('VMP Security Config Changed', 'vmpfence-security'),
            'vmpfence_audit_log_mode_changed' => __('Audit Log Mode Changed', 'vmpfence-security'),
            'vmpfence_license_changed'       => __('License Changed', 'vmpfence-security'),
            'brute_force_detected'           => __('Brute Force Detected', 'vmpfence-security'),
            'backup_created'                 => __('Backup Created', 'vmpfence-security'),
            'backup_restored'                => __('Backup Restored', 'vmpfence-security'),
            'backup_deleted'                 => __('Backup Deleted', 'vmpfence-security'),
            'database_updated'               => __('Database Updated', 'vmpfence-security'),
            'database_cleanup'               => __('Database Cleanup', 'vmpfence-security'),
            'support_ticket_submitted'       => __('Support Ticket', 'vmpfence-security'),
            'feedback_submitted'             => __('Feedback Submitted', 'vmpfence-security'),

            // Direct security events
            'blocked_ip_access_attempt'      => __('Blocked IP Access Attempt', 'vmpfence-security'),
            'brute_force_invalid_username'   => __('Invalid Username Login', 'vmpfence-security'),
            'brute_force_blocked_username'   => __('Blocked Username Login', 'vmpfence-security'),
            'brute_force_forgot_password'    => __('Forgot Password Abuse', 'vmpfence-security'),
            'weak_password_detected'         => __('Weak Password Detected', 'vmpfence-security'),
            'firewall_block'                 => __('Firewall Block', 'vmpfence-security'),
            'xss_detected'                   => __('XSS Detected', 'vmpfence-security'),
            'sqli_detected'                  => __('SQL Injection Detected', 'vmpfence-security'),
            'sql_injection_attempt'          => __('SQL Injection Attempt', 'vmpfence-security'),
            'suspicious_user_agent'          => __('Suspicious User Agent', 'vmpfence-security'),
            'directory_traversal_attempt'    => __('Directory Traversal Attempt', 'vmpfence-security'),
            'file_inclusion_attempt'         => __('File Inclusion Attempt', 'vmpfence-security'),
            'admin_page_denied'              => __('Admin Page Denied', 'vmpfence-security'),
            'site_data_exported'             => __('Site Data Exported', 'vmpfence-security'),

            // Multisite events
            'multisite_site_created'          => __('Site Created', 'vmpfence-security'),
            'multisite_site_deleted'          => __('Site Deleted', 'vmpfence-security'),
            'multisite_site_archived'         => __('Site Archived', 'vmpfence-security'),
            'multisite_site_unarchived'       => __('Site Unarchived', 'vmpfence-security'),
            'multisite_site_activated'        => __('Site Activated', 'vmpfence-security'),
            'multisite_site_deactivated'      => __('Site Deactivated', 'vmpfence-security'),
            'multisite_site_spam'             => __('Site Marked Spam', 'vmpfence-security'),
            'multisite_site_not_spam'         => __('Site Unmarked Spam', 'vmpfence-security'),
            'multisite_site_mature'           => __('Site Marked Mature', 'vmpfence-security'),
            'multisite_site_unmature'         => __('Site Unmarked Mature', 'vmpfence-security'),
            'multisite_super_admin_granted'   => __('Super Admin Granted', 'vmpfence-security'),
            'multisite_super_admin_revoked'   => __('Super Admin Revoked', 'vmpfence-security'),
            'multisite_network_option_changed' => __('Network Option Changed', 'vmpfence-security'),
            'multisite_user_added_to_site'    => __('User Added to Site', 'vmpfence-security'),
            'multisite_user_removed_from_site' => __('User Removed from Site', 'vmpfence-security'),
            'multisite_network_plugin_activated' => __('Network Plugin Activated', 'vmpfence-security'),
            'multisite_network_plugin_deactivated' => __('Network Plugin Deactivated', 'vmpfence-security'),
            'multisite_network_theme_enabled' => __('Network Theme Enabled', 'vmpfence-security'),
            'multisite_network_theme_disabled' => __('Network Theme Disabled', 'vmpfence-security'),
            'multisite_site_option_changed'   => __('Site Option Changed', 'vmpfence-security'),
            'multisite_blog_switched'         => __('Blog Switched', 'vmpfence-security'),
            'multisite_blog_restored'         => __('Blog Restored', 'vmpfence-security'),
        );

        return $names[$event_type] ?? ucwords(str_replace('_', ' ', $event_type));
    }
}
