<?php
/**
 * Comprehensive Activity Logging for Guard Dog.
 *
 * Tracks security events, WordPress activities, and user actions.
 *
 * @package GuardDog
 * @since 1.6.0
 */

if (!defined('ABSPATH')) exit; // Exit if accessed directly

class Guard_Dog_Activity_Log {

    /**
     * Activity log event types and their default enabled status
     * @var array
     */
    private static $event_types = [
        // Security Events
        'login_successful' => ['name' => 'Login Successful', 'category' => 'security', 'default' => true],
        'login_failed' => ['name' => 'Login Failed', 'category' => 'security', 'default' => true],
        'login_blocked' => ['name' => 'Login Blocked', 'category' => 'security', 'default' => true],
        'login_attempt_during_lockout' => ['name' => 'Login Attempt During Lockout', 'category' => 'security', 'default' => true],
        'login_lockout_initiated' => ['name' => 'Login Lockout Initiated', 'category' => 'security', 'default' => true],
        'login_access_denied' => ['name' => 'Login Access Denied', 'category' => 'security', 'default' => true],
        'site_access_denied' => ['name' => 'Site Access Denied', 'category' => 'security', 'default' => true],
        'ip_blocked' => ['name' => 'IP Address Blocked', 'category' => 'security', 'default' => true],
        'not_in_whitelist' => ['name' => 'Access Denied - Not in Whitelist', 'category' => 'security', 'default' => true],
        'user_blacklist' => ['name' => 'Access Denied - Username Blacklisted', 'category' => 'security', 'default' => true],
        'ip_blacklist' => ['name' => 'Access Denied - IP Blacklisted', 'category' => 'security', 'default' => true],
        'ip_added_to_blacklist' => ['name' => 'IP Added to Blacklist', 'category' => 'security', 'default' => true],
        'ip_removed_from_blacklist' => ['name' => 'IP Removed from Blacklist', 'category' => 'security', 'default' => true],
        'country_added_to_blacklist' => ['name' => 'Country Added to Blacklist', 'category' => 'security', 'default' => true],
        'country_removed_from_blacklist' => ['name' => 'Country Removed from Blacklist', 'category' => 'security', 'default' => true],
        'temp_access_created' => ['name' => 'Temporary Access Created', 'category' => 'security', 'default' => true],
        'temp_access_used' => ['name' => 'Temporary Access Used', 'category' => 'security', 'default' => true],
        'captcha_failed' => ['name' => 'CAPTCHA Failed', 'category' => 'security', 'default' => true],
        'captcha_verification' => ['name' => 'CAPTCHA Verification', 'category' => 'security', 'default' => true],
        '2fa_enabled' => ['name' => '2FA Enabled', 'category' => 'security', 'default' => true],
        '2fa_disabled' => ['name' => '2FA Disabled', 'category' => 'security', 'default' => true],
        '2fa_successful' => ['name' => '2FA Successful', 'category' => 'security', 'default' => true],
        '2fa_failed' => ['name' => '2FA Authentication Failed', 'category' => 'security', 'default' => true],
        'login_warning_2fa_required' => ['name' => 'Login Warning 2FA Required', 'category' => 'security', 'default' => true],
        'user_2fa_setup_completed' => ['name' => '2FA Setup Completed', 'category' => 'security', 'default' => true],
        'email_2fa_enabled' => ['name' => 'Email 2FA Enabled', 'category' => 'security', 'default' => true],
        'email_2fa_disabled' => ['name' => 'Email 2FA Disabled', 'category' => 'security', 'default' => true],
        'email_2fa_code_sent' => ['name' => 'Email 2FA Code Sent', 'category' => 'security', 'default' => true],
        'email_2fa_verified' => ['name' => 'Email 2FA Verified', 'category' => 'security', 'default' => true],
        'email_2fa_failed' => ['name' => 'Email 2FA Failed', 'category' => 'security', 'default' => true],
        'password_reset' => ['name' => 'Password Reset', 'category' => 'security', 'default' => true],
        'email_verification_sent' => ['name' => 'Email Verification Sent', 'category' => 'security', 'default' => true],
        'email_verification_verified' => ['name' => 'Email Verification Verified', 'category' => 'security', 'default' => true],
        'email_verification_expired' => ['name' => 'Email Verification Expired', 'category' => 'security', 'default' => true],
        'email_verification_resend' => ['name' => 'Email Verification Resent', 'category' => 'security', 'default' => true],
        'email_verification_failed' => ['name' => 'Email Verification Failed', 'category' => 'security', 'default' => true],
        'email_verification_admin_verified' => ['name' => 'Email Verification Admin Verified', 'category' => 'security', 'default' => true],
        'password_policy_violation' => ['name' => 'Password Policy Violation', 'category' => 'security', 'default' => true],
        'password_policy_enforced' => ['name' => 'Password Policy Enforced', 'category' => 'security', 'default' => true],
        'password_reuse_blocked' => ['name' => 'Password Reuse Blocked', 'category' => 'security', 'default' => true],
        'common_password_blocked' => ['name' => 'Common Password Blocked', 'category' => 'security', 'default' => true],
        'password_expired' => ['name' => 'Password Expired', 'category' => 'security', 'default' => true],
        'password_expiration_reset' => ['name' => 'Password Expiration Reset', 'category' => 'security', 'default' => true],
        'password_expiration_warning_sent' => ['name' => 'Password Expiration Warning Sent', 'category' => 'security', 'default' => true],
        'password_expired_notice_sent' => ['name' => 'Password Expired Notice Sent', 'category' => 'security', 'default' => true],

        // Session Management Events
        'session_created' => ['name' => 'Session Created', 'category' => 'security', 'default' => true],
        'session_terminated' => ['name' => 'Session Terminated', 'category' => 'security', 'default' => true],
        'session_terminated_limit' => ['name' => 'Session Terminated (Limit Reached)', 'category' => 'security', 'default' => true],
        'session_expired' => ['name' => 'Session Expired', 'category' => 'security', 'default' => true],
        'session_ip_shift' => ['name' => 'Session IP Shift Detected', 'category' => 'security', 'default' => true],
        'session_geo_anomaly' => ['name' => 'Session Geo Anomaly Detected', 'category' => 'security', 'default' => true],

        // Passkey (WebAuthn) Events
        'passkey_registered' => ['name' => 'Passkey Registered', 'category' => 'security', 'default' => true],
        'passkey_deleted' => ['name' => 'Passkey Deleted', 'category' => 'security', 'default' => true],
        'passkey_login_success' => ['name' => 'Passkey Login Success', 'category' => 'security', 'default' => true],
        'passkey_login_failed' => ['name' => 'Passkey Login Failed', 'category' => 'security', 'default' => true],

        // IP Reputation Events
        'login_blocked_ip_reputation' => ['name' => 'Login Blocked - IP Reputation', 'category' => 'security', 'default' => true],
        'session_terminated_ip_reputation' => ['name' => 'Session Terminated - IP Reputation', 'category' => 'security', 'default' => true],

        // User Enumeration Events
        'enumeration_attempt' => ['name' => 'User Enumeration Attempt', 'category' => 'security', 'default' => true],
        'enumeration_auto_blocked' => ['name' => 'Enumeration Auto-Block', 'category' => 'security', 'default' => true],

        // Social Login Events
        'social_login_success' => ['name' => 'Social Login Success', 'category' => 'security', 'default' => true],
        'social_login_failed' => ['name' => 'Social Login Failed', 'category' => 'security', 'default' => true],
        'social_account_linked' => ['name' => 'Social Account Linked', 'category' => 'security', 'default' => true],
        'social_account_unlinked' => ['name' => 'Social Account Unlinked', 'category' => 'security', 'default' => true],
        'social_user_created' => ['name' => 'Social Login User Created', 'category' => 'security', 'default' => true],

        // User Management
        'user_created' => ['name' => 'User Created', 'category' => 'users', 'default' => true],
        'user_deleted' => ['name' => 'User Deleted', 'category' => 'users', 'default' => true],
        'user_updated' => ['name' => 'User Updated', 'category' => 'users', 'default' => false],
        'user_role_changed' => ['name' => 'User Role Changed', 'category' => 'users', 'default' => true],
        'profile_updated' => ['name' => 'Profile Updated', 'category' => 'users', 'default' => false],
        
        // Content Management
        'post_created' => ['name' => 'Post Created', 'category' => 'content', 'default' => true],
        'post_updated' => ['name' => 'Post Updated', 'category' => 'content', 'default' => true],
        'post_deleted' => ['name' => 'Post Deleted', 'category' => 'content', 'default' => true],
        'post_status_changed' => ['name' => 'Post Status Changed', 'category' => 'content', 'default' => true],
        'post_trashed' => ['name' => 'Post Trashed', 'category' => 'content', 'default' => true],
        'comment_created' => ['name' => 'Comment Created', 'category' => 'content', 'default' => true],
        'comment_approved' => ['name' => 'Comment Approved', 'category' => 'content', 'default' => true],
        'comment_spam' => ['name' => 'Comment Marked as Spam', 'category' => 'content', 'default' => true],
        'comment_deleted' => ['name' => 'Comment Deleted', 'category' => 'content', 'default' => true],
        
        // System Events
        'plugin_activated' => ['name' => 'Plugin Activated', 'category' => 'system', 'default' => true],
        'plugin_deactivated' => ['name' => 'Plugin Deactivated', 'category' => 'system', 'default' => true],
        'plugin_installed' => ['name' => 'Plugin Installed', 'category' => 'system', 'default' => true],
        'plugin_deleted' => ['name' => 'Plugin Deleted', 'category' => 'system', 'default' => true],
        'theme_switched' => ['name' => 'Theme Switched', 'category' => 'system', 'default' => true],
        'theme_installed' => ['name' => 'Theme Installed', 'category' => 'system', 'default' => true],
        'theme_deleted' => ['name' => 'Theme Deleted', 'category' => 'system', 'default' => true],
        'core_updated' => ['name' => 'WordPress Core Updated', 'category' => 'system', 'default' => true],
        'settings_updated' => ['name' => 'Settings Updated', 'category' => 'system', 'default' => false],
        'settings_action' => ['name' => 'Settings Action', 'category' => 'system', 'default' => false],
        'health_check' => ['name' => 'Health Check', 'category' => 'system', 'default' => false],
        'menu_created' => ['name' => 'Menu Created', 'category' => 'system', 'default' => false],
        'menu_updated' => ['name' => 'Menu Updated', 'category' => 'system', 'default' => false],
        'menu_deleted' => ['name' => 'Menu Deleted', 'category' => 'system', 'default' => false],
        'widget_added' => ['name' => 'Widget Added', 'category' => 'system', 'default' => false],
        'widget_updated' => ['name' => 'Widget Updated', 'category' => 'system', 'default' => false],
        'widget_deleted' => ['name' => 'Widget Deleted', 'category' => 'system', 'default' => false],

        // WooCommerce Events (only registered if WooCommerce is active)
        // Product Management
        'wc_product_created' => ['name' => 'Product Created', 'category' => 'woocommerce', 'default' => true],
        'wc_product_updated' => ['name' => 'Product Updated', 'category' => 'woocommerce', 'default' => false],
        'wc_product_deleted' => ['name' => 'Product Deleted', 'category' => 'woocommerce', 'default' => true],
        'wc_product_trashed' => ['name' => 'Product Trashed', 'category' => 'woocommerce', 'default' => true],
        'wc_product_restored' => ['name' => 'Product Restored', 'category' => 'woocommerce', 'default' => true],
        'wc_product_stock_changed' => ['name' => 'Product Stock Changed', 'category' => 'woocommerce', 'default' => true],

        // Order Management
        'wc_order_created' => ['name' => 'Order Created', 'category' => 'woocommerce', 'default' => true],
        'wc_order_status_changed' => ['name' => 'Order Status Changed', 'category' => 'woocommerce', 'default' => true],
        'wc_order_deleted' => ['name' => 'Order Deleted', 'category' => 'woocommerce', 'default' => true],
        'wc_order_refunded' => ['name' => 'Order Refunded', 'category' => 'woocommerce', 'default' => true],
        'wc_order_note_added' => ['name' => 'Order Note Added', 'category' => 'woocommerce', 'default' => false],

        // Coupon Management
        'wc_coupon_created' => ['name' => 'Coupon Created', 'category' => 'woocommerce', 'default' => true],
        'wc_coupon_updated' => ['name' => 'Coupon Updated', 'category' => 'woocommerce', 'default' => false],
        'wc_coupon_deleted' => ['name' => 'Coupon Deleted', 'category' => 'woocommerce', 'default' => true],

        // Category & Taxonomy Management
        'wc_product_cat_created' => ['name' => 'Product Category Created', 'category' => 'woocommerce', 'default' => true],
        'wc_product_cat_updated' => ['name' => 'Product Category Updated', 'category' => 'woocommerce', 'default' => false],
        'wc_product_cat_deleted' => ['name' => 'Product Category Deleted', 'category' => 'woocommerce', 'default' => true],

        // Settings & Configuration
        'wc_settings_updated' => ['name' => 'WooCommerce Settings Updated', 'category' => 'woocommerce', 'default' => true],
        'wc_payment_gateway_toggled' => ['name' => 'Payment Gateway Enabled/Disabled', 'category' => 'woocommerce', 'default' => true],
        'wc_shipping_zone_created' => ['name' => 'Shipping Zone Created', 'category' => 'woocommerce', 'default' => true],
        'wc_shipping_zone_updated' => ['name' => 'Shipping Zone Updated', 'category' => 'woocommerce', 'default' => false],
        'wc_shipping_zone_deleted' => ['name' => 'Shipping Zone Deleted', 'category' => 'woocommerce', 'default' => true],
        'wc_tax_rate_added' => ['name' => 'Tax Rate Added', 'category' => 'woocommerce', 'default' => true],
        'wc_tax_rate_updated' => ['name' => 'Tax Rate Updated', 'category' => 'woocommerce', 'default' => false],
        'wc_tax_rate_deleted' => ['name' => 'Tax Rate Deleted', 'category' => 'woocommerce', 'default' => true],
    ];

    /**
     * Request-level cache to prevent duplicate logs
     * @var array
     */
    private static $request_cache = [];

    /**
     * Track if hooks have been initialized to prevent multiple initialization
     * @var bool
     */
    private static $hooks_initialized = false;

    /**
     * Track which events are currently being processed to prevent recursion
     * @var array
     */
    private static $processing_events = [];

    /**
     * Batch logging queue for performance
     * @var array
     */
    private static $batch_queue = [];

    /**
     * Constructor. Initialize hooks based on enabled events.
     */
    public function __construct() {
        $this->init_hooks();
        
        // Cleanup expired logs on a daily schedule
        if (!wp_next_scheduled('guard_dog_cleanup_activity_logs')) {
            wp_schedule_event(time(), 'daily', 'guard_dog_cleanup_activity_logs');
        }
        add_action('guard_dog_cleanup_activity_logs', [$this, 'cleanup_old_logs']);
        
        // Process batch queue on shutdown for performance
        add_action('shutdown', [$this, 'process_batch_queue']);
    }

    /**
     * Initialize hooks based on enabled event types
     */
    private function init_hooks(): void {
        // Prevent multiple initialization
        if (self::$hooks_initialized) {
            return;
        }
        self::$hooks_initialized = true;

        $enabled_events = $this->get_enabled_events();

        // Security Events
        if (in_array('login_successful', $enabled_events)) {
            add_action('wp_login', [$this, 'log_login_successful'], 10, 2);
        }
        if (in_array('login_failed', $enabled_events)) {
            add_action('wp_login_failed', [$this, 'log_login_failed'], 10, 1);
        }
        if (in_array('password_reset', $enabled_events)) {
            add_action('password_reset', [$this, 'log_password_reset'], 10, 2);
        }

        // User Management Events
        if (in_array('user_created', $enabled_events)) {
            add_action('user_register', [$this, 'log_user_created'], 10, 1);
        }
        if (in_array('user_deleted', $enabled_events)) {
            add_action('delete_user', [$this, 'log_user_deleted'], 10, 1);
        }
        if (in_array('user_updated', $enabled_events)) {
            add_action('profile_update', [$this, 'log_user_updated'], 10, 2);
        }
        if (in_array('user_role_changed', $enabled_events)) {
            add_action('set_user_role', [$this, 'log_user_role_changed'], 10, 3);
        }

        // Content Management Events  
        if (in_array('post_created', $enabled_events)) {
            add_action('wp_insert_post', [$this, 'log_post_created'], 10, 3);
        }
        if (in_array('post_updated', $enabled_events)) {
            add_action('post_updated', [$this, 'log_post_updated'], 10, 3);
        }
        if (in_array('post_deleted', $enabled_events)) {
            add_action('before_delete_post', [$this, 'log_post_deleted'], 10, 1);
        }
        if (in_array('post_status_changed', $enabled_events)) {
            add_action('transition_post_status', [$this, 'log_post_status_changed'], 10, 3);
        }

        // Comment Events
        if (in_array('comment_created', $enabled_events)) {
            add_action('wp_insert_comment', [$this, 'log_comment_created'], 10, 2);
        }
        if (in_array('comment_approved', $enabled_events)) {
            add_action('wp_set_comment_status', [$this, 'log_comment_status_changed'], 10, 2);
        }

        // System Events
        if (in_array('plugin_activated', $enabled_events)) {
            add_action('activated_plugin', [$this, 'log_plugin_activated'], 10, 2);
        }
        if (in_array('plugin_deactivated', $enabled_events)) {
            add_action('deactivated_plugin', [$this, 'log_plugin_deactivated'], 10, 2);
        }
        if (in_array('theme_switched', $enabled_events)) {
            add_action('switch_theme', [$this, 'log_theme_switched'], 10, 3);
        }
        if (in_array('core_updated', $enabled_events)) {
            add_action('_core_updated_successfully', [$this, 'log_core_updated'], 10, 1);
        }

        // Settings Events
        if (in_array('settings_updated', $enabled_events)) {
            add_action('updated_option', [$this, 'log_option_updated'], 10, 3);
        }

        // Menu Events
        if (in_array('menu_created', $enabled_events) || in_array('menu_updated', $enabled_events)) {
            add_action('wp_create_nav_menu', [$this, 'log_menu_created'], 10, 2);
            add_action('wp_update_nav_menu', [$this, 'log_menu_updated'], 10, 1);
        }
        if (in_array('menu_deleted', $enabled_events)) {
            add_action('wp_delete_nav_menu', [$this, 'log_menu_deleted'], 10, 1);
        }

        // Widget Events
        if (in_array('widget_added', $enabled_events) || in_array('widget_updated', $enabled_events) || in_array('widget_deleted', $enabled_events)) {
            add_action('sidebar_admin_setup', [$this, 'setup_widget_monitoring']);
        }

        // WooCommerce Events - delay initialization until plugins_loaded to ensure WooCommerce is available
        add_action('plugins_loaded', function() use ($enabled_events) {
            if ($this->is_woocommerce_active()) {
                $this->init_woocommerce_hooks($enabled_events);
            }
        }, 20); // Priority 20 to run after WooCommerce initializes
    }

    /**
     * Check if WooCommerce is active
     */
    private function is_woocommerce_active(): bool {
        return class_exists('WooCommerce');
    }

    /**
     * Initialize WooCommerce-specific hooks
     */
    private function init_woocommerce_hooks(array $enabled_events): void {
        // Product Events
        if (in_array('wc_product_created', $enabled_events)) {
            add_action('woocommerce_new_product', [$this, 'log_wc_product_created'], 10, 1);
        }
        if (in_array('wc_product_updated', $enabled_events)) {
            add_action('woocommerce_update_product', [$this, 'log_wc_product_updated'], 10, 2);
        }
        if (in_array('wc_product_deleted', $enabled_events)) {
            add_action('before_delete_post', [$this, 'log_wc_product_deleted'], 10, 1);
        }
        if (in_array('wc_product_trashed', $enabled_events)) {
            add_action('wp_trash_post', [$this, 'log_wc_product_trashed'], 10, 1);
        }
        if (in_array('wc_product_restored', $enabled_events)) {
            add_action('untrashed_post', [$this, 'log_wc_product_restored'], 10, 1);
        }
        if (in_array('wc_product_stock_changed', $enabled_events)) {
            add_action('woocommerce_product_set_stock', [$this, 'log_wc_product_stock_changed'], 10, 1);
            add_action('woocommerce_variation_set_stock', [$this, 'log_wc_product_stock_changed'], 10, 1);
        }

        // Order Events
        if (in_array('wc_order_created', $enabled_events)) {
            add_action('woocommerce_new_order', [$this, 'log_wc_order_created'], 10, 1);
        }
        if (in_array('wc_order_status_changed', $enabled_events)) {
            add_action('woocommerce_order_status_changed', [$this, 'log_wc_order_status_changed'], 10, 4);
        }
        if (in_array('wc_order_deleted', $enabled_events)) {
            add_action('before_delete_post', [$this, 'log_wc_order_deleted'], 10, 1);
        }
        if (in_array('wc_order_refunded', $enabled_events)) {
            add_action('woocommerce_order_refunded', [$this, 'log_wc_order_refunded'], 10, 2);
        }
        if (in_array('wc_order_note_added', $enabled_events)) {
            add_action('woocommerce_new_order_note', [$this, 'log_wc_order_note_added'], 10, 1);
        }

        // Coupon Events
        if (in_array('wc_coupon_created', $enabled_events)) {
            add_action('woocommerce_new_coupon', [$this, 'log_wc_coupon_created'], 10, 1);
        }
        if (in_array('wc_coupon_updated', $enabled_events)) {
            add_action('woocommerce_update_coupon', [$this, 'log_wc_coupon_updated'], 10, 2);
        }
        if (in_array('wc_coupon_deleted', $enabled_events)) {
            add_action('before_delete_post', [$this, 'log_wc_coupon_deleted'], 10, 1);
        }

        // Product Category Events
        if (in_array('wc_product_cat_created', $enabled_events)) {
            add_action('created_product_cat', [$this, 'log_wc_product_cat_created'], 10, 2);
        }
        if (in_array('wc_product_cat_updated', $enabled_events)) {
            add_action('edited_product_cat', [$this, 'log_wc_product_cat_updated'], 10, 2);
        }
        if (in_array('wc_product_cat_deleted', $enabled_events)) {
            add_action('delete_product_cat', [$this, 'log_wc_product_cat_deleted'], 10, 4);
        }

        // Settings Events
        if (in_array('wc_settings_updated', $enabled_events)) {
            add_action('woocommerce_settings_saved', [$this, 'log_wc_settings_updated'], 10, 0);
        }
        if (in_array('wc_payment_gateway_toggled', $enabled_events)) {
            add_action('woocommerce_update_option', [$this, 'log_wc_payment_gateway_toggled'], 10, 1);
        }

        // Shipping Zone Events
        if (in_array('wc_shipping_zone_created', $enabled_events)) {
            add_action('woocommerce_shipping_zone_added', [$this, 'log_wc_shipping_zone_created'], 10, 2);
        }
        if (in_array('wc_shipping_zone_updated', $enabled_events)) {
            add_action('woocommerce_shipping_zone_updated', [$this, 'log_wc_shipping_zone_updated'], 10, 2);
        }
        if (in_array('wc_shipping_zone_deleted', $enabled_events)) {
            add_action('woocommerce_delete_shipping_zone', [$this, 'log_wc_shipping_zone_deleted'], 10, 1);
        }

        // Tax Rate Events
        if (in_array('wc_tax_rate_added', $enabled_events)) {
            add_action('woocommerce_tax_rate_added', [$this, 'log_wc_tax_rate_added'], 10, 2);
        }
        if (in_array('wc_tax_rate_updated', $enabled_events)) {
            add_action('woocommerce_tax_rate_updated', [$this, 'log_wc_tax_rate_updated'], 10, 2);
        }
        if (in_array('wc_tax_rate_deleted', $enabled_events)) {
            add_action('woocommerce_tax_rate_deleted', [$this, 'log_wc_tax_rate_deleted'], 10, 1);
        }
    }

    /**
     * Add an entry to the activity log with performance optimizations
     */
    public function add_log_entry(string $event_type, array $args = []): bool {
        // Check if event type is enabled
        if (!$this->is_event_enabled($event_type)) {
            // Debug logging to help troubleshoot
            if (function_exists('Guard_Dog') && Guard_Dog()->debug && Guard_Dog()->debug->is_enabled()) {
                Guard_Dog()->debug->info('Activity Log: Event disabled, not logging', 'activity_log', [
                    'event_type' => $event_type,
                    'settings' => get_option('guard_dog_activity_log_settings', [])
                ]);
            }
            return false;
        }

        // Debug logging for enabled events
        if (function_exists('Guard_Dog') && Guard_Dog()->debug && Guard_Dog()->debug->is_enabled()) {
            Guard_Dog()->debug->info('Activity Log: Event enabled, logging', 'activity_log', [
                'event_type' => $event_type
            ]);
        }

        // Prevent duplicate logs within the same request
        $cache_key = md5($event_type . serialize($args));
        if (isset(self::$request_cache[$cache_key])) {
            return false;
        }
        self::$request_cache[$cache_key] = true;

        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';
        
        if (!$this->table_exists($table_name)) {
            Guard_Dog()->debug->error('Guard Dog Activity Log: Table ' . $table_name . ' does not exist.');
            return false;
        }

        $current_user = wp_get_current_user();
        $current_user_ip = Guard_Dog_Utils::get_user_ip();

        $default_args = [
            'username'   => $current_user->exists() ? $current_user->user_login : null,
            'user_id'    => $current_user->exists() ? $current_user->ID : null,
            'ip_address' => $current_user_ip,
            'details'    => null,
            'object_id'  => null,
            'object_type' => null,
        ];

        $data = wp_parse_args($args, $default_args);

        $insert_data = [
            'timestamp'   => current_time('mysql', 1),
            'event_type'  => sanitize_text_field($event_type),
            'username'    => $data['username'] ? sanitize_user($data['username'], true) : null,
            'user_id'     => $data['user_id'] ? absint($data['user_id']) : null,
            'ip_address'  => $data['ip_address'] ? sanitize_text_field($data['ip_address']) : null,
            'object_id'   => $data['object_id'] ? absint($data['object_id']) : null,
            'object_type' => $data['object_type'] ? sanitize_text_field($data['object_type']) : null,
            'details'     => $data['details'] ? wp_json_encode($data['details']) : null,
        ];

        // For critical security events, log immediately. Otherwise, use the batch queue.
        $critical_events = [
            'login_successful', 'login_failed', 'login_blocked', 'ip_blocked', 
            '2fa_successful', '2fa_failed', 'temp_access_used'
        ];

        if (in_array($event_type, $critical_events) || !$this->is_batch_logging_enabled()) {
            return $this->insert_log_entry($table_name, $insert_data);
        }

        // Add to batch queue for performance
        self::$batch_queue[] = $insert_data;
        return true;
    }

    /**
     * Insert log entry into database
     */
    private function insert_log_entry(string $table_name, array $data): bool {
        global $wpdb;
        
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database queries are necessary for activity logging to ensure real-time data accuracy
        // Caching is not appropriate for security event logging as it could cause data loss
        $result = $wpdb->insert($table_name, array_filter($data, function($value) {
            return $value !== null;
        }));
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

        if ($result === false) {
            Guard_Dog()->debug->error("Guard Dog: Failed to insert log entry. DB Error: " . $wpdb->last_error);
            return false;
        }
        
        // Trigger cleanup to enforce max entries limit (but only occasionally to avoid performance impact)
        if (wp_rand(1, 100) <= 5) { // 5% chance - adjust as needed
            $this->cleanup_excess_entries();
        }
        
        return true;
    }

    /**
     * Process batch queue for performance optimization
     */
    public function process_batch_queue(): void {
        if (empty(self::$batch_queue)) {
            return;
        }

        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';

        if (!$this->table_exists($table_name)) {
            return;
        }

        // Process in chunks of 50 for optimal performance
        $chunks = array_chunk(self::$batch_queue, 50);
        
        foreach ($chunks as $chunk) {
            $this->batch_insert_logs($table_name, $chunk);
        }

        // Clear the queue
        self::$batch_queue = [];
    }

    /**
     * Batch insert logs for better performance
     */
    private function batch_insert_logs(string $table_name, array $logs): void {
        global $wpdb;

        if (empty($logs)) {
            return;
        }

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            Guard_Dog()->debug->error("Invalid table name for batch insert: " . esc_html($table_name));
            return;
        }

        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database queries are necessary for activity logging to ensure real-time data accuracy
        // Caching is not appropriate for security event logging as it could cause data loss
        // Use individual inserts to satisfy WordPress Plugin Checker
        // This is safer and more compatible than dynamic bulk inserts
        foreach ($logs as $log) {
            $insert_data = array_filter([
                'timestamp' => $log['timestamp'] ?? null,
                'event_type' => $log['event_type'] ?? null,
                'username' => $log['username'] ?? null,
                'user_id' => $log['user_id'] ?? null,
                'ip_address' => $log['ip_address'] ?? null,
                'object_id' => $log['object_id'] ?? null,
                'object_type' => $log['object_type'] ?? null,
                'details' => $log['details'] ?? null,
            ], function($value) {
                return $value !== null;
            });

            $result = $wpdb->insert($table_name, $insert_data);
            
            if ($result === false) {
                Guard_Dog()->debug->error("Failed to insert log entry. DB Error: " . $wpdb->last_error);
                break; // Stop on first error
            }
        }

    }

    // ===== EVENT HANDLERS =====

    /**
     * Log successful login
     */
    public function log_login_successful(string $user_login, WP_User $user): void {
        // Check if a 2FA event was already logged for this user in this request to avoid duplicate entries.
        $cache_key = md5('2fa_successful' . serialize(['user_id' => $user->ID]));
        if (isset(self::$request_cache[$cache_key])) {
            return;
        }

        $this->add_log_entry('login_successful', [
            'username' => $user_login,
            'user_id' => $user->ID,
            'details' => [
                'display_name' => $user->display_name,
                'roles' => $user->roles,
                'user_agent' => $this->get_user_agent_if_enabled(),
            ]
        ]);
    }

    /**
     * Log failed login attempt
     */
    public function log_login_failed(string $username): void {
        $this->add_log_entry('login_failed', [
            'username' => $username,
            'details' => [
                'error' => 'Incorrect username or password',
                'user_agent' => $this->get_user_agent_if_enabled(),
            ]
        ]);
    }

    /**
     * Log password reset
     */
    public function log_password_reset(WP_User $user, string $new_pass): void {
        $this->add_log_entry('password_reset', [
            'username' => $user->user_login,
            'user_id' => $user->ID,
            'details' => [
                'method' => 'Password reset request'
            ]
        ]);
    }

    /**
     * Log user creation
     */
    public function log_user_created(int $user_id): void {
        $user = get_user_by('id', $user_id);
        if (!$user) return;

        $this->add_log_entry('user_created', [
            'object_id' => $user_id,
            'object_type' => 'user',
            'details' => [
                'username' => $user->user_login,
                'email' => $user->user_email,
                'roles' => $user->roles,
            ]
        ]);
    }

    /**
     * Log user deletion
     */
    public function log_user_deleted(int $user_id): void {
        $user = get_user_by('id', $user_id);
        if (!$user) return;

        $this->add_log_entry('user_deleted', [
            'object_id' => $user_id,
            'object_type' => 'user',
            'details' => [
                'username' => $user->user_login,
                'email' => $user->user_email,
                'roles' => $user->roles,
            ]
        ]);
    }

    /**
     * Log user role change
     */
    public function log_user_role_changed(int $user_id, string $role, array $old_roles): void {
        $user = get_user_by('id', $user_id);
        if (!$user) return;

        $this->add_log_entry('user_role_changed', [
            'object_id' => $user_id,
            'object_type' => 'user',
            'details' => [
                'username' => $user->user_login,
                'old_roles' => $old_roles,
                'new_role' => $role,
            ]
        ]);
    }

    /**
     * Log post creation
     */
    public function log_post_created(int $post_id, WP_Post $post, bool $update): void {
        if ($update || $post->post_status === 'auto-draft') {
            return; // Skip updates and auto-drafts
        }

        // Exclude WooCommerce post types - they have their own handlers
        $wc_post_types = ['product', 'product_variation', 'shop_order', 'shop_coupon'];
        if (in_array($post->post_type, $wc_post_types)) {
            return;
        }

        $this->add_log_entry('post_created', [
            'object_id' => $post_id,
            'object_type' => 'post',
            'details' => [
                'post_title' => $post->post_title,
                'post_type' => $post->post_type,
                'post_status' => $post->post_status,
            ]
        ]);
    }

    /**
     * Log post deletion
     */
    public function log_post_deleted(int $post_id): void {
        Guard_Dog()->debug->debug('log_post_deleted called for post_id ' . $post_id);
        $post = get_post($post_id);
        if (!$post) {
            Guard_Dog()->debug->debug('log_post_deleted - post not found for post_id ' . $post_id);
            return;
        }

        // Exclude WooCommerce post types - they have their own handlers
        $wc_post_types = ['product', 'product_variation', 'shop_order', 'shop_coupon'];
        if (in_array($post->post_type, $wc_post_types)) {
            return;
        }

        $this->add_log_entry('post_deleted', [
            'object_id' => $post_id,
            'object_type' => 'post',
            'details' => [
                'post_title' => $post->post_title,
                'post_type' => $post->post_type,
                'post_status' => $post->post_status,
            ]
        ]);
    }

    /**
     * Log post status change
     */
    public function log_post_status_changed(string $new_status, string $old_status, WP_Post $post): void {
        Guard_Dog()->debug->debug('log_post_status_changed called for post_id ' . $post->ID . ' from ' . $old_status . ' to ' . $new_status);
        if ($new_status === $old_status || $old_status === 'auto-draft') {
            return;
        }

        // Exclude WooCommerce post types - they have their own handlers
        $wc_post_types = ['product', 'product_variation', 'shop_order', 'shop_coupon'];
        if (in_array($post->post_type, $wc_post_types)) {
            return;
        }

        if ($new_status === 'trash') {
            $this->add_log_entry('post_trashed', [
                'object_id' => $post->ID,
                'object_type' => 'post',
                'details' => [
                    'post_title' => $post->post_title,
                    'post_type' => $post->post_type,
                    'old_status' => $old_status,
                    'new_status' => $new_status,
                ]
            ]);
        }

        $this->add_log_entry('post_status_changed', [
            'object_id' => $post->ID,
            'object_type' => 'post',
            'details' => [
                'post_title' => $post->post_title,
                'post_type' => $post->post_type,
                'old_status' => $old_status,
                'new_status' => $new_status,
            ]
        ]);
    }

    /**
     * Log post update event
     * @param int $post_ID
     * @param WP_Post $post_after
     * @param WP_Post $post_before
     */
    public function log_post_updated($post_ID, $post_after, $post_before) {
        Guard_Dog()->debug->debug('log_post_updated called for post_ID ' . $post_ID);
        // Only log if something actually changed
        if ($post_after->post_modified === $post_before->post_modified) {
            return;
        }

        // Exclude WooCommerce post types - they have their own handlers
        $wc_post_types = ['product', 'product_variation', 'shop_order', 'shop_coupon'];
        if (in_array($post_after->post_type, $wc_post_types)) {
            return;
        }

        $this->add_log_entry('post_updated', [
            'object_id' => $post_ID,
            'object_type' => 'post',
            'details' => [
                'post_title_before' => $post_before->post_title,
                'post_title_after' => $post_after->post_title,
                'post_type' => $post_after->post_type,
                'status_before' => $post_before->post_status,
                'status_after' => $post_after->post_status,
            ]
        ]);
    }

    /**
     * Log plugin activation
     */
    public function log_plugin_activated(string $plugin, bool $network_wide): void {
        $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin, false, false);
        
        $this->add_log_entry('plugin_activated', [
            'details' => [
                'plugin_name' => $plugin_data['Name'] ?? $plugin,
                'plugin_file' => $plugin,
                'version' => $plugin_data['Version'] ?? 'Unknown',
                'network_wide' => $network_wide,
            ]
        ]);
    }

    /**
     * Log plugin deactivation
     */
    public function log_plugin_deactivated(string $plugin, bool $network_wide): void {
        $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin, false, false);
        
        $this->add_log_entry('plugin_deactivated', [
            'details' => [
                'plugin_name' => $plugin_data['Name'] ?? $plugin,
                'plugin_file' => $plugin,
                'version' => $plugin_data['Version'] ?? 'Unknown',
                'network_wide' => $network_wide,
            ]
        ]);
    }

    /**
     * Log theme switch
     */
    public function log_theme_switched(string $new_name, WP_Theme $new_theme, WP_Theme $old_theme): void {
        $this->add_log_entry('theme_switched', [
            'details' => [
                'old_theme' => $old_theme->get('Name'),
                'new_theme' => $new_theme->get('Name'),
                'new_version' => $new_theme->get('Version'),
            ]
        ]);
    }

    /**
     * Log WordPress core update
     */
    public function log_core_updated(string $wp_version): void {
        $this->add_log_entry('core_updated', [
            'details' => [
                'new_version' => $wp_version,
                'old_version' => get_option('guard_dog_wp_version_before_update', 'Unknown'),
            ]
        ]);
    }

    // ===== SECURITY-SPECIFIC LOGGING METHODS =====

    /**
     * Log IP blocking event
     */
    public function log_ip_blocked(string $ip_address, string $reason): void {
        $this->add_log_entry('ip_blocked', [
            'ip_address' => $ip_address,
            'details' => [
                'reason' => $reason,
                'user_agent' => $this->get_user_agent_if_enabled(),
            ]
        ]);
    }

    /**
     * Log CAPTCHA failure
     */
    public function log_captcha_failed(string $type, ?string $username = null): void {
        $this->add_log_entry('captcha_failed', [
            'username' => $username,
            'details' => [
                'captcha_type' => $type,
                'user_agent' => $this->get_user_agent_if_enabled(),
            ]
        ]);
    }

    /**
     * Log 2FA events
     */
    public function log_2fa_event(string $event_type, int $user_id, array $details = []): void {
        $user = get_user_by('id', $user_id);
        if (!$user) return;

        $this->add_log_entry($event_type, [
            'username' => $user->user_login,
            'user_id' => $user_id,
            'details' => array_merge([
                'user_agent' => $this->get_user_agent_if_enabled(),
            ], $details)
        ]);
    }

    /**
     * Log temporary access events
     */
    public function log_temp_access_event(string $event_type, array $details = []): void {
        $this->add_log_entry($event_type, [
            'details' => $details
        ]);
    }

    // ===== UTILITY METHODS =====

    /**
     * Get supported event categories for Activity Log event definitions.
     */
    private static function get_supported_event_categories(): array {
        return ['security', 'users', 'content', 'system', 'woocommerce'];
    }

    /**
     * Normalize Activity Log event type definitions from core and developer filters.
     */
    private static function normalize_event_types(array $event_types): array {
        $normalized = [];

        foreach ($event_types as $event_type => $config) {
            $event_type = sanitize_key((string) $event_type);

            if ($event_type === '' || strlen($event_type) > 100 || !is_array($config)) {
                continue;
            }

            $name = isset($config['name']) ? sanitize_text_field((string) $config['name']) : $event_type;
            $category = isset($config['category']) ? sanitize_key((string) $config['category']) : 'system';

            if (!in_array($category, self::get_supported_event_categories(), true)) {
                $category = 'system';
            }

            $normalized[$event_type] = [
                'name' => $name !== '' ? $name : $event_type,
                'category' => $category,
                'default' => isset($config['default']) ? (bool) $config['default'] : false,
            ];
        }

        return $normalized;
    }

    /**
     * Get enabled event types
     */
    private function get_enabled_events(): array {
        $settings = get_option('guard_dog_activity_log_settings', []);
        $enabled = [];

        foreach (self::get_event_types() as $event_type => $config) {
            // Check if explicitly set in settings
            if (isset($settings['events'][$event_type])) {
                $is_enabled = $settings['events'][$event_type];
            } else {
                // Use default if not explicitly set
                $is_enabled = $config['default'];
            }
                
            if ($is_enabled) {
                $enabled[] = $event_type;
            }
        }

        return $enabled;
    }

    /**
     * Check if specific event type is enabled
     */
    private function is_event_enabled(string $event_type): bool {
        $event_types = self::get_event_types();

        // Check if event type exists in our defined types
        if (!isset($event_types[$event_type])) {
            return false;
        }

        // Get current settings format
        $settings = get_option('guard_dog_activity_log_settings', []);
        
        // If explicitly set in settings, use that value
        if (isset($settings['events'][$event_type])) {
            $final_result = (bool) $settings['events'][$event_type];
        } else {
            // If not set in settings, use the default from event definition
            $final_result = $event_types[$event_type]['default'];
        }
        
        // Debug logging to help troubleshoot
        if (function_exists('Guard_Dog') && Guard_Dog()->debug && Guard_Dog()->debug->is_enabled()) {
            Guard_Dog()->debug->info('Activity Log: Event enabled check', 'activity_log', [
                'event_type' => $event_type,
                'settings' => $settings,
                'default_enabled' => $event_types[$event_type]['default'],
                'final_result' => $final_result
            ]);
        }
        
        return $final_result;
    }

    /**
     * Check if batch logging is enabled
     */
    private function is_batch_logging_enabled(): bool {
        $settings = get_option('guard_dog_activity_log_settings', []);
        return $settings['enable_batch_logging'] ?? true;
    }

    /**
     * Get event types configuration
     */
    public static function get_event_types(): array {
        /**
         * Filter the Activity Log event type registry.
         *
         * Custom event slugs must be 100 characters or fewer because the database
         * column is VARCHAR(100). Supported categories are security, users, content,
         * system, and woocommerce.
         *
         * @param array $event_types Event definitions keyed by event slug.
         */
        $event_types = apply_filters('guard_dog_activity_log_event_types', self::$event_types);

        if (!is_array($event_types)) {
            $event_types = self::$event_types;
        }

        return self::normalize_event_types($event_types);
    }

    /**
     * Get event types that are available based on current WordPress configuration
     * Filters out WooCommerce events if WooCommerce is not active
     *
     * @return array Filtered event types
     */
    public static function get_available_event_types(): array {
        $event_types = self::get_event_types();

        // If WooCommerce is not active, filter out WooCommerce events
        if (!class_exists('WooCommerce')) {
            $event_types = array_filter($event_types, function($event_config) {
                return $event_config['category'] !== 'woocommerce';
            });
        }

        return $event_types;
    }

    /**
     * Get the human-readable label for an event type.
     *
     * Used when rendering the Activity Log in the admin (titles, list table).
     * Falls back to "Unknown Event" when the slug is not in the registered event types.
     *
     * @param string $event_type The event type slug (e.g. 'passkey_login_success', 'session_created').
     * @return string The translated label for the event.
     */
    public static function get_event_label(string $event_type): string {
        $types = self::get_event_types();
        if ( isset( $types[ $event_type ]['name'] ) ) {
            return __( $types[ $event_type ]['name'], 'guard-dog' );
        }
        return __( 'Unknown Event', 'guard-dog' );
    }

    /**
     * Get activity logs with filtering
     */
    public function get_logs(array $filters = []): array {
        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';

        if (!$this->table_exists($table_name)) {
            return [];
        }

        // Pagination
        $page = max(1, intval($filters['page'] ?? 1));
        $per_page = min(100, max(10, intval($filters['per_page'] ?? 20)));
        $offset = ($page - 1) * $per_page;

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            return [];
        }

        // Use a simplified approach that satisfies WordPress Plugin Checker
        // Start with base query and apply filters through separate queries if needed
        
        // If no filters, return simple paginated results
        if (empty(array_filter($filters, function($value, $key) {
            return !in_array($key, ['page', 'per_page']) && !empty($value) && $value !== 'all';
        }, ARRAY_FILTER_USE_BOTH))) {
            // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            // Direct database queries are necessary for activity log retrieval to ensure real-time data
            // Caching is not appropriate for security event logs as data may be updated frequently
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $per_page,
                $offset
            ), ARRAY_A) ?: [];
            // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        }

        // For filtered queries, we'll need to compromise with WordPress Plugin Checker limitations
        // Use a single comprehensive query with all possible parameters
        $query_params = [];
        
        // Set default values for all possible parameters
        $event_type = !empty($filters['event_type']) && $filters['event_type'] !== 'all' ? $filters['event_type'] : '';
        $user_id = !empty($filters['user_id']) ? intval($filters['user_id']) : 0;
        $ip_address = !empty($filters['ip_address']) ? $filters['ip_address'] : '';
        $date_from = !empty($filters['date_from']) ? $filters['date_from'] . ' 00:00:00' : '1970-01-01 00:00:00';
        $date_to = !empty($filters['date_to']) ? $filters['date_to'] . ' 23:59:59' : '2099-12-31 23:59:59';
        $search_term = !empty($filters['search']) ? '%' . $wpdb->esc_like($filters['search']) . '%' : '';

        // Handle category filtering separately due to IN clause complexity
        if (!empty($filters['category']) && $filters['category'] !== 'all') {
            $event_types = self::get_event_types();
            $event_types_in_category = array_keys(array_filter($event_types, function($info) use ($filters) {
                return $info['category'] === $filters['category'];
            }));
            
            if (empty($event_types_in_category)) {
                return []; // No events in this category
            }
            
            // Use static SQL patterns for WordPress Plugin Checker compliance
            // Handle different category sizes with separate queries
            $category_count = count($event_types_in_category);
            
            // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            // Direct database queries are necessary for activity log retrieval to ensure real-time data
            // Caching is not appropriate for security event logs as data may be updated frequently
            if ($category_count === 1) {
                return $wpdb->get_results($wpdb->prepare(
                    "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                    $event_types_in_category[0],
                    $per_page,
                    $offset
                ), ARRAY_A) ?: [];
            } elseif ($category_count === 2) {
                return $wpdb->get_results($wpdb->prepare(
                    "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type IN (%s, %s) ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                    $event_types_in_category[0],
                    $event_types_in_category[1],
                    $per_page,
                    $offset
                ), ARRAY_A) ?: [];
            } elseif ($category_count === 3) {
                return $wpdb->get_results($wpdb->prepare(
                    "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type IN (%s, %s, %s) ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                    $event_types_in_category[0],
                    $event_types_in_category[1],
                    $event_types_in_category[2],
                    $per_page,
                    $offset
                ), ARRAY_A) ?: [];
            } else {
                // For larger categories, use a simpler approach with multiple queries
                $results = [];
                foreach ($event_types_in_category as $event_type) {
                    $type_results = $wpdb->get_results($wpdb->prepare(
                        "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s ORDER BY timestamp DESC LIMIT %d",
                        $event_type,
                        $per_page * 2 // Get more to account for pagination
                    ), ARRAY_A) ?: [];
                    $results = array_merge($results, $type_results);
                }
                
                // Sort by timestamp and apply pagination
                usort($results, function($a, $b) {
                    return strtotime($b['timestamp']) - strtotime($a['timestamp']);
                });
                
                return array_slice($results, $offset, $per_page);
            }
            // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        }

        // Build the comprehensive query for non-category filters
        // Use conditional branching instead of dynamic SQL construction for WordPress Plugin Checker compliance
        
        // Determine which filters are active
        $has_event_type = !empty($event_type);
        $has_user_id = $user_id > 0;
        $has_ip_address = !empty($ip_address);
        $has_date_from = $date_from !== '1970-01-01 00:00:00';
        $has_date_to = $date_to !== '2099-12-31 23:59:59';
        $has_search = !empty($search_term);
        
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database queries are necessary for activity log retrieval to ensure real-time data
        // Caching is not appropriate for security event logs as data may be updated frequently
        // Build query based on active filters using static SQL patterns
        if ($has_event_type && $has_user_id && $has_ip_address && $has_date_from && $has_date_to && $has_search) {
            // All filters active
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d AND ip_address = %s AND timestamp >= %s AND timestamp <= %s AND (username LIKE %s OR details LIKE %s) ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $event_type, $user_id, $ip_address, $date_from, $date_to, $search_term, $search_term, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_event_type && $has_user_id && $has_ip_address && $has_date_from && $has_date_to) {
            // All except search
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d AND ip_address = %s AND timestamp >= %s AND timestamp <= %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $event_type, $user_id, $ip_address, $date_from, $date_to, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_event_type && $has_user_id && $has_ip_address && $has_date_from) {
            // All except date_to and search
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d AND ip_address = %s AND timestamp >= %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $event_type, $user_id, $ip_address, $date_from, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_event_type && $has_user_id && $has_ip_address) {
            // All except dates and search
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d AND ip_address = %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $event_type, $user_id, $ip_address, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_event_type && $has_user_id) {
            // Event type and user ID only
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $event_type, $user_id, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_event_type) {
            // Event type only
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $event_type, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_user_id) {
            // User ID only
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE user_id = %d ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $user_id, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_ip_address) {
            // IP address only
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE ip_address = %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $ip_address, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_date_from && $has_date_to) {
            // Date range only
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND timestamp <= %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $date_from, $date_to, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_date_from) {
            // Date from only
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $date_from, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_date_to) {
            // Date to only
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp <= %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $date_to, $per_page, $offset
            ), ARRAY_A) ?: [];
        } elseif ($has_search) {
            // Search only
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` WHERE username LIKE %s OR details LIKE %s ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $search_term, $search_term, $per_page, $offset
            ), ARRAY_A) ?: [];
        } else {
            // No filters - return all
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` ORDER BY timestamp DESC LIMIT %d OFFSET %d",
                $per_page, $offset
            ), ARRAY_A) ?: [];
        }
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    }

    /**
     * Get filtered activity logs count
     * 
     * Applies the same filtering logic as get_logs() but returns only the count.
     * Used for pagination calculations that need to reflect current filters.
     *
     * @param array $filters Filter parameters (category, event_type, user_id, ip_address, date_from, date_to, search)
     * @return int Total count of logs matching the filters
     */
    public function get_filtered_logs_count(array $filters = []): int {
        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';

        if (!$this->table_exists($table_name)) {
            return 0;
        }

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            return 0;
        }

        // Set default values for all possible parameters (same as get_logs)
        $event_type = !empty($filters['event_type']) && $filters['event_type'] !== 'all' ? $filters['event_type'] : '';
        $user_id = !empty($filters['user_id']) ? intval($filters['user_id']) : 0;
        $ip_address = !empty($filters['ip_address']) ? $filters['ip_address'] : '';
        $date_from = !empty($filters['date_from']) ? $filters['date_from'] . ' 00:00:00' : '1970-01-01 00:00:00';
        $date_to = !empty($filters['date_to']) ? $filters['date_to'] . ' 23:59:59' : '2099-12-31 23:59:59';
        $search_term = !empty($filters['search']) ? '%' . $wpdb->esc_like($filters['search']) . '%' : '';

        // Handle category filtering separately due to IN clause complexity
        if (!empty($filters['category']) && $filters['category'] !== 'all') {
            $event_types = self::get_event_types();
            $event_types_in_category = array_keys(array_filter($event_types, function($info) use ($filters) {
                return $info['category'] === $filters['category'];
            }));
            
            if (empty($event_types_in_category)) {
                return 0; // No events in this category
            }
            
            // Use static SQL patterns for WordPress Plugin Checker compliance
            // Handle different category sizes with separate queries
            $category_count = count($event_types_in_category);
            
            // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            // Direct database queries are necessary for activity log count to ensure real-time data
            // Caching is not appropriate for security event counts as data may be updated frequently
            if ($category_count === 1) {
                $count = $wpdb->get_var($wpdb->prepare(
                    "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s",
                    $event_types_in_category[0]
                ));
                return intval($count);
            } elseif ($category_count === 2) {
                $count = $wpdb->get_var($wpdb->prepare(
                    "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type IN (%s, %s)",
                    $event_types_in_category[0],
                    $event_types_in_category[1]
                ));
                return intval($count);
            } elseif ($category_count === 3) {
                $count = $wpdb->get_var($wpdb->prepare(
                    "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type IN (%s, %s, %s)",
                    $event_types_in_category[0],
                    $event_types_in_category[1],
                    $event_types_in_category[2]
                ));
                return intval($count);
            } else {
                // For larger categories, count each type and sum
                $total_count = 0;
                foreach ($event_types_in_category as $type) {
                    $type_count = $wpdb->get_var($wpdb->prepare(
                        "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s",
                        $type
                    ));
                    $total_count += intval($type_count);
                }
                return $total_count;
            }
            // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        }

        // Build the comprehensive query for non-category filters
        // Use conditional branching instead of dynamic SQL construction for WordPress Plugin Checker compliance
        
        // Determine which filters are active
        $has_event_type = !empty($event_type);
        $has_user_id = $user_id > 0;
        $has_ip_address = !empty($ip_address);
        $has_date_from = $date_from !== '1970-01-01 00:00:00';
        $has_date_to = $date_to !== '2099-12-31 23:59:59';
        $has_search = !empty($search_term);
        
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database queries are necessary for activity log count to ensure real-time data
        // Caching is not appropriate for security event counts as data may be updated frequently
        // Build query based on active filters using static SQL patterns
        $count = 0;
        if ($has_event_type && $has_user_id && $has_ip_address && $has_date_from && $has_date_to && $has_search) {
            // All filters active
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d AND ip_address = %s AND timestamp >= %s AND timestamp <= %s AND (username LIKE %s OR details LIKE %s)",
                $event_type, $user_id, $ip_address, $date_from, $date_to, $search_term, $search_term
            ));
        } elseif ($has_event_type && $has_user_id && $has_ip_address && $has_date_from && $has_date_to) {
            // All except search
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d AND ip_address = %s AND timestamp >= %s AND timestamp <= %s",
                $event_type, $user_id, $ip_address, $date_from, $date_to
            ));
        } elseif ($has_event_type && $has_user_id && $has_ip_address && $has_date_from) {
            // All except date_to and search
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d AND ip_address = %s AND timestamp >= %s",
                $event_type, $user_id, $ip_address, $date_from
            ));
        } elseif ($has_event_type && $has_user_id && $has_ip_address) {
            // All except dates and search
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d AND ip_address = %s",
                $event_type, $user_id, $ip_address
            ));
        } elseif ($has_event_type && $has_user_id) {
            // Event type and user ID only
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s AND user_id = %d",
                $event_type, $user_id
            ));
        } elseif ($has_event_type) {
            // Event type only
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE event_type = %s",
                $event_type
            ));
        } elseif ($has_user_id) {
            // User ID only
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE user_id = %d",
                $user_id
            ));
        } elseif ($has_ip_address) {
            // IP address only
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE ip_address = %s",
                $ip_address
            ));
        } elseif ($has_date_from && $has_date_to) {
            // Date range only
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND timestamp <= %s",
                $date_from, $date_to
            ));
        } elseif ($has_date_from) {
            // Date from only
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s",
                $date_from
            ));
        } elseif ($has_date_to) {
            // Date to only
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp <= %s",
                $date_to
            ));
        } elseif ($has_search) {
            // Search only
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE username LIKE %s OR details LIKE %s",
                $search_term, $search_term
            ));
        } else {
            // No filters - return all count
            $count = $wpdb->get_var("SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs`");
        }
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        
        return intval($count);
    }

    /**
     * Get activity statistics
     */
    public function get_statistics(int $days = 30): array {
        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';

        if (!$this->table_exists($table_name)) {
            return [
                'total_events' => 0,
                'security_events' => 0,
                'login_events' => 0,
                'content_events' => 0,
                'system_events' => 0,
                'failed_logins' => 0,
                'unique_users' => 0,
                'unique_ips' => 0,
            ];
        }

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            return [
                'total_events' => 0,
                'security_events' => 0,
                'login_events' => 0,
                'content_events' => 0,
                'system_events' => 0,
                'failed_logins' => 0,
                'unique_users' => 0,
                'unique_ips' => 0,
            ];
        }

        $date_from = gmdate('Y-m-d H:i:s', strtotime("-{$days} days"));

        // Get event types organized by category
        $event_types = self::get_event_types();
        
        // Build arrays of event types for each category
        $security_event_types = [];
        $user_event_types = [];
        $content_event_types = [];
        $system_event_types = [];
        
        foreach ($event_types as $event_type => $config) {
            switch ($config['category']) {
                case 'security':
                    $security_event_types[] = $event_type;
                    break;
                case 'users':
                    $user_event_types[] = $event_type;
                    break;
                case 'content':
                    $content_event_types[] = $event_type;
                    break;
                case 'system':
                    $system_event_types[] = $event_type;
                    break;
            }
        }
        
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database queries are necessary for activity log statistics to ensure real-time data
        // Caching is not appropriate for security event statistics as data may be updated frequently
        // Get basic counts - table name already validated above
        $total_events = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s",
            $date_from
        ));
        


        // Get category counts by querying each event type individually to satisfy WordPress Plugin Checker
        // This avoids dynamic placeholder generation which the Plugin Checker flags as unsafe
        // The event types are validated against a predefined list and cannot be injected
        $security_events = 0;
        if (!empty($security_event_types)) {
            foreach ($security_event_types as $event_type) {
                $count = $wpdb->get_var($wpdb->prepare(
                    "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND event_type = %s",
                    $date_from,
                    $event_type
                ));
                $security_events += intval($count);
            }
        }

        $login_events = 0;
        if (!empty($user_event_types)) {
            foreach ($user_event_types as $event_type) {
                $count = $wpdb->get_var($wpdb->prepare(
                    "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND event_type = %s",
                    $date_from,
                    $event_type
                ));
                $login_events += intval($count);
            }
        }

        $content_events = 0;
        if (!empty($content_event_types)) {
            foreach ($content_event_types as $event_type) {
                $count = $wpdb->get_var($wpdb->prepare(
                    "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND event_type = %s",
                    $date_from,
                    $event_type
                ));
                $content_events += intval($count);
            }
        }

        $system_events = 0;
        if (!empty($system_event_types)) {
            foreach ($system_event_types as $event_type) {
                $count = $wpdb->get_var($wpdb->prepare(
                    "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND event_type = %s",
                    $date_from,
                    $event_type
                ));
                $system_events += intval($count);
            }
        }

        $failed_logins = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND event_type = 'login_failed'",
            $date_from
        ));

        $unique_users = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT user_id) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND user_id IS NOT NULL",
            $date_from
        ));

        $unique_ips = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT ip_address) FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp >= %s AND ip_address IS NOT NULL",
            $date_from
        ));
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

        return [
            'total_events' => intval($total_events),
            'security_events' => intval($security_events),
            'login_events' => intval($login_events),
            'content_events' => intval($content_events),
            'system_events' => intval($system_events),
            'failed_logins' => intval($failed_logins),
            'unique_users' => intval($unique_users),
            'unique_ips' => intval($unique_ips),
        ];
    }

    /**
     * Cleanup old logs based on retention settings
     */
    public function cleanup_old_logs(): void {
        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';

        if (!$this->table_exists($table_name)) {
            return;
        }

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            return;
        }

        $total_deleted = 0;

        // 1. Clean up by retention period (time-based cleanup)
        $settings = get_option('guard_dog_activity_log_settings', []);
        $retention_days = intval($settings['retention_days'] ?? 90);

        if ($retention_days > 0) {
            $cutoff_date = gmdate('Y-m-d H:i:s', strtotime("-{$retention_days} days"));
            
            // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            // Direct database query is necessary for cleanup operations to ensure immediate data removal
            // Caching is not appropriate for cleanup operations as they modify the database
            $deleted_by_age = $wpdb->query($wpdb->prepare(
                "DELETE FROM `{$wpdb->prefix}guard_dog_logs` WHERE timestamp < %s",
                $cutoff_date
            ));
            
            if ($deleted_by_age !== false) {
                $total_deleted += intval($deleted_by_age);
                if ($deleted_by_age > 0) {
                    Guard_Dog()->debug->info("Guard Dog: Cleaned up {$deleted_by_age} old activity log entries older than {$retention_days} days.");
                }
            }
        }

        // 2. Clean up by maximum entries limit (count-based cleanup)
        $max_entries = intval(get_option('guard_dog_max_log_entries', 10000));
        
        if ($max_entries > 0) {
            // Get current count
            $current_count = intval($wpdb->get_var("SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs`"));
            
            if ($current_count > $max_entries) {
                $excess_entries = $current_count - $max_entries;
                
                // Delete oldest entries beyond the limit
                $deleted_by_limit = $wpdb->query($wpdb->prepare(
                    "DELETE FROM `{$wpdb->prefix}guard_dog_logs` 
                     WHERE id IN (
                         SELECT id FROM (
                             SELECT id FROM `{$wpdb->prefix}guard_dog_logs` 
                             ORDER BY timestamp ASC 
                             LIMIT %d
                         ) AS oldest_entries
                     )",
                    $excess_entries
                ));
                
                if ($deleted_by_limit !== false) {
                    $total_deleted += intval($deleted_by_limit);
                    if ($deleted_by_limit > 0) {
                        Guard_Dog()->debug->info("Guard Dog: Cleaned up {$deleted_by_limit} excess activity log entries to maintain maximum of {$max_entries} entries.");
                    }
                }
            }
        }
        
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

        if ($total_deleted > 0) {
            Guard_Dog()->debug->info("Guard Dog: Total cleanup completed. Removed {$total_deleted} activity log entries.");
        }
    }

    /**
     * Clean up excess entries based on maximum entries limit only
     * This is called occasionally during log insertion for real-time enforcement
     */
    private function cleanup_excess_entries(): void {
        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';

        if (!$this->table_exists($table_name)) {
            return;
        }

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            return;
        }

        $max_entries = intval(get_option('guard_dog_max_log_entries', 10000));
        
        if ($max_entries <= 0) {
            return; // No limit set
        }

        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database query is necessary for cleanup operations to ensure immediate data removal
        // Caching is not appropriate for cleanup operations as they modify the database
        
        // Get current count
        $current_count = intval($wpdb->get_var("SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs`"));
        
        if ($current_count > $max_entries) {
            $excess_entries = $current_count - $max_entries;
            
            // Delete oldest entries beyond the limit
            $deleted = $wpdb->query($wpdb->prepare(
                "DELETE FROM `{$wpdb->prefix}guard_dog_logs` 
                 WHERE id IN (
                     SELECT id FROM (
                         SELECT id FROM `{$wpdb->prefix}guard_dog_logs` 
                         ORDER BY timestamp ASC 
                         LIMIT %d
                     ) AS oldest_entries
                 )",
                $excess_entries
            ));
            
            if ($deleted !== false && $deleted > 0) {
                Guard_Dog()->debug->info("Guard Dog: Cleaned up {$deleted} excess activity log entries to maintain maximum of {$max_entries} entries.");
            }
        }
        
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    }

    /**
     * Get user agent string if logging is enabled
     *
     * @return string User agent string or empty string if logging is disabled
     */
    private function get_user_agent_if_enabled(): string {
        $log_user_agents = get_option('guard_dog_log_user_agents', false);
        
        if (!$log_user_agents) {
            return '';
        }
        
        return isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '';
    }

    /**
     * Export logs to CSV
     */
    public function export_to_csv(array $filters = []): string {
        $logs = $this->get_logs(array_merge($filters, ['per_page' => 10000]));
        
        $csv_data = [];
        $csv_data[] = ['Timestamp', 'Event Type', 'Username', 'IP Address', 'Details'];

        foreach ($logs as $log) {
            $details = !empty($log['details']) ? json_decode($log['details'], true) : [];
            $details_string = '';
            
            if (is_array($details)) {
                $formatted_details = [];
                foreach ($details as $key => $value) {
                    if (is_array($value)) {
                        $value = implode(', ', $value);
                    }
                    $formatted_details[] = $key . ': ' . $value;
                }
                $details_string = implode(' | ', $formatted_details);
            }

            $csv_data[] = [
                $log['timestamp'],
                $log['event_type'],
                $log['username'] ?? 'N/A',
                $log['ip_address'] ?? 'N/A',
                $details_string
            ];
        }

        // Create CSV content using string concatenation instead of file operations
        // All data is sanitized before being added to CSV to prevent injection attacks
        $csv_content = '';
        foreach ($csv_data as $row) {
            $escaped_row = array_map(function($field) {
                // Ensure field is a string and sanitize it
                $field = is_string($field) ? $field : (string) $field;
                
                // Escape double quotes and wrap in quotes if needed
                // This follows RFC 4180 CSV escaping rules
                if (strpos($field, '"') !== false || strpos($field, ',') !== false || strpos($field, "\n") !== false || strpos($field, "\r") !== false) {
                    return '"' . str_replace('"', '""', $field) . '"';
                }
                return $field;
            }, $row);
            $csv_content .= implode(',', $escaped_row) . "\n";
        }

        return $csv_content;
    }

    /**
     * Check if table exists
     */
    private function table_exists(string $table_name): bool {
        global $wpdb;
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database query is necessary to check if our custom table exists
        // Caching is not appropriate for table existence checks as tables may be created/deleted
        $result = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name));
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        return $result === $table_name;
    }

    // ===== ADDITIONAL EVENT HANDLERS =====

    /**
     * Log menu events
     */
    public function log_menu_created(int $menu_id, array $menu_data): void {
        $this->add_log_entry('menu_created', [
            'object_id' => $menu_id,
            'object_type' => 'nav_menu',
            'details' => [
                'menu_name' => $menu_data['menu-name'] ?? 'Unknown',
            ]
        ]);
    }

    public function log_menu_updated(int $menu_id): void {
        $menu = wp_get_nav_menu_object($menu_id);
        $this->add_log_entry('menu_updated', [
            'object_id' => $menu_id,
            'object_type' => 'nav_menu',
            'details' => [
                'menu_name' => $menu ? $menu->name : 'Unknown',
            ]
        ]);
    }

    public function log_menu_deleted(int $menu_id): void {
        $menu = wp_get_nav_menu_object($menu_id);
        $this->add_log_entry('menu_deleted', [
            'object_id' => $menu_id,
            'object_type' => 'nav_menu',
            'details' => [
                'menu_name' => $menu ? $menu->name : 'Unknown',
            ]
        ]);
    }

    /**
     * Setup widget monitoring
     */
    public function setup_widget_monitoring(): void {
        global $wp_registered_widgets, $wp_registered_sidebars;
        
        // Monitor widget changes through options updates
        add_action('updated_option', function($option_name, $old_value, $value) {
            if (strpos($option_name, 'widget_') === 0) {
                $this->log_widget_change($option_name, $old_value, $value);
            }
        }, 10, 3);
    }

    /**
     * Log widget changes
     */
    private function log_widget_change(string $option_name, $old_value, $new_value): void {
        // Simple widget change detection
        if (json_encode($old_value) !== json_encode($new_value)) {
            $this->add_log_entry('widget_updated', [
                'details' => [
                    'widget_type' => str_replace('widget_', '', $option_name),
                    'changes_detected' => true,
                ]
            ]);
        }
    }

    /**
     * Log option updates (for settings changes)
     */
    public function log_option_updated(string $option_name, $old_value, $value): void {
        // Only log important WordPress settings, not every option
        $tracked_options = [
            'blogname', 'blogdescription', 'admin_email', 'start_of_week',
            'use_balanceTags', 'use_smilies', 'require_name_email', 'comments_notify',
            'posts_per_page', 'date_format', 'time_format', 'links_updated_date_format',
            'comment_moderation', 'moderation_notify', 'permalink_structure',
            'category_base', 'tag_base'
        ];

        if (in_array($option_name, $tracked_options) && $old_value !== $value) {
            $this->add_log_entry('settings_updated', [
                'details' => [
                    'option_name' => $option_name,
                    'old_value' => is_array($old_value) ? json_encode($old_value) : $old_value,
                    'new_value' => is_array($value) ? json_encode($value) : $value,
                ]
            ]);
        }
    }

    /**
     * Log comment events
     */
    public function log_comment_created(int $comment_id, \WP_Comment $comment_data): void {
        // Use the passed WP_Comment object directly instead of fetching again
        $comment = $comment_data;

        $this->add_log_entry('comment_created', [
            'object_id' => $comment_id,
            'object_type' => 'comment',
            'details' => [
                'comment_author' => $comment->comment_author,
                'comment_post_ID' => $comment->comment_post_ID,
                'post_title' => get_the_title($comment->comment_post_ID),
                'comment_approved' => $comment->comment_approved,
            ]
        ]);
    }

    public function log_comment_status_changed(int $comment_id, string $comment_status): void {
        $comment = get_comment($comment_id);
        if (!$comment) return;

        $event_type = 'comment_updated';
        if ($comment_status === 'approve') {
            $event_type = 'comment_approved';
        } elseif ($comment_status === 'spam') {
            $event_type = 'comment_spam';
        }

        $this->add_log_entry($event_type, [
            'object_id' => $comment_id,
            'object_type' => 'comment',
            'details' => [
                'comment_author' => $comment->comment_author,
                'comment_post_ID' => $comment->comment_post_ID,
                'post_title' => get_the_title($comment->comment_post_ID),
                'new_status' => $comment_status,
            ]
        ]);
    }

    /**
     * Log when a user profile is updated (profile_update action)
     *
     * @param int $user_id
     * @param WP_User $old_user_data
     */
    public function log_user_updated($user_id, $old_user_data) {
        // Basic log entry for now; can be expanded with more detail later
        $this->add_log_entry('user_updated', [
            'user_id' => $user_id,
            'old_user_data' => is_object($old_user_data) ? $old_user_data->user_login : '',
        ]);
    }

    /**
     * Get total number of log entries
     */
    public function get_total_logs_count(): int {
        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';
        
        if (!$this->table_exists($table_name)) {
            return 0;
        }

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            return 0;
        }
        
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database query is necessary for activity log count to ensure real-time data
        // Caching is not appropriate for security event counts as data may be updated frequently
        $count = $wpdb->get_var("SELECT COUNT(*) FROM `{$wpdb->prefix}guard_dog_logs`");
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        return intval($count);
    }

    /**
     * Get the oldest log entry
     */
    public function get_oldest_log(): ?array {
        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';
        
        if (!$this->table_exists($table_name)) {
            return null;
        }

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            return null;
        }
        
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database query is necessary for activity log retrieval to ensure real-time data
        // Caching is not appropriate for security event logs as data may be updated frequently
        $oldest = $wpdb->get_row(
            "SELECT * FROM `{$wpdb->prefix}guard_dog_logs` ORDER BY timestamp ASC LIMIT 1",
            ARRAY_A
        );
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        
        return $oldest ?: null;
    }

    /**
     * Get the size of the activity log table
     */
    public function get_table_size(): int {
        global $wpdb;
        $table_name = $wpdb->prefix . 'guard_dog_logs';
        
        if (!$this->table_exists($table_name)) {
            return 0;
        }

        // Validate table name to prevent injection
        if ($table_name !== $wpdb->prefix . 'guard_dog_logs') {
            return 0;
        }
        
        $escaped_table_name = esc_sql($table_name);
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        // Direct database query is necessary for table size calculation to ensure real-time data
        // Caching is not appropriate for table size as it may change frequently
        $size = $wpdb->get_var($wpdb->prepare("
            SELECT SUM(data_length + index_length) 
            FROM information_schema.tables 
            WHERE table_schema = DATABASE() 
            AND table_name = %s
        ", $table_name));
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

        return intval($size);
    }

    // ===== WOOCOMMERCE EVENT HANDLERS =====

    /**
     * Log WooCommerce product creation
     */
    public function log_wc_product_created(int $product_id): void {
        // Prevent recursive calls
        $event_key = 'wc_product_created_' . $product_id;
        if (isset(self::$processing_events[$event_key])) {
            return;
        }
        self::$processing_events[$event_key] = true;

        $product = wc_get_product($product_id);
        if (!$product) {
            unset(self::$processing_events[$event_key]);
            return;
        }

        $this->add_log_entry('wc_product_created', [
            'object_id' => $product_id,
            'object_type' => 'wc_product',
            'details' => [
                'product_name' => $product->get_name(),
                'product_type' => $product->get_type(),
                'sku' => $product->get_sku(),
                'price' => $product->get_price(),
            ]
        ]);

        unset(self::$processing_events[$event_key]);
    }

    /**
     * Log WooCommerce product update
     */
    public function log_wc_product_updated(int $product_id, $product): void {
        if (!$product || !is_a($product, 'WC_Product')) return;

        $this->add_log_entry('wc_product_updated', [
            'object_id' => $product_id,
            'object_type' => 'wc_product',
            'details' => [
                'product_name' => $product->get_name(),
                'product_type' => $product->get_type(),
                'sku' => $product->get_sku(),
            ]
        ]);
    }

    /**
     * Log WooCommerce product deletion
     */
    public function log_wc_product_deleted(int $post_id): void {
        $post = get_post($post_id);
        if (!$post || $post->post_type !== 'product') return;

        $product = wc_get_product($post_id);
        $product_name = $product ? $product->get_name() : $post->post_title;

        $this->add_log_entry('wc_product_deleted', [
            'object_id' => $post_id,
            'object_type' => 'wc_product',
            'details' => [
                'product_name' => $product_name,
            ]
        ]);
    }

    /**
     * Log WooCommerce product trashed
     */
    public function log_wc_product_trashed(int $post_id): void {
        $post = get_post($post_id);
        if (!$post || $post->post_type !== 'product') return;

        $product = wc_get_product($post_id);
        if (!$product) return;

        $this->add_log_entry('wc_product_trashed', [
            'object_id' => $post_id,
            'object_type' => 'wc_product',
            'details' => [
                'product_name' => $product->get_name(),
            ]
        ]);
    }

    /**
     * Log WooCommerce product restored
     */
    public function log_wc_product_restored(int $post_id): void {
        $post = get_post($post_id);
        if (!$post || $post->post_type !== 'product') return;

        $product = wc_get_product($post_id);
        if (!$product) return;

        $this->add_log_entry('wc_product_restored', [
            'object_id' => $post_id,
            'object_type' => 'wc_product',
            'details' => [
                'product_name' => $product->get_name(),
            ]
        ]);
    }

    /**
     * Log WooCommerce product stock change
     */
    public function log_wc_product_stock_changed($product): void {
        if (!$product || !is_a($product, 'WC_Product')) return;

        $this->add_log_entry('wc_product_stock_changed', [
            'object_id' => $product->get_id(),
            'object_type' => 'wc_product',
            'details' => [
                'product_name' => $product->get_name(),
                'stock_quantity' => $product->get_stock_quantity(),
                'stock_status' => $product->get_stock_status(),
            ]
        ]);
    }

    /**
     * Log WooCommerce order creation
     */
    public function log_wc_order_created(int $order_id): void {
        $order = wc_get_order($order_id);
        if (!$order) return;

        $this->add_log_entry('wc_order_created', [
            'object_id' => $order_id,
            'object_type' => 'wc_order',
            'details' => [
                'order_number' => $order->get_order_number(),
                'order_total' => $order->get_total(),
                'order_status' => $order->get_status(),
                'customer_email' => $order->get_billing_email(),
            ]
        ]);
    }

    /**
     * Log WooCommerce order status change
     */
    public function log_wc_order_status_changed(int $order_id, string $old_status, string $new_status, $order): void {
        if (!$order || !is_a($order, 'WC_Order')) return;

        $this->add_log_entry('wc_order_status_changed', [
            'object_id' => $order_id,
            'object_type' => 'wc_order',
            'details' => [
                'order_number' => $order->get_order_number(),
                'old_status' => $old_status,
                'new_status' => $new_status,
                'order_total' => $order->get_total(),
            ]
        ]);
    }

    /**
     * Log WooCommerce order deletion
     */
    public function log_wc_order_deleted(int $post_id): void {
        $post = get_post($post_id);
        if (!$post || !in_array($post->post_type, ['shop_order', 'shop_order_placehold'])) return;

        $order = wc_get_order($post_id);
        $order_number = $order ? $order->get_order_number() : $post_id;

        $this->add_log_entry('wc_order_deleted', [
            'object_id' => $post_id,
            'object_type' => 'wc_order',
            'details' => [
                'order_number' => $order_number,
            ]
        ]);
    }

    /**
     * Log WooCommerce order refund
     */
    public function log_wc_order_refunded(int $order_id, int $refund_id): void {
        $order = wc_get_order($order_id);
        $refund = wc_get_order($refund_id);

        if (!$order || !$refund) return;

        $this->add_log_entry('wc_order_refunded', [
            'object_id' => $order_id,
            'object_type' => 'wc_order',
            'details' => [
                'order_number' => $order->get_order_number(),
                'refund_amount' => $refund->get_amount(),
                'refund_reason' => $refund->get_reason(),
            ]
        ]);
    }

    /**
     * Log WooCommerce order note added
     */
    public function log_wc_order_note_added(array $note_data): void {
        $order_id = isset($note_data['order_id']) ? $note_data['order_id'] : 0;
        $order = wc_get_order($order_id);

        if (!$order) return;

        // Only log admin/customer notes, not system notes
        if (isset($note_data['is_customer_note']) && $note_data['is_customer_note']) {
            $note_type = 'Customer Note';
        } elseif (empty($note_data['is_customer_note'])) {
            $note_type = 'Private Note';
        } else {
            return; // Skip system notes
        }

        $this->add_log_entry('wc_order_note_added', [
            'object_id' => $order_id,
            'object_type' => 'wc_order',
            'details' => [
                'order_number' => $order->get_order_number(),
                'note_type' => $note_type,
                'note_content' => isset($note_data['comment_content']) ? substr($note_data['comment_content'], 0, 100) : '',
            ]
        ]);
    }

    /**
     * Log WooCommerce coupon creation
     */
    public function log_wc_coupon_created(int $coupon_id): void {
        $coupon = new \WC_Coupon($coupon_id);
        if (!$coupon) return;

        $this->add_log_entry('wc_coupon_created', [
            'object_id' => $coupon_id,
            'object_type' => 'wc_coupon',
            'details' => [
                'coupon_code' => $coupon->get_code(),
                'discount_type' => $coupon->get_discount_type(),
                'amount' => $coupon->get_amount(),
            ]
        ]);
    }

    /**
     * Log WooCommerce coupon update
     */
    public function log_wc_coupon_updated(int $coupon_id, $coupon): void {
        if (!$coupon || !is_a($coupon, 'WC_Coupon')) return;

        $this->add_log_entry('wc_coupon_updated', [
            'object_id' => $coupon_id,
            'object_type' => 'wc_coupon',
            'details' => [
                'coupon_code' => $coupon->get_code(),
                'discount_type' => $coupon->get_discount_type(),
                'amount' => $coupon->get_amount(),
            ]
        ]);
    }

    /**
     * Log WooCommerce coupon deletion
     */
    public function log_wc_coupon_deleted(int $post_id): void {
        $post = get_post($post_id);
        if (!$post || $post->post_type !== 'shop_coupon') return;

        $this->add_log_entry('wc_coupon_deleted', [
            'object_id' => $post_id,
            'object_type' => 'wc_coupon',
            'details' => [
                'coupon_code' => $post->post_title,
            ]
        ]);
    }

    /**
     * Log WooCommerce product category creation
     */
    public function log_wc_product_cat_created(int $term_id, int $tt_id): void {
        // Prevent recursive calls
        $event_key = 'wc_product_cat_created_' . $term_id;
        if (isset(self::$processing_events[$event_key])) {
            return;
        }
        self::$processing_events[$event_key] = true;

        $term = get_term($term_id, 'product_cat');
        if (!$term || is_wp_error($term)) {
            unset(self::$processing_events[$event_key]);
            return;
        }

        $this->add_log_entry('wc_product_cat_created', [
            'object_id' => $term_id,
            'object_type' => 'wc_product_cat',
            'details' => [
                'category_name' => $term->name,
                'slug' => $term->slug,
            ]
        ]);

        unset(self::$processing_events[$event_key]);
    }

    /**
     * Log WooCommerce product category update
     */
    public function log_wc_product_cat_updated(int $term_id, int $tt_id): void {
        $term = get_term($term_id, 'product_cat');
        if (!$term || is_wp_error($term)) return;

        $this->add_log_entry('wc_product_cat_updated', [
            'object_id' => $term_id,
            'object_type' => 'wc_product_cat',
            'details' => [
                'category_name' => $term->name,
                'slug' => $term->slug,
            ]
        ]);
    }

    /**
     * Log WooCommerce product category deletion
     */
    public function log_wc_product_cat_deleted(int $term_id, int $tt_id, string $taxonomy, $deleted_term): void {
        if ($taxonomy !== 'product_cat') return;

        $cat_name = is_object($deleted_term) && isset($deleted_term->name) ? $deleted_term->name : 'Unknown';

        $this->add_log_entry('wc_product_cat_deleted', [
            'object_id' => $term_id,
            'object_type' => 'wc_product_cat',
            'details' => [
                'category_name' => $cat_name,
            ]
        ]);
    }

    /**
     * Log WooCommerce settings update
     */
    public function log_wc_settings_updated(): void {
        // Get current tab/section if available
        $current_tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'general';
        $current_section = isset($_GET['section']) ? sanitize_text_field(wp_unslash($_GET['section'])) : '';

        $this->add_log_entry('wc_settings_updated', [
            'object_type' => 'wc_settings',
            'details' => [
                'settings_tab' => $current_tab,
                'settings_section' => $current_section,
            ]
        ]);
    }

    /**
     * Log WooCommerce payment gateway toggled
     */
    public function log_wc_payment_gateway_toggled($option): void {
        // Only log payment gateway enabled/disabled changes
        if (!is_array($option) || !isset($option['id'])) return;

        // Check if this is a payment gateway option
        if (strpos($option['id'], 'woocommerce_') === 0 && strpos($option['id'], '_settings') !== false) {
            $gateway_id = str_replace(['woocommerce_', '_settings'], '', $option['id']);

            $this->add_log_entry('wc_payment_gateway_toggled', [
                'object_type' => 'wc_payment_gateway',
                'details' => [
                    'gateway_id' => $gateway_id,
                ]
            ]);
        }
    }

    /**
     * Log WooCommerce shipping zone creation
     */
    public function log_wc_shipping_zone_created(int $zone_id, array $zone_data): void {
        $this->add_log_entry('wc_shipping_zone_created', [
            'object_id' => $zone_id,
            'object_type' => 'wc_shipping_zone',
            'details' => [
                'zone_name' => isset($zone_data['zone_name']) ? $zone_data['zone_name'] : 'Unknown',
            ]
        ]);
    }

    /**
     * Log WooCommerce shipping zone update
     */
    public function log_wc_shipping_zone_updated(int $zone_id, array $zone_data): void {
        $this->add_log_entry('wc_shipping_zone_updated', [
            'object_id' => $zone_id,
            'object_type' => 'wc_shipping_zone',
            'details' => [
                'zone_name' => isset($zone_data['zone_name']) ? $zone_data['zone_name'] : 'Unknown',
            ]
        ]);
    }

    /**
     * Log WooCommerce shipping zone deletion
     */
    public function log_wc_shipping_zone_deleted(int $zone_id): void {
        $this->add_log_entry('wc_shipping_zone_deleted', [
            'object_id' => $zone_id,
            'object_type' => 'wc_shipping_zone',
            'details' => [
                'zone_id' => $zone_id,
            ]
        ]);
    }

    /**
     * Log WooCommerce tax rate addition
     */
    public function log_wc_tax_rate_added(int $tax_rate_id, array $tax_rate): void {
        $this->add_log_entry('wc_tax_rate_added', [
            'object_id' => $tax_rate_id,
            'object_type' => 'wc_tax_rate',
            'details' => [
                'tax_rate_country' => isset($tax_rate['tax_rate_country']) ? $tax_rate['tax_rate_country'] : '',
                'tax_rate_state' => isset($tax_rate['tax_rate_state']) ? $tax_rate['tax_rate_state'] : '',
                'tax_rate' => isset($tax_rate['tax_rate']) ? $tax_rate['tax_rate'] : '',
                'tax_rate_name' => isset($tax_rate['tax_rate_name']) ? $tax_rate['tax_rate_name'] : '',
            ]
        ]);
    }

    /**
     * Log WooCommerce tax rate update
     */
    public function log_wc_tax_rate_updated(int $tax_rate_id, array $tax_rate): void {
        $this->add_log_entry('wc_tax_rate_updated', [
            'object_id' => $tax_rate_id,
            'object_type' => 'wc_tax_rate',
            'details' => [
                'tax_rate_country' => isset($tax_rate['tax_rate_country']) ? $tax_rate['tax_rate_country'] : '',
                'tax_rate_state' => isset($tax_rate['tax_rate_state']) ? $tax_rate['tax_rate_state'] : '',
                'tax_rate' => isset($tax_rate['tax_rate']) ? $tax_rate['tax_rate'] : '',
                'tax_rate_name' => isset($tax_rate['tax_rate_name']) ? $tax_rate['tax_rate_name'] : '',
            ]
        ]);
    }

    /**
     * Log WooCommerce tax rate deletion
     */
    public function log_wc_tax_rate_deleted(int $tax_rate_id): void {
        $this->add_log_entry('wc_tax_rate_deleted', [
            'object_id' => $tax_rate_id,
            'object_type' => 'wc_tax_rate',
            'details' => [
                'tax_rate_id' => $tax_rate_id,
            ]
        ]);
    }

} 
