<?php
/**
 * Plugin Name: Sentinel - WordPress Activity Logger
 * Plugin URI: http://www.getsentinel.dev/
 * Description: Comprehensive WordPress activity logging and monitoring system. Track user actions, system events, and security incidents with detailed reporting and real-time monitoring.
 * Version: 1.0.0
 * Author: JPSNT Development Team
 * Author URI: http://www.getsentinel.dev/
 * License: GPL v2 or later
 * Text Domain: sentinel
 * Domain Path: /languages
 * Requires at least: 5.0
 * Tested up to: 6.4
 * Requires PHP: 7.4
 */

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

// Define plugin constants
define('SENTINEL_VERSION', '1.0.0');
define('SENTINEL_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SENTINEL_PLUGIN_URL', plugin_dir_url(__FILE__));
define('SENTINEL_PLUGIN_BASENAME', plugin_basename(__FILE__));

// Include required files
require_once SENTINEL_PLUGIN_DIR . 'includes/class-sentinel-migration.php';
require_once SENTINEL_PLUGIN_DIR . 'includes/class-sentinel-core.php';
require_once SENTINEL_PLUGIN_DIR . 'includes/class-sentinel-events.php';
require_once SENTINEL_PLUGIN_DIR . 'includes/class-sentinel-logger.php';
require_once SENTINEL_PLUGIN_DIR . 'admin/class-sentinel-admin.php';
require_once SENTINEL_PLUGIN_DIR . 'includes/class-sentinel-cleanup.php';
require_once SENTINEL_PLUGIN_DIR . 'includes/class-sentinel-digest-reports.php';
require_once SENTINEL_PLUGIN_DIR . 'includes/class-sentinel-email-templates.php';
require_once SENTINEL_PLUGIN_DIR . 'includes/class-sentinel-privacy.php';



/**
 * Test function to verify disabled events functionality
 */
function sentinel_test_disabled_events() {
    // Get all registered events
    $registered_events = array();
    if (class_exists('Sentinel_Events')) {
        $registered_events = Sentinel_Events::get_all_events();
    }
    
    // Get disabled events
    $disabled_events = get_option('sentinel_disabled_events', array());
    
    // Dump to error log
    error_log('=== SENTINEL EVENT REGISTRY DEBUG ===');
    error_log('Total registered events: ' . count($registered_events));
    error_log('Total disabled events: ' . count($disabled_events));
    error_log('');
    
    if (empty($registered_events)) {
        error_log('⚠️  NO EVENTS REGISTERED! This might be why logging is failing.');
        error_log('Events are registered in sentinel_register_default_events() function');
    } else {
        error_log('📋 REGISTERED EVENTS:');
        foreach ($registered_events as $event_key => $config) {
            $is_disabled = in_array($event_key, $disabled_events);
            $status = $is_disabled ? '🔴 DISABLED' : '🟢 ENABLED';
            error_log("  {$event_key}: {$status} [{$config['category']}] - {$config['description']}");
        }
    }
    
    error_log('');
    if (!empty($disabled_events)) {
        error_log('🚫 DISABLED EVENTS LIST:');
        foreach ($disabled_events as $disabled_event) {
            error_log("  - {$disabled_event}");
        }
    } else {
        error_log('✅ No events are disabled - all events will be logged');
    }
    
    error_log('');
    error_log('🔧 DEBUGGING INFO:');
    error_log('Sentinel_Events class exists: ' . (class_exists('Sentinel_Events') ? 'YES' : 'NO'));
    error_log('sentinel_log_event function exists: ' . (function_exists('sentinel_log_event') ? 'YES' : 'NO'));
    error_log('Current user ID: ' . get_current_user_id());
    error_log('Is admin: ' . (is_admin() ? 'YES' : 'NO'));
    error_log('=== END SENTINEL DEBUG ===');
    
    // Return simple results for display
    return array(
        'enabled_test' => array(
            'logged' => true,
            'passed' => true,
            'function_result' => true,
            'event_used' => 'Debug info logged'
        ),
        'disabled_test' => array(
            'logged' => false,
            'passed' => true,
            'function_result' => true,
            'event_used' => 'Check error log'
        ),
        'summary' => array(
            'total_tests' => 2,
            'passed' => 2,
            'all_passed' => true
        )
    );
}

// Simple debug function
function sentinel_debug($message) {
    if (defined('WP_DEBUG') && WP_DEBUG) {
        error_log('[Sentinel] ' . $message);
    }
}

/**
 * Check if a user's role is excluded from logging
 *
 * @param int|null $user_id User ID to check (null for current user)
 * @return bool True if user role is excluded, false otherwise
 */
function sentinel_is_user_role_excluded($user_id = null) {
    // Get excluded user roles from settings
    $settings = get_option('sentinel_log_management', array());
    $excluded_roles = isset($settings['excluded_user_roles']) ? $settings['excluded_user_roles'] : array();
    
    // If no roles are excluded, don't exclude anyone
    if (empty($excluded_roles)) {
        return false;
    }
    
    // If no user ID provided, use current user
    if ($user_id === null) {
        $user_id = get_current_user_id();
    }
    
    // If still no user ID (not logged in), don't exclude
    if (!$user_id) {
        return false;
    }
    
    // Get user data
    $user = get_userdata($user_id);
    if (!$user) {
        return false; // User doesn't exist, don't exclude
    }
    
    // Check if any of the user's roles are in the excluded list
    $user_roles = $user->roles;
    foreach ($user_roles as $role) {
        if (in_array($role, $excluded_roles)) {
            return true; // User has an excluded role
        }
    }
    
    return false; // User doesn't have any excluded roles
}

/**
 * Fallback logging when database logging fails
 * Uses WordPress error_log and admin notices as backup
 */
function sentinel_fallback_log($event_key, $data = array(), $user_id = null) {
    // Log to WordPress error log
    $message = sprintf(
        '[SENTINEL FALLBACK] %s: %s (User: %d, URL: %s)',
        strtoupper($event_key),
        isset($data['error_message']) ? $data['error_message'] : json_encode($data),
        $user_id ?: get_current_user_id(),
        $_SERVER['REQUEST_URI'] ?? 'Unknown'
    );
    
    error_log($message);
    
    // Store in WordPress transient for admin display
    $fallback_logs = get_transient('sentinel_fallback_logs') ?: array();
    $fallback_logs[] = array(
        'event_key' => $event_key,
        'message' => $message,
        'timestamp' => current_time('mysql'),
        'data' => $data
    );
    
    // Keep only last 10 fallback logs
    $fallback_logs = array_slice($fallback_logs, -10);
    set_transient('sentinel_fallback_logs', $fallback_logs, HOUR_IN_SECONDS);
    
    // Add admin notice for critical errors
    if (is_admin() && in_array($event_key, array('wp_database_error', 'php_fatal_error'))) {
        add_action('admin_notices', function() use ($event_key, $data) {
            echo '<div class="notice notice-error"><p>';
            echo '<strong>Sentinel Alert:</strong> ';
            echo esc_html($event_key . ' - ' . (isset($data['error_message']) ? $data['error_message'] : 'Unknown error'));
            echo '</p></div>';
        });
    }
}

// Initialize the plugin
function sentinel_init() {
    // Check if database needs updating
    Sentinel_Migration::check_version();
    
    // Initialize admin functionality using singleton pattern
    if (is_admin()) {
        $admin = Sentinel_Admin::get_instance();
        $admin->init();
    }
    
    // Initialize cleanup functionality
    if (class_exists('Sentinel_Cleanup')) {
        Sentinel_Cleanup::init();
    }
    
    // Initialize logger to set up batch logging cron hooks
    if (class_exists('Sentinel_Logger')) {
        new Sentinel_Logger();
    }
    
    // Initialize digest reports functionality
    if (class_exists('Sentinel_Digest_Reports')) {
        Sentinel_Digest_Reports::init();
    }
    
    // Initialize privacy functionality
    if (class_exists('Sentinel_Privacy')) {
        new Sentinel_Privacy();
    }
    
    // Ensure batch logging cron is scheduled if enabled
    $settings = get_option('sentinel_log_management', array());
    if (!empty($settings['batch_logging_enabled'])) {
        // Check if the cron job is scheduled, if not schedule it
        if (!wp_next_scheduled('sentinel_process_log_queue')) {
            sentinel_update_batch_logging_schedule();
        }
    }
    
    // Set up cleanup cron hooks
    add_action('sentinel_cleanup_logs', 'sentinel_run_cleanup_cron');
    add_action('sentinel_optimize_database', 'sentinel_run_optimization_cron');
    
    // Set up batch logging cron hook
    add_action('sentinel_process_log_queue', 'sentinel_run_batch_processing_cron');
    
    // Add custom cron interval for batch processing
    add_filter('cron_schedules', 'sentinel_add_batch_cron_interval');
    
    // Set up error logging
    sentinel_setup_php_error_handler();
    
    // Set up database error logging
    add_action('wp_loaded', 'sentinel_setup_db_error_logging');
    
    // Set up hooks for event logging
    add_action('wp_login', 'sentinel_log_user_login', 10, 2);
    add_action('wp_logout', 'sentinel_log_user_logout');
    add_action('user_register', 'sentinel_log_user_registered');
    add_action('profile_update', 'sentinel_log_profile_updated');
    add_action('transition_post_status', 'sentinel_log_post_published', 10, 3);
    add_action('before_delete_post', 'sentinel_log_post_deleted');
    add_action('comment_post', 'sentinel_log_comment_posted', 10, 2);
    add_action('comment_unapproved_to_approved', 'sentinel_log_comment_approved');
    add_action('delete_comment', 'sentinel_log_comment_deleted');
    add_action('activated_plugin', 'sentinel_log_plugin_activated');
    add_action('deactivated_plugin', 'sentinel_log_plugin_deactivated');
    add_action('wp_login_failed', 'sentinel_log_login_failed');
    add_action('auth_cookie_bad', 'sentinel_log_bad_auth_cookie');
    add_action('wp_insert_post_data', 'sentinel_check_db_errors_on_post', 10, 2);
    add_action('wp_handle_upload_prefilter', 'sentinel_check_upload_errors');
    add_action('activated_plugin', 'sentinel_check_plugin_activation_errors');
    add_filter('wp_die_handler', 'sentinel_wp_die_handler');
    add_action('init', 'sentinel_check_http_errors');
    add_action('wp_cron_fail', 'sentinel_log_cron_errors');
    add_action('shutdown', 'sentinel_check_memory_usage');
}
add_action('plugins_loaded', 'sentinel_init');

// Activation hook
register_activation_hook(__FILE__, 'sentinel_activate');
function sentinel_activate() {
    sentinel_debug('Plugin activated');
    
    // Create database tables
    $migration = new Sentinel_Migration();
    $migration->create_tables();
    
    // Set default options
    Sentinel_Migration::set_default_options();
    
    // Schedule cleanup events
    if (!wp_next_scheduled('sentinel_cleanup_logs')) {
        wp_schedule_event(current_time('timestamp'), 'daily', 'sentinel_cleanup_logs');
    }
    // Schedule anonymization event
    if (!wp_next_scheduled('sentinel_anonymize_logs')) {
        wp_schedule_event(current_time('timestamp'), 'daily', 'sentinel_anonymize_logs');
    }
    // Schedule digest reports
    if (!wp_next_scheduled('sentinel_daily_digest')) {
        wp_schedule_event(current_time('timestamp'), 'daily', 'sentinel_daily_digest');
    }
    if (!wp_next_scheduled('sentinel_weekly_digest')) {
        wp_schedule_event(current_time('timestamp'), 'weekly', 'sentinel_weekly_digest');
    }
    // Schedule batch logging if enabled
    sentinel_update_batch_logging_schedule();
}

// Deactivation hook
register_deactivation_hook(__FILE__, 'sentinel_deactivate');
function sentinel_deactivate() {
    sentinel_debug('Plugin deactivated');
    // Clear scheduled events
    wp_clear_scheduled_hook('sentinel_cleanup_logs');
    wp_clear_scheduled_hook('sentinel_optimize_database');
    wp_clear_scheduled_hook('sentinel_process_log_queue');
    wp_clear_scheduled_hook('sentinel_anonymize_logs');
    wp_clear_scheduled_hook('sentinel_daily_digest');
    wp_clear_scheduled_hook('sentinel_weekly_digest');
}

/**
 * Update cleanup schedule when settings change
 */
function sentinel_update_cleanup_schedule() {
    if (!class_exists('Sentinel_Cleanup')) {
        return;
    }
    
    $cleanup = new Sentinel_Cleanup();
    $cleanup->unschedule_cleanup();
    $cleanup->schedule_cleanup();
}

/**
 * Update batch logging schedule when settings change
 */
function sentinel_update_batch_logging_schedule() {
    $settings = get_option('sentinel_log_management', array());
    
    // Always clear existing batch logging schedule first
    wp_clear_scheduled_hook('sentinel_process_log_queue');
    
    // If batch logging is enabled, set up new schedule
    if (!empty($settings['batch_logging_enabled'])) {
        $frequency = !empty($settings['batch_frequency']) ? intval($settings['batch_frequency']) : 60;
        
        // Ensure we have a valid frequency
        if ($frequency < 30) {
            $frequency = 30; // Minimum 30 seconds
        }
        
        // Schedule the event with safeguards
        $schedule_time = current_time('timestamp') + $frequency;
        $scheduled = wp_schedule_event($schedule_time, 'sentinel_batch_interval', 'sentinel_process_log_queue');
        
        // Log the scheduling attempt
        if ($scheduled === false) {
            error_log('[Sentinel] Failed to schedule batch logging cron job');
        } else {
            error_log('[Sentinel] Batch logging cron job scheduled successfully with frequency: ' . $frequency . ' seconds');
        }
        
        // Verify it was scheduled and is in the future
        $next_run = wp_next_scheduled('sentinel_process_log_queue');
        if ($next_run) {
            if ($next_run > current_time('timestamp')) {
                error_log('[Sentinel] Next batch processing scheduled for: ' . date('Y-m-d H:i:s', $next_run));
            } else {
                error_log('[Sentinel] WARNING: Batch logging scheduled in the past, attempting to reschedule');
                // Clear and reschedule with immediate future time
                wp_clear_scheduled_hook('sentinel_process_log_queue');
                wp_schedule_event(current_time('timestamp') + 60, 'sentinel_batch_interval', 'sentinel_process_log_queue');
            }
        } else {
            error_log('[Sentinel] WARNING: Batch logging cron job was not scheduled despite being enabled');
        }
    } else {
        error_log('[Sentinel] Batch logging disabled - cron job unscheduled');
    }
}

/**
 * Add custom cron interval for batch processing
 */
function sentinel_add_batch_cron_interval($schedules) {
    $settings = get_option('sentinel_log_management', array());
    $frequency = !empty($settings['batch_frequency']) ? intval($settings['batch_frequency']) : 60;
    
    $schedules['sentinel_batch_interval'] = array(
        'interval' => $frequency,
        'display' => sprintf(__('Every %d seconds (Sentinel Batch)', 'sentinel'), $frequency)
    );
    
    return $schedules;
}

/**
 * Update digest report schedules based on settings
 */
function sentinel_update_digest_schedules() {
    $settings = get_option('sentinel_log_management', array());
    
    // Check if any digest notifications are enabled
    $daily_digests = array('sentinel_email_daily_summary', 'sentinel_email_daily_error', 'sentinel_email_daily_user');
    $weekly_digests = array('sentinel_email_weekly_health', 'sentinel_email_weekly_performance', 'sentinel_email_weekly_security');
    
    $daily_enabled = false;
    $weekly_enabled = false;
    
    foreach ($daily_digests as $setting) {
        if (!empty($settings[$setting])) {
            $daily_enabled = true;
            break;
        }
    }
    
    foreach ($weekly_digests as $setting) {
        if (!empty($settings[$setting])) {
            $weekly_enabled = true;
            break;
        }
    }
    
    // Schedule daily digest if enabled
    if ($daily_enabled) {
        if (!wp_next_scheduled('sentinel_daily_digest')) {
            // Schedule for 9:00 AM tomorrow
            $tomorrow_9am = strtotime('tomorrow 9:00 AM');
            wp_schedule_event($tomorrow_9am, 'daily', 'sentinel_daily_digest');
            error_log('[Sentinel] Daily digest scheduled for: ' . date('Y-m-d H:i:s', $tomorrow_9am));
        }
    } else {
        wp_clear_scheduled_hook('sentinel_daily_digest');
        error_log('[Sentinel] Daily digest disabled - cron job unscheduled');
    }
    
    // Schedule weekly digest if enabled
    if ($weekly_enabled) {
        if (!wp_next_scheduled('sentinel_weekly_digest')) {
            // Schedule for 9:00 AM next Monday
            $next_monday_9am = strtotime('next monday 9:00 AM');
            wp_schedule_event($next_monday_9am, 'weekly', 'sentinel_weekly_digest');
            error_log('[Sentinel] Weekly digest scheduled for: ' . date('Y-m-d H:i:s', $next_monday_9am));
        }
    } else {
        wp_clear_scheduled_hook('sentinel_weekly_digest');
        error_log('[Sentinel] Weekly digest disabled - cron job unscheduled');
    }
}

/**
 * Cron callback for log cleanup
 */
function sentinel_run_cleanup_cron() {
    if (!class_exists('Sentinel_Cleanup')) {
        return;
    }
    
    $cleanup = new Sentinel_Cleanup();
    $cleanup->cleanup_logs();
}

/**
 * Cron callback for database optimization
 */
function sentinel_run_optimization_cron() {
    if (!class_exists('Sentinel_Cleanup')) {
        return;
    }
    
    $cleanup = new Sentinel_Cleanup();
    $cleanup->optimize_database();
}

/**
 * Cron callback for batch processing
 */
function sentinel_run_batch_processing_cron() {
    error_log('[Sentinel] Batch processing cron started at ' . date('Y-m-d H:i:s'));
    
    if (!class_exists('Sentinel_Logger')) {
        error_log('[Sentinel] ERROR: Sentinel_Logger class not found in cron callback');
        return;
    }
    
    $logger = new Sentinel_Logger();
    $processed = $logger->process_queue();
    
    error_log('[Sentinel] Batch processing cron completed, processed: ' . $processed . ' items');
    
    // Check if we need to reschedule (important for manual cron execution)
    $next_run = wp_next_scheduled('sentinel_process_log_queue');
    if ($next_run && $next_run <= current_time('timestamp')) {
        error_log('[Sentinel] Detected overdue schedule, forcing reschedule');
        wp_clear_scheduled_hook('sentinel_process_log_queue');
        sentinel_update_batch_logging_schedule();
        $next_run = wp_next_scheduled('sentinel_process_log_queue');
    }
    
    // Log the next scheduled run
    if ($next_run) {
        error_log('[Sentinel] Next batch run scheduled for: ' . date('Y-m-d H:i:s', $next_run));
    } else {
        error_log('[Sentinel] WARNING: No next batch run scheduled after cron execution');
    }
}

// Public API function for logging events
if (!function_exists('sentinel_log_event')) {
    /**
     * Log an event using Sentinel
     *
     * @param string $event_key The event key (must be registered)
     * @param array $data       Additional event data (optional)
     * @param int $user_id      User ID (optional)
     * @return bool             True on success, false on failure
     */
    function sentinel_log_event($event_key, $data = array(), $user_id = null) {
        if (!class_exists('Sentinel_Logger')) {
            return false;
        }
        
        // Check if this event type is disabled
        $disabled_events = get_option('sentinel_disabled_events', array());
        if (in_array($event_key, $disabled_events)) {
            sentinel_debug("Event '{$event_key}' is disabled, skipping logging");
            return false; // Event is disabled, don't log it
        }
        
        // Check if user role is excluded from logging
        if (sentinel_is_user_role_excluded($user_id)) {
            sentinel_debug("Event '{$event_key}' skipped - user role is excluded from logging");
            return false; // User role is excluded, don't log it
        }
        
        sentinel_debug("Event '{$event_key}' is enabled, proceeding with logging");
        
        // Try database logging first
        $logger = new Sentinel_Logger();
        $result = $logger->log($event_key, $data, $user_id);
        
        // If database logging fails, use fallback logging for critical events
        if (!$result && in_array($event_key, array('wp_database_error', 'php_fatal_error', 'wp_config_error'))) {
            sentinel_fallback_log($event_key, $data, $user_id);
        }
        
        // --- BEGIN: Security Email Debug Logging ---
        // Only run if admin_notifications is enabled
        $settings = get_option('sentinel_log_management', array());
        if (!empty($settings['admin_notifications'])) {
            if (class_exists('Sentinel_Events')) {
                $event_config = Sentinel_Events::get_event($event_key);
                if ($event_config) {
                    $is_security = ($event_config['category'] === 'security');
                    $is_critical = ($event_config['priority'] === 'critical');
                    $is_system = ($event_config['category'] === 'system'); // NEW: Notify on system events too
                    // Notify on security, critical, or system events
                    if ($is_security || $is_critical || $is_system) {
                        // Compose debug email
                        $to = isset($settings['notification_email']) ? $settings['notification_email'] : get_option('admin_email');
                        $subject = '[Sentinel Security Alert] ' . ($event_config['label'] ?? $event_key);
                        
                        // Plain text version
                        $body_plain = "A security/critical/system event was logged by Sentinel:\n\n";
                        $body_plain .= "Event: " . ($event_config['label'] ?? $event_key) . "\n";
                        $body_plain .= "Category: " . $event_config['category'] . "\n";
                        $body_plain .= "Priority: " . $event_config['priority'] . "\n";
                        $body_plain .= "User ID: " . ($user_id ?: 'N/A') . "\n";
                        $body_plain .= "Data: " . print_r($data, true) . "\n";
                        $body_plain .= "Time: " . current_time('mysql') . "\n";
                        $body_plain .= "URL: " . ($_SERVER['REQUEST_URI'] ?? 'Unknown') . "\n";
                        
                        // --- Use external HTML template for email body ---
                        $is_notification = false; // Security/system/critical
                        // Set up all required variables for the template
                        // $event_config, $data, $to, $subject, $is_notification, $event_key
                        include SENTINEL_PLUGIN_DIR . 'includes/email-template.php';
                        // $body_html is now available
                        
                        // Send the actual email
                        $headers = array(
                            'Content-Type: text/html; charset=UTF-8',
                            'From: Sentinel <' . get_option('admin_email') . '>'
                        );
                        
                        $sent = wp_mail($to, $subject, $body_html, $headers);
                        
                        if ($sent) {
                            error_log('[Sentinel] Security alert email sent successfully to ' . $to);
                        } else {
                            error_log('[Sentinel] Failed to send security alert email to ' . $to);
                        }
                        
                        // Log both versions to debug.log (only in debug mode)
                        if (defined('WP_DEBUG') && WP_DEBUG) {
                            error_log("[Sentinel Email Debug] To: $to\nSubject: $subject\n\n=== PLAIN TEXT VERSION ===\n$body_plain\n\n=== HTML VERSION (Copy below for preview) ===\n$body_html\n=== END HTML VERSION ===");
                        }
                    }
                }
            }
        }
        // --- END: Security Email Debug Logging ---

        // --- BEGIN: Granular Email Debug Logging ---
        // This block is additive and does NOT affect security notifications
        if (function_exists('sentinel_should_send_granular_email_notification') && class_exists('Sentinel_Events')) {
            $event_config = Sentinel_Events::get_event($event_key);
            if ($event_config && sentinel_should_send_granular_email_notification($event_key, $event_config, $data, $user_id)) {
                // Compose granular debug email (same template for consistency)
                $to = isset($settings['notification_email']) ? $settings['notification_email'] : get_option('admin_email');
                $subject = '[Sentinel Notification] ' . ($event_config['label'] ?? $event_key);
                // Use the same $body_plain and $body_html logic as above
                // (Copy the template code here for consistency)
                $priority_color = '';
                $priority_bg = '';
                switch ($event_config['priority']) {
                    case 'critical': $priority_color = '#dc2626'; $priority_bg = '#fef2f2'; break;
                    case 'high': $priority_color = '#ea580c'; $priority_bg = '#fff7ed'; break;
                    case 'medium': $priority_color = '#ca8a04'; $priority_bg = '#fefce8'; break;
                    default: $priority_color = '#2563eb'; $priority_bg = '#eff6ff';
                }
                $category_color = '';
                switch ($event_config['category']) {
                    case 'security': $category_color = '#dc2626'; break;
                    case 'system': $category_color = '#059669'; break;
                    default: $category_color = '#6b7280';
                }
                $body_plain = "A Sentinel event notification was triggered:\n\n";
                $body_plain .= "Event: " . ($event_config['label'] ?? $event_key) . "\n";
                $body_plain .= "Category: " . $event_config['category'] . "\n";
                $body_plain .= "Priority: " . $event_config['priority'] . "\n";
                $body_plain .= "User ID: " . (get_current_user_id() ?: 'N/A') . "\n";
                $body_plain .= "Data: " . print_r($data, true) . "\n";
                $body_plain .= "Time: " . current_time('mysql') . "\n";
                // --- Use external HTML template for email body (granular) ---
                $is_notification = true; // Granular notification
                // $event_config, $data, $to, $subject, $is_notification, $event_key
                include SENTINEL_PLUGIN_DIR . 'includes/email-template.php';
                // $body_html is now available
                
                // Send the actual email
                $headers = array(
                    'Content-Type: text/html; charset=UTF-8',
                    'From: Sentinel <' . get_option('admin_email') . '>'
                );
                
                $sent = wp_mail($to, $subject, $body_html, $headers);
                
                if ($sent) {
                    error_log('[Sentinel] Granular notification email sent successfully to ' . $to);
                } else {
                    error_log('[Sentinel] Failed to send granular notification email to ' . $to);
                }
                
                // Log both versions to debug.log (only in debug mode)
                if (defined('WP_DEBUG') && WP_DEBUG) {
                    error_log("[Sentinel Email Debug] To: $to\nSubject: $subject\n\n=== PLAIN TEXT VERSION ===\n$body_plain\n\n=== HTML VERSION (Copy below for preview) ===\n$body_html\n=== END HTML VERSION ===");
                }
            }
        }
        // --- END: Granular Email Debug Logging ---
        
        return $result;
    }
}

// Public API function for registering events
if (!function_exists('sentinel_register_event')) {
    /**
     * Register a custom event type
     *
     * @param string $event_key The event key
     * @param array $config     Event configuration
     * @return bool             True on success, false on failure
     */
    function sentinel_register_event($event_key, $config = array()) {
        if (!class_exists('Sentinel_Events')) {
            return false;
        }
        return Sentinel_Events::register_event($event_key, $config);
    }
}

// Register default WordPress events
add_action('init', 'sentinel_register_default_events');
function sentinel_register_default_events() {
    // Authentication events
    sentinel_register_event('user_login', array(
        'label' => 'User Login',
        'category' => 'authentication',
        'priority' => 'low',
        'description' => 'User logged in successfully'
    ));
    
    sentinel_register_event('user_logout', array(
        'label' => 'User Logout',
        'category' => 'authentication',
        'priority' => 'low',
        'description' => 'User logged out'
    ));
    
    sentinel_register_event('user_registered', array(
        'label' => 'User Registered',
        'category' => 'authentication',
        'priority' => 'low',
        'description' => 'New user registered'
    ));
    
    sentinel_register_event('profile_updated', array(
        'label' => 'Profile Updated',
        'category' => 'user',
        'priority' => 'low',
        'description' => 'User profile was updated'
    ));
    
    // Content events
    sentinel_register_event('post_published', array(
        'label' => 'Post Published',
        'category' => 'content',
        'priority' => 'low',
        'description' => 'Post was published'
    ));
    
    sentinel_register_event('post_updated', array(
        'label' => 'Post Updated',
        'category' => 'content',
        'priority' => 'low',
        'description' => 'Post was updated'
    ));
    
    sentinel_register_event('post_deleted', array(
        'label' => 'Post Deleted',
        'category' => 'content',
        'priority' => 'high',
        'description' => 'Post was deleted'
    ));
    
    sentinel_register_event('comment_posted', array(
        'label' => 'Comment Posted',
        'category' => 'content',
        'priority' => 'low',
        'description' => 'Comment was posted'
    ));
    
    sentinel_register_event('comment_approved', array(
        'label' => 'Comment Approved',
        'category' => 'content',
        'priority' => 'low',
        'description' => 'Comment was approved'
    ));
    
    sentinel_register_event('comment_deleted', array(
        'label' => 'Comment Deleted',
        'category' => 'content',
        'priority' => 'high',
        'description' => 'Comment was deleted'
    ));
    
    // System events
    sentinel_register_event('plugin_activated', array(
        'label' => 'Plugin Activated',
        'category' => 'system',
        'priority' => 'low',
        'description' => 'Plugin was activated'
    ));
    
    sentinel_register_event('plugin_deactivated', array(
        'label' => 'Plugin Deactivated',
        'category' => 'system',
        'priority' => 'low',
        'description' => 'Plugin was deactivated'
    ));
    
    // System maintenance events
    sentinel_register_event('logs_cleaned', array(
        'label' => 'Logs Cleaned',
        'category' => 'system',
        'priority' => 'low',
        'description' => 'Old log entries were cleaned up'
    ));
    
    sentinel_register_event('tables_optimized', array(
        'label' => 'Tables Optimized',
        'category' => 'system',
        'priority' => 'low',
        'description' => 'Database tables were optimized'
    ));
    
    // Admin/testing events
    sentinel_register_event('admin_test', array(
        'label' => 'Admin Test',
        'category' => 'system',
        'priority' => 'low',
        'description' => 'Test log entry created from admin panel'
    ));
    
    // Rate Limiting Events
    sentinel_register_event('rate_limit_warning', array(
        'label' => 'Rate Limit Warning',
        'category' => 'system',
        'priority' => 'high',
        'description' => 'Rate limit approaching threshold (80% or 90%)'
    ));
    
    sentinel_register_event('rate_limit_exceeded', array(
        'label' => 'Rate Limit Exceeded',
        'category' => 'system',
        'priority' => 'critical',
        'description' => 'Rate limit exceeded, rate limiting behavior active'
    ));
    
    // =====================================
    // ERROR EVENTS - Comprehensive Coverage
    // =====================================
    
    // PHP Error Events
    sentinel_register_event('php_fatal_error', array(
        'label' => 'PHP Fatal Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'PHP fatal error occurred'
    ));
    
    sentinel_register_event('php_warning', array(
        'label' => 'PHP Warning',
        'category' => 'error',
        'priority' => 'high',
        'description' => 'PHP warning occurred'
    ));
    
    sentinel_register_event('php_notice', array(
        'label' => 'PHP Notice',
        'category' => 'error',
        'priority' => 'low',
        'description' => 'PHP notice occurred'
    ));
    
    sentinel_register_event('php_deprecated', array(
        'label' => 'PHP Deprecated',
        'category' => 'error',
        'priority' => 'high',
        'description' => 'PHP deprecated function used'
    ));
    
    // WordPress Core Errors
    sentinel_register_event('wp_database_error', array(
        'label' => 'Database Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'WordPress database error occurred'
    ));
    
    sentinel_register_event('wp_memory_error', array(
        'label' => 'Memory Limit Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'WordPress memory limit exceeded'
    ));
    
    sentinel_register_event('wp_permission_error', array(
        'label' => 'Permission Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'File or directory permission error'
    ));
    
    sentinel_register_event('wp_config_error', array(
        'label' => 'Configuration Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'WordPress configuration error'
    ));
    
    // Authentication & Security Errors
    sentinel_register_event('login_failed', array(
        'label' => 'Login Failed',
        'category' => 'security',
        'priority' => 'high',
        'description' => 'User login attempt failed'
    ));
    
    sentinel_register_event('auth_cookie_bad', array(
        'label' => 'Bad Authentication Cookie',
        'category' => 'security',
        'priority' => 'high',
        'description' => 'Invalid authentication cookie detected'
    ));
    
    sentinel_register_event('nonce_verification_failed', array(
        'label' => 'Nonce Verification Failed',
        'category' => 'security',
        'priority' => 'high',
        'description' => 'WordPress nonce verification failed'
    ));
    
    sentinel_register_event('permission_denied', array(
        'label' => 'Permission Denied',
        'category' => 'security',
        'priority' => 'critical',
        'description' => 'Access permission denied'
    ));
    
    // HTTP & API Errors
    sentinel_register_event('http_404_error', array(
        'label' => '404 Not Found',
        'category' => 'error',
        'priority' => 'low',
        'description' => 'Page not found error'
    ));
    
    sentinel_register_event('http_500_error', array(
        'label' => '500 Internal Server Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'Internal server error'
    ));
    
    sentinel_register_event('wp_remote_error', array(
        'label' => 'Remote Request Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'WordPress remote request failed'
    ));
    
    sentinel_register_event('wp_cron_error', array(
        'label' => 'Cron Job Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'WordPress cron job failed'
    ));
    
    // Plugin & Theme Errors
    sentinel_register_event('plugin_error', array(
        'label' => 'Plugin Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'Plugin caused an error'
    ));
    
    sentinel_register_event('theme_error', array(
        'label' => 'Theme Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'Theme caused an error'
    ));
    
    sentinel_register_event('plugin_activation_error', array(
        'label' => 'Plugin Activation Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'Plugin failed to activate'
    ));
    
    // File & Upload Errors
    sentinel_register_event('file_upload_error', array(
        'label' => 'File Upload Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'File upload failed'
    ));
    
    sentinel_register_event('file_permission_error', array(
        'label' => 'File Permission Error',
        'category' => 'error',
        'priority' => 'critical',
        'description' => 'File permission error'
    ));

    // Audit log access
    sentinel_register_event('log_accessed', array(
        'label' => 'Log Accessed',
        'category' => 'audit',
        'priority' => 'low',
        'description' => 'Log accessed'
    ));
    
    // Performance monitoring events for weekly digest
    sentinel_register_event('memory_peak_usage', array(
        'label' => 'Memory Peak Usage',
        'category' => 'performance',
        'priority' => 'low',
        'description' => 'Peak memory usage for this request'
    ));
    
    sentinel_register_event('db_query_count', array(
        'label' => 'Database Query Count',
        'category' => 'performance',
        'priority' => 'low',
        'description' => 'Number of database queries for this request'
    ));
    
    sentinel_register_event('response_time_ms', array(
        'label' => 'Response Time',
        'category' => 'performance',
        'priority' => 'low',
        'description' => 'Response time in milliseconds for this request'
    ));
    
    // Privacy & GDPR Events
    sentinel_register_event('user_deletion_request', array(
        'label' => 'User Deletion Request',
        'category' => 'privacy',
        'priority' => 'high',
        'description' => 'User requested data deletion (GDPR Article 17)'
    ));
    
    sentinel_register_event('user_data_anonymized', array(
        'label' => 'User Data Anonymized',
        'category' => 'privacy',
        'priority' => 'high',
        'description' => 'User data was anonymized from logs'
    ));
    
    sentinel_register_event('admin_deletion_request_processed', array(
        'label' => 'Admin Processed Deletion Request',
        'category' => 'privacy',
        'priority' => 'high',
        'description' => 'Admin approved or denied a data deletion request'
    ));
    
    // Custom events can be registered by themes/plugins using sentinel_register_event()
    // Example: sentinel_register_event('custom_action', array('category' => 'custom', 'priority' => 'low'));
}

// Hook into WordPress events for automatic logging
/**
 * Log user login events
 */
function sentinel_log_user_login($user_login, $user) {
    $username = $user->user_login ?? $user_login;
    
    sentinel_log_event('user_login', array(
        'username' => $username,
        'user_id' => $user->ID ?? 0,
        'login_method' => 'standard',
        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
        'success' => true
    ), $user->ID ?? 0);
}

/**
 * Log user logout events
 */
function sentinel_log_user_logout() {
    $current_user = wp_get_current_user();
    
    if ($current_user && $current_user->ID) {
        sentinel_log_event('user_logout', array(
            'username' => $current_user->user_login,
            'user_id' => $current_user->ID,
            'logout_method' => 'standard',
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? ''
        ), $current_user->ID);
    }
}

// Store user ID before logout
add_action('init', function() {
    if (is_user_logged_in()) {
        $GLOBALS['sentinel_current_user_id'] = get_current_user_id();
    }
});

// Log logout event with correct user ID
add_action('wp_logout', function() {
    $user_id = isset($GLOBALS['sentinel_current_user_id']) ? $GLOBALS['sentinel_current_user_id'] : 0;
    if ($user_id) {
        sentinel_log_event('user_logout', array(), $user_id);
    }
});

add_action('user_register', 'sentinel_log_user_registered');
function sentinel_log_user_registered($user_id) {
    $user = get_userdata($user_id);
    sentinel_log_event('user_registered', array(
        'username' => $user->user_login,
        'email' => $user->user_email
    ), $user_id);
}

add_action('profile_update', 'sentinel_log_profile_updated');
function sentinel_log_profile_updated($user_id) {
    sentinel_log_event('profile_updated', array(), $user_id);
}

add_action('wp_insert_post', 'sentinel_log_post_published', 10, 3);
function sentinel_log_post_published($post_id, $post, $update) {
    // Ensure we have a valid post object
    if (!is_object($post) || !isset($post->post_status)) {
        $post = get_post($post_id);
        if (!$post) {
            return; // Invalid post, skip logging
        }
    }
    
    if ($post->post_status === 'publish' && !$update) {
        sentinel_log_event('post_published', array(
            'post_id' => $post_id,
            'post_type' => $post->post_type,
            'post_title' => $post->post_title
        ), $post->post_author);
    } elseif ($update) {
        sentinel_log_event('post_updated', array(
            'post_id' => $post_id,
            'post_type' => $post->post_type,
            'post_title' => $post->post_title
        ), $post->post_author);
    }
}

add_action('before_delete_post', 'sentinel_log_post_deleted');
function sentinel_log_post_deleted($post_id) {
    $post = get_post($post_id);
    if ($post && is_object($post) && isset($post->post_type)) {
        sentinel_log_event('post_deleted', array(
            'post_id' => $post_id,
            'post_type' => $post->post_type,
            'post_title' => $post->post_title
        ), $post->post_author);
    }
}

add_action('wp_insert_comment', 'sentinel_log_comment_posted', 10, 2);
function sentinel_log_comment_posted($comment_id, $comment) {
    // Ensure we have a valid comment object
    if (!is_object($comment) || !isset($comment->comment_post_ID)) {
        $comment = get_comment($comment_id);
        if (!$comment) {
            return; // Invalid comment, skip logging
        }
    }
    
    sentinel_log_event('comment_posted', array(
        'comment_id' => $comment_id,
        'post_id' => $comment->comment_post_ID
    ), $comment->user_id);
}

add_action('comment_unapproved_to_approved', 'sentinel_log_comment_approved');
function sentinel_log_comment_approved($comment) {
    // Ensure we have a valid comment object
    if (!is_object($comment) || !isset($comment->comment_ID)) {
        return; // Invalid comment, skip logging
    }
    
    sentinel_log_event('comment_approved', array(
        'comment_id' => $comment->comment_ID,
        'post_id' => $comment->comment_post_ID
    ), $comment->user_id);
}

add_action('delete_comment', 'sentinel_log_comment_deleted');
function sentinel_log_comment_deleted($comment_id) {
    $comment = get_comment($comment_id);
    if ($comment && is_object($comment) && isset($comment->comment_post_ID)) {
        sentinel_log_event('comment_deleted', array(
            'comment_id' => $comment_id,
            'post_id' => $comment->comment_post_ID
        ), $comment->user_id);
    }
}

add_action('activated_plugin', 'sentinel_log_plugin_activated');
function sentinel_log_plugin_activated($plugin) {
    sentinel_log_event('plugin_activated', array(
        'plugin' => $plugin
    ));
}

add_action('deactivated_plugin', 'sentinel_log_plugin_deactivated');
function sentinel_log_plugin_deactivated($plugin) {
    sentinel_log_event('plugin_deactivated', array(
        'plugin' => $plugin
    ));
}

// =====================================
// ERROR HANDLING HOOKS
// =====================================

// WordPress Login Failures
add_action('wp_login_failed', 'sentinel_log_login_failed');
function sentinel_log_login_failed($username) {
    // Prevent duplicate logging within the same request
    static $logged_failures = array();
    $failure_key = md5($username . $_SERVER['REMOTE_ADDR'] . $_SERVER['REQUEST_TIME']);
    
    if (isset($logged_failures[$failure_key])) {
        return; // Already logged this failure
    }
    
    $logged_failures[$failure_key] = true;
    
    sentinel_log_event('login_failed', array(
        'username' => $username,
        'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'
    ));
}

// Bad Authentication Cookies
add_action('auth_cookie_bad_username', 'sentinel_log_bad_auth_cookie');
add_action('auth_cookie_bad_hash', 'sentinel_log_bad_auth_cookie');
function sentinel_log_bad_auth_cookie($cookie_elements) {
    sentinel_log_event('auth_cookie_bad', array(
        'cookie_data' => is_array($cookie_elements) ? json_encode($cookie_elements) : $cookie_elements
    ));
}

// WordPress Database Errors
add_action('wp_insert_post_data', 'sentinel_check_db_errors_on_post', 10, 2);
function sentinel_check_db_errors_on_post($data, $postarr) {
    global $wpdb;
    if (!empty($wpdb->last_error)) {
        // Prevent logging database errors during Sentinel's own database operations
        static $db_error_logging = false;
        if ($db_error_logging) {
            return $data; // Prevent recursive database error logging
        }
        
        // Throttle database error logging to prevent feedback loops
        static $last_db_error_time = 0;
        $current_time = time();
        if ($current_time - $last_db_error_time < 5) {
            return $data; // Only log database errors every 5 seconds at most
        }
        $last_db_error_time = $current_time;
        
        // Check if this is a Sentinel-related query to prevent feedback loop
        if (strpos($wpdb->last_query, 'sentinel_logs') !== false) {
            error_log('[Sentinel] Database error during Sentinel logging operation (not logging to prevent feedback loop): ' . $wpdb->last_error);
            return $data;
        }
        
        $db_error_logging = true;
        sentinel_log_event('wp_database_error', array(
            'error_message' => $wpdb->last_error,
            'last_query' => $wpdb->last_query,
            'context' => 'post_insert'
        ));
        $db_error_logging = false;
    }
    return $data;
}

/**
 * Set up database error logging
 */
function sentinel_setup_db_error_logging() {
    global $wpdb;
    
    // Only set up if not already done
    if (!isset($wpdb->sentinel_error_handler_set)) {
        $wpdb->sentinel_error_handler_set = true;
        
        // Hook into WordPress database error handling
        add_action('wp_error_added', 'sentinel_log_wp_error', 10, 4);
        
        // Check for database errors on shutdown
        add_action('shutdown', 'sentinel_check_db_errors');
    }
}

/**
 * Log WordPress errors
 */
function sentinel_log_wp_error($code, $message, $data, $wp_error) {
    // Skip if this is a database error (we handle those separately)
    if (strpos($code, 'db_') === 0) {
        return;
    }
    
    sentinel_log_event('wp_error', array(
        'error_code' => $code,
        'message' => $message,
        'data' => $data
    ));
}

/**
 * Check for database errors on shutdown
 */
function sentinel_check_db_errors() {
    global $wpdb;
    
    if (!empty($wpdb->last_error)) {
        // Prevent logging database errors during Sentinel's own database operations
        static $db_error_logging = false;
        if ($db_error_logging) {
            return; // Prevent recursive database error logging
        }
        
        // Throttle database error logging to prevent feedback loops
        static $last_db_error_time = 0;
        $current_time = time();
        if ($current_time - $last_db_error_time < 5) {
            return; // Only log database errors every 5 seconds at most
        }
        $last_db_error_time = $current_time;
        
        // Check if this is a Sentinel-related query to prevent feedback loop
        if (strpos($wpdb->last_query, 'sentinel_logs') !== false) {
            error_log('[Sentinel] Database error during Sentinel logging operation (not logging to prevent feedback loop): ' . $wpdb->last_error);
            return;
        }
        
        $db_error_logging = true;
        sentinel_log_event('wp_database_error', array(
            'error_message' => $wpdb->last_error,
            'last_query' => $wpdb->last_query,
            'url' => $_SERVER['REQUEST_URI'] ?? 'unknown'
        ));
        $db_error_logging = false;
    }
}

// PHP Error Handler
add_action('init', 'sentinel_setup_php_error_handler');
function sentinel_setup_php_error_handler() {
    // Only set up if not already handling errors
    if (!defined('SENTINEL_ERROR_HANDLING')) {
        define('SENTINEL_ERROR_HANDLING', true);
        
        // Set custom error handler
        set_error_handler('sentinel_php_error_handler');
        
        // Register shutdown function to catch fatal errors
        register_shutdown_function('sentinel_php_fatal_error_handler');
    }
}

function sentinel_php_error_handler($errno, $errstr, $errfile, $errline) {
    // Don't log errors if error reporting is turned off
    if (!(error_reporting() & $errno)) {
        return false;
    }
    
    $event_key = 'php_notice';
    $priority = 'info';
    
    switch ($errno) {
        case E_ERROR:
        case E_CORE_ERROR:
        case E_COMPILE_ERROR:
        case E_USER_ERROR:
            $event_key = 'php_fatal_error';
            $priority = 'critical';
            break;
        case E_WARNING:
        case E_CORE_WARNING:
        case E_COMPILE_WARNING:
        case E_USER_WARNING:
            $event_key = 'php_warning';
            $priority = 'high';
            break;
        case E_NOTICE:
        case E_USER_NOTICE:
            $event_key = 'php_notice';
            $priority = 'low';
            break;
        case E_DEPRECATED:
        case E_USER_DEPRECATED:
            $event_key = 'php_deprecated';
            $priority = 'high';
            break;
    }
    
    sentinel_log_event($event_key, array(
        'error_message' => $errstr,
        'error_file' => $errfile,
        'error_line' => $errline,
        'error_type' => $errno,
        'url' => $_SERVER['REQUEST_URI'] ?? 'Unknown'
    ));
    
    // Don't interfere with WordPress error handling
    return false;
}

function sentinel_php_fatal_error_handler() {
    $error = error_get_last();
    if ($error !== null && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR])) {
        sentinel_log_event('php_fatal_error', array(
            'error_message' => $error['message'],
            'error_file' => $error['file'],
            'error_line' => $error['line'],
            'error_type' => $error['type'],
            'url' => $_SERVER['REQUEST_URI'] ?? 'Unknown'
        ));
    }
    
    // Log performance metrics for weekly digest
    sentinel_log_performance_metrics();
}

// File Upload Errors
add_filter('wp_handle_upload_prefilter', 'sentinel_check_upload_errors');
function sentinel_check_upload_errors($file) {
    if (isset($file['error']) && $file['error'] != UPLOAD_ERR_OK) {
        $error_messages = array(
            UPLOAD_ERR_INI_SIZE => 'File exceeds upload_max_filesize',
            UPLOAD_ERR_FORM_SIZE => 'File exceeds MAX_FILE_SIZE',
            UPLOAD_ERR_PARTIAL => 'File was only partially uploaded',
            UPLOAD_ERR_NO_FILE => 'No file was uploaded',
            UPLOAD_ERR_NO_TMP_DIR => 'Missing temporary folder',
            UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk',
            UPLOAD_ERR_EXTENSION => 'File upload stopped by extension'
        );
        
        sentinel_log_event('file_upload_error', array(
            'error_code' => $file['error'],
            'error_message' => isset($error_messages[$file['error']]) ? $error_messages[$file['error']] : 'Unknown upload error',
            'filename' => $file['name'] ?? 'Unknown',
            'filesize' => $file['size'] ?? 0
        ));
    }
    return $file;
}

// Plugin Activation Errors
add_action('activated_plugin', 'sentinel_check_plugin_activation_errors');
function sentinel_check_plugin_activation_errors($plugin) {
    // Check if there were any errors during activation
    $errors = get_transient('sentinel_plugin_activation_errors');
    if ($errors) {
        sentinel_log_event('plugin_activation_error', array(
            'plugin' => $plugin,
            'error_message' => $errors
        ));
        delete_transient('sentinel_plugin_activation_errors');
    }
}

// Catch WordPress die() calls that might indicate errors
add_action('wp_die_handler', 'sentinel_wp_die_handler');
function sentinel_wp_die_handler($handler) {
    // Store the original handler
    $original_handler = $handler;
    
    // Return a custom handler that logs before dying
    return function($message, $title = '', $args = array()) use ($original_handler) {
        // Log the wp_die event
        sentinel_log_event('wp_config_error', array(
            'error_message' => is_string($message) ? $message : 'WordPress died',
            'error_title' => $title,
            'context' => 'wp_die',
            'url' => $_SERVER['REQUEST_URI'] ?? 'Unknown'
        ));
        
        // Call the original handler
        return call_user_func($original_handler, $message, $title, $args);
    };
}

// HTTP Error Handling
add_action('wp', 'sentinel_check_http_errors');
function sentinel_check_http_errors() {
    // Check if this is a 404 error
    if (is_404()) {
        sentinel_log_event('http_404_error', array(
            'requested_url' => $_SERVER['REQUEST_URI'] ?? 'Unknown',
            'referer' => $_SERVER['HTTP_REFERER'] ?? 'Direct',
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'
        ));
    }
}

// WordPress Remote Request Errors
add_action('http_api_debug', 'sentinel_log_remote_request_errors', 10, 5);
function sentinel_log_remote_request_errors($response, $context, $class, $args, $url) {
    if (is_wp_error($response)) {
        sentinel_log_event('wp_remote_error', array(
            'error_message' => $response->get_error_message(),
            'error_code' => $response->get_error_code(),
            'url' => $url,
            'context' => $context
        ));
    }
}

// WordPress Cron Errors
add_action('wp_cron_api_error', 'sentinel_log_cron_errors');
function sentinel_log_cron_errors($error) {
    if (is_wp_error($error)) {
        sentinel_log_event('wp_cron_error', array(
            'error_message' => $error->get_error_message(),
            'error_code' => $error->get_error_code()
        ));
    }
}

// Include comprehensive memory monitoring
require_once plugin_dir_path(__FILE__) . 'includes/class-sentinel-memory-monitor.php';

// Legacy memory check (kept for backward compatibility)
add_action('init', 'sentinel_check_memory_usage');
function sentinel_check_memory_usage() {
    // Note: This is now handled by the comprehensive Sentinel_Memory_Monitor class
    // This function is kept for backward compatibility only
    
    $settings = get_option('sentinel_log_management', array());
    if (empty($settings['memory_monitoring_enabled'])) {
        return; // Memory monitoring disabled
    }
    
    $memory_limit = ini_get('memory_limit');
    $memory_usage = memory_get_usage(true);
    
    // Convert memory limit to bytes
    $limit_bytes = sentinel_convert_to_bytes($memory_limit);
    
    // If using more than 90% of memory limit, log a warning (legacy behavior)
    if ($memory_usage > ($limit_bytes * 0.9)) {
        sentinel_log_event('wp_memory_error', array(
            'memory_usage' => $memory_usage,
            'memory_limit' => $memory_limit,
            'percentage_used' => round(($memory_usage / $limit_bytes) * 100, 2),
            'url' => $_SERVER['REQUEST_URI'] ?? 'Unknown',
            'note' => 'Legacy memory check - comprehensive monitoring active'
        ));
    }
}

/**
 * Log performance metrics for weekly digest reports
 * This function is called at shutdown to capture real performance data
 * Stores samples in a transient instead of the activity log
 */
function sentinel_log_performance_metrics() {
    $settings = get_option('sentinel_log_management', array());
    if (empty($settings['memory_monitoring_enabled'])) {
        return; // Performance monitoring disabled
    }
    
    // Implement sampling to reduce storage - only log 1 in 10 requests
    $sample_rate = 10; // Only log every 10th request
    $request_hash = md5($_SERVER['REQUEST_URI'] ?? 'unknown' . time());
    $should_log = (ord($request_hash[0]) % $sample_rate) === 0;
    if (!$should_log) {
        return; // Skip this request
    }
    // Gather metrics
    $peak_memory = memory_get_peak_usage(true);
    global $wpdb;
    $db_queries = $wpdb->num_queries;
    $response_time_ms = 0;
    if (isset($_SERVER['REQUEST_TIME_FLOAT'])) {
        $response_time_ms = round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000, 2);
    }
    $sample = array(
        'memory_bytes' => $peak_memory,
        'db_queries' => $db_queries,
        'response_time_ms' => $response_time_ms,
        'timestamp' => time(),
        'url' => $_SERVER['REQUEST_URI'] ?? 'Unknown',
    );
    // Store in transient (array of samples)
    $samples = get_transient('sentinel_performance_samples');
    if (!is_array($samples)) {
        $samples = array();
    }
    $samples[] = $sample;
    set_transient('sentinel_performance_samples', $samples, 691200);
    // Debug log for testing
    if (defined('WP_DEBUG') && WP_DEBUG) {
        error_log('[Sentinel Debug] Performance sample added. Total samples: ' . count($samples));
        error_log('[Sentinel Debug] Last sample: ' . json_encode($sample));
    }
}

// Helper function to convert memory limit to bytes
function sentinel_convert_to_bytes($value) {
    $value = trim($value);
    $last = strtolower($value[strlen($value) - 1]);
    $value = (int) $value;
    
    switch ($last) {
        case 'g':
            $value *= 1024;
        case 'm':
            $value *= 1024;
        case 'k':
            $value *= 1024;
    }
    
    return $value;
}

// Helper function to format activity messages for display
if (!function_exists('sentinel_format_activity_message')) {
    /**
     * Format activity message for display
     *
     * @param object $activity   The activity object from database
     * @param array $usernames   Array of user IDs to usernames
     * @return string            Formatted message
     */
    function sentinel_format_activity_message($activity, $usernames) {
        $username = isset($usernames[$activity->user_id]) ? $usernames[$activity->user_id] : 'Unknown User';
        $data = (!empty($activity->data) && is_string($activity->data)) ? json_decode($activity->data, true) : array();

        switch ($activity->event_key) {
            case 'user_login':
                return sprintf('%s logged in', $username);
            
            case 'user_logout':
                return sprintf('%s logged out', $username);
            
            case 'user_registered':
                return sprintf('New user %s registered', $username);
            
            case 'profile_updated':
                return sprintf('%s updated their profile', $username);
            
            case 'post_published':
                $post_type = isset($data['post_type']) ? $data['post_type'] : 'post';
                return sprintf('%s published a %s', $username, $post_type);
            
            case 'post_updated':
                $post_type = isset($data['post_type']) ? $data['post_type'] : 'post';
                return sprintf('%s updated a %s', $username, $post_type);
            
            case 'post_deleted':
                $post_type = isset($data['post_type']) ? $data['post_type'] : 'post';
                return sprintf('%s deleted a %s', $username, $post_type);
            
            case 'comment_posted':
                return sprintf('%s posted a comment', $username);
            
            case 'comment_approved':
                return sprintf('Comment by %s was approved', $username);
            
            case 'comment_deleted':
                return sprintf('Comment by %s was deleted', $username);
            
            case 'plugin_activated':
                $plugin = isset($data['plugin']) ? $data['plugin'] : 'Unknown Plugin';
                return sprintf('Plugin %s was activated', $plugin);
            
            case 'plugin_deactivated':
                $plugin = isset($data['plugin']) ? $data['plugin'] : 'Unknown Plugin';
                return sprintf('Plugin %s was deactivated', $plugin);
            
            case 'logs_cleaned':
                $deleted_count = isset($data['deleted_count']) ? $data['deleted_count'] : 0;
                return sprintf('System cleaned up %d old log entries', $deleted_count);
            
            case 'tables_optimized':
                $tables_count = isset($data['tables_optimized']) ? $data['tables_optimized'] : 0;
                return sprintf('System optimized %d database tables', $tables_count);
            
            // PHP Error Events
            case 'php_fatal_error':
                return 'PHP Fatal Error';
            
            case 'php_warning':
                return 'PHP Warning';
            
            case 'php_notice':
                return 'PHP Notice';
            
            case 'php_deprecated':
                return 'PHP Deprecated';
            
            // WordPress Core Errors
            case 'wp_database_error':
                return 'Database Error';
            
            case 'wp_memory_error':
                return 'Memory Limit Exceeded';
            
            case 'wp_permission_error':
                return 'Permission Error';
            
            case 'wp_config_error':
                return 'Configuration Error';
            
            // Security & Authentication Errors
            case 'login_failed':
                return 'Login Failed';
            
            case 'auth_cookie_bad':
                return sprintf('Bad authentication cookie detected');
            
            case 'nonce_verification_failed':
                return sprintf('Nonce verification failed');
            
            case 'permission_denied':
                return sprintf('Access permission denied');
            
            // HTTP & API Errors
            case 'http_404_error':
                return '404 Error';
            
            case 'http_500_error':
                return sprintf('Internal Server Error occurred');
            
            case 'wp_remote_error':
                $error_msg = isset($data['error_message']) ? substr($data['error_message'], 0, 100) : 'Unknown remote error';
                return sprintf('Remote Request Error: %s', $error_msg);
            
            case 'wp_cron_error':
                $error_msg = isset($data['error_message']) ? substr($data['error_message'], 0, 100) : 'Unknown cron error';
                return sprintf('Cron Job Error: %s', $error_msg);
            
            // Plugin & Theme Errors
            case 'plugin_error':
                $plugin_name = isset($data['plugin']) ? $data['plugin'] : 'unknown plugin';
                return sprintf('Plugin Error: %s', $plugin_name);
            
            case 'theme_error':
                $theme_name = isset($data['theme']) ? $data['theme'] : 'unknown theme';
                return sprintf('Theme Error: %s', $theme_name);
            
            case 'plugin_activation_error':
                $plugin_name = isset($data['plugin']) ? $data['plugin'] : 'unknown plugin';
                return sprintf('Plugin Activation Error: %s', $plugin_name);
            
            // File & Upload Errors
            case 'file_upload_error':
                return 'File Upload Error';
            
            case 'file_permission_error':
                return sprintf('File Permission Error: %s', isset($data['error_message']) ? $data['error_message'] : 'file permission denied');
            
            // Rate Limiting Events
            case 'rate_limit_warning':
                $severity = isset($data['severity']) ? strtoupper($data['severity']) : 'WARNING';
                $percentage = isset($data['percentage']) ? $data['percentage'] : 'N/A';
                $time_window = isset($data['time_window']) ? $data['time_window'] : 'unknown';
                return sprintf('%s: Rate limit approaching (%s%% of %s limit)', $severity, $percentage, $time_window);
            
            case 'rate_limit_exceeded':
                $time_window = isset($data['time_window']) ? $data['time_window'] : 'unknown';
                $count = isset($data['current_count']) ? $data['current_count'] : 'N/A';
                $limit = isset($data['limit']) ? $data['limit'] : 'N/A';
                $behavior_desc = isset($data['behavior_description']) ? $data['behavior_description'] : 'Rate limiting active';
                return sprintf('Rate limit exceeded (%s/%s %s) - %s', $count, $limit, $time_window, $behavior_desc);
            
            // Audit log access
            case 'log_accessed':
                return sprintf('%s accessed the logs', $username);
            
            // Custom events will fall through to default case
            
            default:
                return sprintf('%s performed %s', $username, $activity->event_key);
        }
    }
}

// Helper function to get activity icon for event type
if (!function_exists('sentinel_get_activity_icon')) {
    /**
     * Get activity icon for event type
     *
     * @param string $event_key The event key
     * @return string           Icon name
     */
    function sentinel_get_activity_icon($event_key) {
        $icons = array(
            'user_login' => 'admin-users',
            'user_logout' => 'exit',
            'user_registered' => 'admin-users',
            'profile_updated' => 'admin-users',
            'post_published' => 'admin-post',
            'post_updated' => 'edit',
            'post_deleted' => 'trash',
            'comment_posted' => 'admin-comments',
            'comment_approved' => 'yes',
            'comment_deleted' => 'trash',
            'plugin_activated' => 'admin-plugins',
            'plugin_deactivated' => 'admin-plugins',
            'logs_cleaned' => 'database',
            'tables_optimized' => 'performance',
            
            // PHP Error Icons
            'php_fatal_error' => 'warning',
            'php_warning' => 'warning',
            'php_notice' => 'info',
            'php_deprecated' => 'warning',
            
            // WordPress Core Error Icons
            'wp_database_error' => 'database-remove',
            'wp_memory_error' => 'warning',
            'wp_permission_error' => 'lock',
            'wp_config_error' => 'admin-tools',
            
            // Security & Authentication Error Icons
            'login_failed' => 'shield-alt',
            'auth_cookie_bad' => 'shield-alt',
            'nonce_verification_failed' => 'shield-alt',
            'permission_denied' => 'lock',
            
            // HTTP & API Error Icons
            'http_404_error' => 'search',
            'http_500_error' => 'warning',
            'wp_remote_error' => 'cloud',
            'wp_cron_error' => 'clock',
            
            // Plugin & Theme Error Icons
            'plugin_error' => 'admin-plugins',
            'theme_error' => 'admin-appearance',
            'plugin_activation_error' => 'admin-plugins',
            
            // File & Upload Error Icons
            'file_upload_error' => 'upload',
            'file_permission_error' => 'lock',
            
            // Rate Limiting Icons
            'rate_limit_warning' => 'warning',
            'rate_limit_exceeded' => 'dashboard'
        );

        return isset($icons[$event_key]) ? $icons[$event_key] : 'admin-generic';
    }
}

// Memory monitor functionality is active through hooks and settings page 

// Handle manual anonymization action in settings page
add_action('admin_init', function() {
    if (is_admin() && isset($_GET['page']) && $_GET['page'] === 'sentinel-settings' && isset($_GET['action']) && $_GET['action'] === 'anonymize_logs') {
        error_log('[Sentinel] Manual anonymize_logs action triggered');
        if (class_exists('Sentinel_Cleanup')) {
            error_log('[Sentinel] Sentinel_Cleanup class exists, calling anonymize_old_logs (manual, all logs)');
            $result = Sentinel_Cleanup::anonymize_old_logs(true);
            error_log('[Sentinel] anonymize_old_logs called, result: ' . var_export($result, true));
            wp_redirect(admin_url('admin.php?page=sentinel-settings&message=anonymize_success&tab=log-management'));
            exit;
        } else {
            error_log('[Sentinel] ERROR: Sentinel_Cleanup class does not exist');
        }
    }
}); 

// --- BEGIN: Granular Email Notification Logic ---
if (!function_exists('sentinel_should_send_granular_email_notification')) {
    /**
     * Determine if a granular email notification should be sent for this event
     * @param string $event_key
     * @param array $event_config
     * @param array $data
     * @param int|null $user_id
     * @return bool
     */
    function sentinel_should_send_granular_email_notification($event_key, $event_config, $data, $user_id = null) {
        $settings = get_option('sentinel_log_management', array());
        if (empty($settings['sentinel_email_notifications_enabled'])) {
            return false;
        }
        $priority = $event_config['priority'] ?? '';
        $category = $event_config['category'] ?? '';
        // Real-time: critical, security, error, high
        if (!empty($settings['sentinel_email_realtime_critical']) && $priority === 'critical') {
            return true;
        }
        if (!empty($settings['sentinel_email_realtime_security']) && $category === 'security') {
            return true;
        }
        if (!empty($settings['sentinel_email_realtime_error']) && $priority === 'error') {
            return true;
        }
        if (!empty($settings['sentinel_email_realtime_high']) && $priority === 'high') {
            return true;
        }
        // Categories
        if (!empty($settings['sentinel_email_cat_authentication']) && $category === 'authentication') {
            return true;
        }
        if (!empty($settings['sentinel_email_cat_content']) && $category === 'content') {
            return true;
        }
        if (!empty($settings['sentinel_email_cat_system']) && $category === 'system') {
            return true;
        }
        if (!empty($settings['sentinel_email_cat_error']) && $category === 'errors') {
            return true;
        }
        if (!empty($settings['sentinel_email_cat_security']) && $category === 'security') {
            return true;
        }
        if (!empty($settings['sentinel_email_cat_user']) && $category === 'user') {
            return true;
        }
        // Priorities
        if (!empty($settings['sentinel_email_priority_high']) && $priority === 'high') {
            return true;
        }
        if (!empty($settings['sentinel_email_priority_medium']) && $priority === 'medium') {
            return true;
        }
        if (!empty($settings['sentinel_email_priority_low']) && $priority === 'low') {
            return true;
        }
        return false;
    }
}
// --- END: Granular Email Notification Logic --- 