<?php
/**
 * VMPFence File Scanner Class
 *
 * Handles file integrity checking and change detection
 *
 * @package VMPFence
 * @since 1.0.0
 * @since 2.1.1
 * @since 2.2.4 SQL Query fix
 */

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

// Include centralized exclusion manager
require_once plugin_dir_path(__FILE__) . 'class-scan-exclusion-manager.php';

class VMPFence_File_Scanner {
    
    /**
     * WordPress version
     */
    private $wp_version;
    
    /**
     * Known Files instance
     */
    private $known_files;
    
    /**
     * Scan results
     */
    private $scan_results = [];
    
    /**
     * Debug log
     */
    private $debug_log = [];
    
    /**
     * Cold start status
     */
    private $is_cold_start = null;
    
    /**
     * SHAC statistics
     */
    private $shac_stats = [
        'files_processed' => 0,
        'suspicious_patterns_found' => 0,
        'total_calculation_time' => 0,
        'high_risk_files' => 0
    ];
    
    /**
     * Threat Intelligence instance
     */
    private $threat_intelligence;
    
    /**
     * Total files count
     */
    private $total_files = 0;
    
    /**
     * Force file count refresh flag
     */
    private $force_file_count_refresh = false;
    
    /**
     * Unknown File Detection Engine
     */
    private $unknown_file_detection;
    
    /**
     * Content Pattern Analysis Engine
     */
    private $content_pattern_analysis;
    
    /**
     * Legitimacy Assessment Engine
     */
    private $legitimacy_assessment;
    
    /**
     * Severity Rating System
     */
    private $severity_rating;
    
    /**
     * Scan options flags
     */
    private $scan_options = null;
    private $skip_core_files = false;
    private $skip_plugins = false;
    private $skip_themes = false;
    private $skip_abandoned_plugins = false;
    private $skip_core_unknown = false;
    private $scan_outside_enabled = false;
    
    /**
     * Track processed files to prevent duplicate issues
     */
    private $processed_files = [];
    
    /**
     * Centralized exclusion manager
     */
    private $exclusion_manager;
    
    /**
     * Constructor
     */
    public function __construct() {
        global $wp_version;
        $this->wp_version = $wp_version;
        
        // Initialize Known Files system
        if (!class_exists('VMPFence_Known_Files')) {
            require_once VMPFENCE_PLUGIN_DIR . 'includes/class-known-files.php';
        }
        $this->known_files = new VMPFence_Known_Files();
        
        // Initialize Threat Intelligence system
        if (!class_exists('VMPFence_Threat_Intelligence')) {
            require_once VMPFENCE_PLUGIN_DIR . 'includes/class-threat-intelligence.php';
        }
        $this->threat_intelligence = new VMPFence_Threat_Intelligence();
        
        // Initialize Unknown File Detection Engine
        if (!class_exists('VMPFence_Unknown_File_Detection')) {
            require_once VMPFENCE_PLUGIN_DIR . 'includes/class-unknown-file-detection.php';
        }
        $this->unknown_file_detection = new VMPFence_Unknown_File_Detection();
        
        // Initialize Content Pattern Analysis Engine
        if (!class_exists('VMPFence_Content_Pattern_Analysis')) {
            require_once VMPFENCE_PLUGIN_DIR . 'includes/class-content-pattern-analysis.php';
        }
        $this->content_pattern_analysis = new VMPFence_Content_Pattern_Analysis();
        
        // Initialize Legitimacy Assessment Engine
        if (!class_exists('VMPFence_Legitimacy_Assessment')) {
            require_once VMPFENCE_PLUGIN_DIR . 'includes/class-legitimacy-assessment.php';
        }
        $this->legitimacy_assessment = new VMPFence_Legitimacy_Assessment();
        
        // Initialize Severity Rating System
        if (!class_exists('VMPFence_Severity_Rating')) {
            require_once VMPFENCE_PLUGIN_DIR . 'includes/class-severity-rating.php';
        }
        $this->severity_rating = new VMPFence_Severity_Rating();
        
        // Initialize centralized exclusion manager
        $this->exclusion_manager = VMPFence_Scan_Exclusion_Manager::getInstance();
        
        $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner initialized with all security engines: Known Files, Threat Intelligence, Unknown File Detection, Content Pattern Analysis, Legitimacy Assessment, and Severity Rating';
    }
    
    /**
     * Start file integrity scan (optimized for performance)
     * @param array $scan_options Optional scan configuration options
     */
    public function start_scan($scan_options = null) {
        // Initialize performance controls if available
        $use_performance_controls = false;
        if (class_exists('VMPFence_Performance_Manager')) {
            VMPFence_Performance_Manager::init();
            $use_performance_controls = true;
            $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner: Performance controls initialized';
        }
        
        $start_time = microtime(true);
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Starting File Changes Scan';
        
        // Reset processed files tracking for new scan
        $this->processed_files = [];
        
        // If scan options provided, respect them
        if ($scan_options) {
            // Check if ONLY outside scanning is enabled (skip all WordPress scanning)
            $only_outside_scan = isset($scan_options['other_scanOutside']) && $scan_options['other_scanOutside'] 
                && (!isset($scan_options['scansEnabled_core']) || !$scan_options['scansEnabled_core'])
                && (!isset($scan_options['scansEnabled_plugins']) || !$scan_options['scansEnabled_plugins'])
                && (!isset($scan_options['scansEnabled_themes']) || !$scan_options['scansEnabled_themes'])
                && (!isset($scan_options['scansEnabled_coreUnknown']) || !$scan_options['scansEnabled_coreUnknown']);
            
            if ($only_outside_scan) {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner: Only outside scanning enabled - skipping all WordPress scans';
                $this->skip_core_files = true;
                $this->skip_plugins = true;
                $this->skip_themes = true;
                $this->skip_abandoned_plugins = true;
            } else {
                // Core Files Check
                if (isset($scan_options['scansEnabled_core']) && !$scan_options['scansEnabled_core']) {
                    $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner: Core files check disabled by configuration';
                    $this->skip_core_files = true;
                }
                
                // Plugins Check
                if (isset($scan_options['scansEnabled_plugins']) && !$scan_options['scansEnabled_plugins']) {
                    $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner: Plugins check disabled by configuration';
                    $this->skip_plugins = true;
                }
                
                // Themes Check
                if (isset($scan_options['scansEnabled_themes']) && !$scan_options['scansEnabled_themes']) {
                    $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner: Themes check disabled by configuration';
                    $this->skip_themes = true;
                }
                
                // Abandoned Plugins Check
                if (isset($scan_options['scansEnabled_abandonedPlugins']) && !$scan_options['scansEnabled_abandonedPlugins']) {
                    $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner: Abandoned plugins check disabled by configuration';
                    $this->skip_abandoned_plugins = true;
                }
                
                // Core Unknown Files Check (wp-admin and wp-includes for files not bundled with WordPress)
                if (isset($scan_options['scansEnabled_coreUnknown']) && !$scan_options['scansEnabled_coreUnknown']) {
                    $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner: Core unknown files check disabled by configuration';
                    $this->skip_core_unknown = true;
                }
            }
            
            // Outside WordPress Scanning Check
            if (isset($scan_options['other_scanOutside']) && $scan_options['other_scanOutside']) {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] File Scanner: Outside WordPress scanning enabled';
                $this->scan_outside_enabled = true;
            }
            
            // Scan options specific to file scanner
            $this->scan_options = $scan_options;
            
            // Initialize exclusion manager with scan options
            $this->exclusion_manager->initialize($scan_options);
            
            // Check if plugins/themes should be excluded based on exclusion patterns
            if ($this->exclusion_manager->should_exclude_scanner_target('wp-content/plugins')) {
                $this->skip_plugins = true;
                $this->debug_log[] = '[SCAN OPTIONS] Plugins excluded by exclusion patterns';
            }
            
            if ($this->exclusion_manager->should_exclude_scanner_target('wp-content/themes')) {
                $this->skip_themes = true;
                $this->debug_log[] = '[SCAN OPTIONS] Themes excluded by exclusion patterns';
            }
            
            // Check if core unknown scan should be excluded (only if BOTH wp-admin AND wp-includes are excluded)
            if ($this->exclusion_manager->should_exclude_scanner_target('wp-admin') && 
                $this->exclusion_manager->should_exclude_scanner_target('wp-includes')) {
                $this->skip_core_unknown = true;
                $this->debug_log[] = '[SCAN OPTIONS] Core unknown scan excluded by exclusion patterns';
            }
            
            // Debug: Log scan options for exclusion patterns
            if (isset($scan_options['scan_exclude'])) {
                $this->debug_log[] = '[SCAN OPTIONS DEBUG] scan_exclude found: "' . $scan_options['scan_exclude'] . '"';
            } else {
                $this->debug_log[] = '[SCAN OPTIONS DEBUG] scan_exclude not found in scan options';
            }
        }
        
        // Cold Start Optimization: Check if this is the first scan after server restart
        $this->is_cold_start = $this->is_cold_start();
        if ($this->is_cold_start) {
            $this->debug_log[] = '[' . current_time('H:i:s') . '] COLD START detected: Applying optimization settings';
            $this->apply_cold_start_optimizations();
        }
        
        // Initialize or update Known Files database if needed
        $this->initialize_known_files_if_needed();
        
        // Initialize scan session
        $scan_id = $this->initialize_scan_session();
        
        // Set reasonable limits with cold start adjustments
        $memory_limit = $this->is_cold_start ? '384M' : '256M'; // More memory for first scan
        $time_limit = $this->is_cold_start ? 180 : 120; // More time for first scan
        
        ini_set('memory_limit', $memory_limit);
        set_time_limit($time_limit);
        
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Memory limit set to ' . $memory_limit . ', execution time limit set to ' . $time_limit . 's' . ($this->is_cold_start ? ' (COLD START)' : '');
        
        // Initialize progress with proper file count estimate
        $this->update_scan_progress(0, 'Calculating total files...');
        
        $this->scan_results = [
            'scan_id' => $scan_id,
            'core_files' => 0,
            'plugins' => 0,
            'themes' => 0,
            'unknown_files' => 0,
            'modified_files' => 0,
            'new_files' => 0,
            'deleted_files' => 0,
            'plugin_updates' => 0,
            'theme_updates' => 0,
            'scan_time' => current_time('mysql'),
            'total_files_checked' => 0,
            'issues_found' => 0,
            'scan_status' => 'running'
        ];
        
        try {
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Starting chunked file scanning process with Plugin Repository Verification';
            
            // Scan in chunks to avoid memory/time issues - respecting scan options
            if (!$this->skip_core_files) {
                $this->scan_core_files_chunked();
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Skipping core files scan (disabled by configuration)';
            }
            
            if (!$this->skip_plugins) {
                $this->scan_plugins_chunked();
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Skipping plugins scan (disabled by configuration)';
            }
            
            if (!$this->skip_themes) {
                $this->scan_themes_chunked();
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Skipping themes scan (disabled by configuration)';
            }
            
            if (!$this->skip_core_unknown) {
                $this->scan_core_unknown_files();
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Skipping core unknown files scan (disabled by configuration)';
            }
            
            // Scan files outside WordPress installation if enabled
            if ($this->scan_outside_enabled) {
                $this->scan_outside_wordpress();
            }
            
            $this->check_skipped_paths();
            
        // Calculate totals and provide detailed summary
        $this->calculate_totals();
        
        // Detailed issue breakdown in debug log
        $this->debug_log[] = '[Scan Summary] === DETAILED ISSUE BREAKDOWN ===';
        $this->debug_log[] = '[Scan Summary] DEBUG: modified_files = ' . $this->scan_results['modified_files'] . ', unknown_files = ' . $this->scan_results['unknown_files'];
        $this->debug_log[] = '[Scan Summary] Core file issues: ' . ($this->scan_results['modified_files'] + $this->scan_results['unknown_files']);
        $this->debug_log[] = '[Scan Summary] Plugin updates: ' . $this->scan_results['plugin_updates'];
        $this->debug_log[] = '[Scan Summary] Theme updates: ' . $this->scan_results['theme_updates'];
        $this->debug_log[] = '[Scan Summary] Theme integrity issues: ' . ($this->scan_results['theme_integrity_issues'] ?? 0);
        $this->debug_log[] = '[Scan Summary] Total issues found: ' . $this->scan_results['issues_found'];
        $this->debug_log[] = '[Scan Summary] Expected total: ' . 
            ($this->scan_results['modified_files'] + $this->scan_results['unknown_files'] + 
             $this->scan_results['plugin_updates'] + $this->scan_results['theme_updates'] + 
             ($this->scan_results['theme_integrity_issues'] ?? 0));
        
        // Add Intelligence Summary (Enhanced SHAC Analysis)
        $this->debug_log[] = '[Intelligence Summary] === SHAC THREAT INTELLIGENCE ===';
        $this->debug_log[] = '[Intelligence Summary] Files analyzed: ' . $this->shac_stats['files_processed'];
        $this->debug_log[] = '[Intelligence Summary] Suspicious patterns: ' . $this->shac_stats['suspicious_patterns_found'] . ' (high-risk PHP functions detected)';
        $this->debug_log[] = '[Intelligence Summary] High-risk files: ' . $this->shac_stats['high_risk_files'] . ' (multiple patterns or sensitive locations)';
        $this->debug_log[] = '[Intelligence Summary] NOTE: These are intelligence metrics, not security issues. Manual review recommended for high-risk files.';
        
        // Mark scan as completed
        $this->complete_scan($scan_id);            
        $this->debug_log[] = '[' . current_time('H:i:s') . '] File Changes Scan Complete - Found ' . $this->scan_results['issues_found'] . ' issues';
            
        } catch (Exception $e) {
            $this->debug_log[] = '[' . current_time('H:i:s') . '] SCAN ERROR: ' . $e->getMessage();
            $this->fail_scan($scan_id, $e->getMessage());
            throw $e;
        }
        
        // Add end log
        $scan_duration = round(microtime(true) - $start_time, 2);
        $this->debug_log[] = '[Scan Completed] File change scan finished - Files: ' . $this->scan_results['total_files_checked'] . ', Issues: ' . $this->scan_results['issues_found'] . ', Time: ' . $scan_duration . 's';
        
        // Update statistics collector with files scanned
        if (class_exists('VMPFence_Scan_Statistics_Collector')) {
            $stats_collector = VMPFence_Scan_Statistics_Collector::get_instance();
            $stats_collector->add_files_scanned($this->scan_results['total_files_checked']);
        }
        
        // Add SHAC statistics to scan results
        $this->scan_results['shac_statistics'] = [
            'files_processed' => $this->shac_stats['files_processed'],
            'suspicious_patterns_found' => $this->shac_stats['suspicious_patterns_found'],
            'high_risk_files' => $this->shac_stats['high_risk_files'],
            'avg_calculation_time' => $this->shac_stats['files_processed'] > 0 
                ? round(($this->shac_stats['total_calculation_time'] / $this->shac_stats['files_processed']) * 1000, 2) . 'ms'
                : '0ms',
            'total_shac_time' => round($this->shac_stats['total_calculation_time'], 3) . 's'
        ];
        
        // Add Threat Intelligence statistics to scan results
        $threat_stats = $this->threat_intelligence->get_threat_statistics();
        $this->scan_results['threat_intelligence'] = $threat_stats;
        
        // Add Unknown File Detection statistics to scan results
        $unknown_detection_stats = $this->unknown_file_detection->get_detection_stats();
        $this->scan_results['unknown_file_detection'] = $unknown_detection_stats;

        // Add Content Pattern Analysis statistics to scan results
        $content_analysis_stats = $this->content_pattern_analysis->get_analysis_stats();
        $this->scan_results['content_pattern_analysis'] = $content_analysis_stats;

        // Add Legitimacy Assessment statistics to scan results
        $legitimacy_assessment_stats = $this->legitimacy_assessment->get_assessment_stats();
        $this->scan_results['legitimacy_assessment'] = $legitimacy_assessment_stats;

        // Add Severity Rating System statistics to scan results
        $severity_rating_stats = $this->severity_rating->get_severity_stats();
        $this->scan_results['severity_rating'] = $severity_rating_stats;
        
        // Generate threat intelligence report
        $threat_report = $this->threat_intelligence->generate_threat_report($this->scan_results);
        $this->scan_results['threat_report'] = $threat_report;
        
        // Add SHAC summary to debug log
        if ($this->shac_stats['files_processed'] > 0) {
            $this->debug_log[] = '[SHAC Summary] Processed: ' . $this->shac_stats['files_processed'] . ' files, Patterns: ' . $this->shac_stats['suspicious_patterns_found'] . ', High-risk: ' . $this->shac_stats['high_risk_files'] . ', Avg time: ' . $this->scan_results['shac_statistics']['avg_calculation_time'];
        }
        
        // Add Threat Intelligence summary to debug log
        if (isset($threat_stats['pattern_matches']) && $threat_stats['pattern_matches'] > 0) {
            $this->debug_log[] = '[Threat Intelligence] Signatures: ' . $threat_stats['signatures_loaded'] . ', Matches: ' . $threat_stats['pattern_matches'] . ', Malware: ' . $threat_stats['malware_detected'] . ', Risk: ' . $threat_report['risk_assessment'];
        }
        
        // Add Unknown File Detection summary to debug log
        if (isset($unknown_detection_stats['files_analyzed']) && $unknown_detection_stats['files_analyzed'] > 0) {
            $this->debug_log[] = '[Unknown File Detection] Analyzed: ' . $unknown_detection_stats['files_analyzed'] . ', Unknown: ' . $unknown_detection_stats['unknown_files_found'] . ', Threats: ' . $unknown_detection_stats['threat_files'] . ', Legitimate: ' . $unknown_detection_stats['legitimate_unknown'];
        }
        
        // Add Content Pattern Analysis summary to debug log
        if (isset($content_analysis_stats['files_analyzed']) && $content_analysis_stats['files_analyzed'] > 0) {
            $this->debug_log[] = '[Content Analysis] Analyzed: ' . $content_analysis_stats['files_analyzed'] . ', Patterns: ' . $content_analysis_stats['content_patterns_found'] . ', High-risk: ' . $content_analysis_stats['high_risk_content'] . ', Avg time: ' . $content_analysis_stats['avg_analysis_time'];
        }
        
        // Add Legitimacy Assessment summary to debug log
        if (isset($legitimacy_assessment_stats['files_assessed']) && $legitimacy_assessment_stats['files_assessed'] > 0) {
            $this->debug_log[] = '[Legitimacy Assessment] Assessed: ' . $legitimacy_assessment_stats['files_assessed'] . ', Legitimate: ' . $legitimacy_assessment_stats['legitimate_files'] . ', Suspicious: ' . $legitimacy_assessment_stats['suspicious_files'] . ', Malicious: ' . $legitimacy_assessment_stats['malicious_files'] . ', Avg time: ' . $legitimacy_assessment_stats['avg_assessment_time'];
        }
        
        // Add Severity Rating System summary to debug log
        if (isset($severity_rating_stats['issues_rated']) && $severity_rating_stats['issues_rated'] > 0) {
            $this->debug_log[] = '[Severity Rating] Rated: ' . $severity_rating_stats['issues_rated'] . ', Critical: ' . $severity_rating_stats['critical_issues'] . ', High: ' . $severity_rating_stats['high_issues'] . ', Medium: ' . $severity_rating_stats['medium_issues'] . ', Low: ' . $severity_rating_stats['low_issues'] . ', Avg time: ' . $severity_rating_stats['avg_rating_time'];
        }
        
        // Add intelligence summary for frontend display
        $this->scan_results['intelligence_summary'] = [
            'title' => 'Threat Intelligence Analysis',
            'description' => 'Advanced pattern analysis and risk assessment (not security issues)',
            'files_analyzed' => $this->shac_stats['files_processed'],
            'patterns_detected' => $this->shac_stats['suspicious_patterns_found'],
            'high_risk_files' => $this->shac_stats['high_risk_files'],
            'risk_level' => $this->calculate_overall_risk_level(),
            'recommendation' => $this->get_intelligence_recommendation()
        ];
        
        // Apply performance controls to limit issues if enabled
        if (class_exists('VMPFence_Performance_Manager')) {
            if (isset($this->scan_results['issues'])) {
                $this->scan_results['issues'] = VMPFence_Performance_Manager::limit_issues($this->scan_results['issues']);
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Performance Manager: Limited issues to ' . count($this->scan_results['issues']);
            }
        }
        
        // Clear memory
        unset($this->wp_core_checksums);
        
        // Add debug log to results
        $this->scan_results['debug_log'] = $this->debug_log;
        
        return $this->scan_results;
    }
    
    /**
     * Initialize Known Files database if needed
     */
    private function initialize_known_files_if_needed() {
        if ($this->known_files->needs_update()) {
            $this->debug_log[] = '[Known Files] Database needs updating, building known files database...';
            
            // Build the known files database
            $result = $this->known_files->initialize_known_files();
            
            if ($result) {
                $stats = $this->known_files->get_known_files_stats();
                $this->debug_log[] = '[Known Files] Database built successfully: ' . $stats['total'] . ' total files tracked';
                $this->debug_log[] = '[Known Files] Core files: ' . ($stats['core'] ?? 0) . ', Plugin files: ' . ($stats['plugin'] ?? 0) . ', Theme files: ' . ($stats['theme'] ?? 0);
            } else {
                $this->debug_log[] = '[Known Files] WARNING: Failed to build known files database';
            }
        } else {
            $stats = $this->known_files->get_known_files_stats();
            $this->debug_log[] = '[Known Files] Using existing database with ' . $stats['total'] . ' tracked files';
        }
    }
    
    /**
     * Enhanced unknown file detection using Known Files database
     */
    private function is_file_known($file_path, $relative_path) {
        // First check if file is in Known Files database
        if ($this->known_files->is_known_file_enhanced($file_path, $relative_path)) {
            return true;
        }
        
        // Additional checks for legitimate file patterns that might not be in database yet
        if ($this->is_legitimate_file_pattern($relative_path)) {
            return true;
        }
        
        return false;
    }
    
    /**
     * Check for legitimate file patterns not yet in database
     */
    private function is_legitimate_file_pattern($relative_path) {
        // WordPress language files
        if (preg_match('/^wp-content\/languages\//i', $relative_path)) {
            return true;
        }
        
        // WordPress uploads directory
        if (preg_match('/^wp-content\/uploads\//i', $relative_path)) {
            return true;
        }
        
        // Cache directories
        if (preg_match('/\/cache\//i', $relative_path)) {
            return true;
        }
        
        // Backup directories
        if (preg_match('/\/backups?\//i', $relative_path)) {
            return true;
        }
        
        // Common configuration files
        $config_files = [
            '.htaccess',
            'wp-config.php',
            'robots.txt',
            'sitemap.xml',
            'favicon.ico'
        ];
        
        $filename = basename($relative_path);
        if (in_array($filename, $config_files)) {
            return true;
        }
        
        return false;
    }
    private function initialize_scan_session() {
        global $wpdb;
        
        // Clear previous scan issues and reset counters
        $this->clear_previous_scan_data();
        
        $table_name = $wpdb->prefix . 'vmpfence_scan_results';
        
        $wpdb->insert(
            $table_name,
            [
                'scan_type' => 'file_changes',
                'scan_time' => current_time('mysql'),
                'total_files' => 0,
                'issues_found' => 0,
                'scan_status' => 'running',
                'scan_data' => json_encode(['status' => 'initializing'])
            ],
            ['%s', '%s', '%d', '%d', '%s', '%s']
        );
        
        return $wpdb->insert_id;
    }
    
    /**
     * Clear previous scan data when starting a new scan
     */
    private function clear_previous_scan_data() {
        global $wpdb;
        
        // Clear previous scan issues (only file_changes issues, only non-ignored ones)
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        $deleted_issues = $wpdb->query($wpdb->prepare(
            "DELETE FROM {$issues_table} WHERE issue_type = %s AND status != 'ignored'", 'file_changes'  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        ));
        
        // Clear previous scan results
        $results_table = $wpdb->prefix . 'vmpfence_scan_results';
        $deleted_results = $wpdb->query($wpdb->prepare(
            "DELETE FROM {$results_table} WHERE scan_type = %s", 'file_changes'  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        ));
        
        // Reset scan statistics
        delete_option('vmpfence_scan_progress');
        delete_option('vmpfence_last_scan_results');
        
        // Reset internal counters
        $this->total_files = 0;
        $this->scan_results = [];
        $this->debug_log = [];
        
        // Reset cached file estimate to force recalculation
        $this->reset_file_estimate_cache();
        
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Previous scan data cleared, starting fresh scan';
    }
    
    /**
     * Reset the cached file estimate to force recalculation
     */
    private function reset_file_estimate_cache() {
        // This will force get_total_files_estimate() to recalculate
        $reflection = new ReflectionMethod($this, 'get_total_files_estimate');
        $reflection->setAccessible(true);
        
        // Clear the static cache by calling the method with a fresh state
        // We'll do this by temporarily setting a property to force recalculation
        $this->force_file_count_refresh = true;
    }
    
    /**
     * Scan WordPress core files in chunks
     */
    private function scan_core_files_chunked() {
        $this->debug_log[] = '[Core Files] Starting WordPress core files scan (excluding wp-content themes/plugins)';
        
        $checksums = $this->get_wordpress_checksums();
        
        // Scan ONLY WordPress core files (wp-admin, wp-includes, root PHP files)
        // NOT themes, plugins, or uploads - those have their own scan options
        $wordpress_root = ABSPATH;
        
        $this->debug_log[] = '[Core Files] Scanning WordPress core files only (wp-admin, wp-includes, root files)';
        $this->debug_log[] = '[Core Files] Retrieved ' . count($checksums) . ' checksums for WordPress ' . $this->wp_version;
        
        // First, collect core files only
        $all_files = [];
        $skipped_files = 0;
        
        // 1. Scan wp-admin directory
        $wp_admin_path = $wordpress_root . 'wp-admin';
        if (is_dir($wp_admin_path)) {
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($wp_admin_path, RecursiveDirectoryIterator::SKIP_DOTS)
            );
            
            foreach ($iterator as $file) {
                if ($file->isFile()) {
                    $file_path = $file->getPathname();
                    
                    // Skip files in excluded paths BEFORE adding to list
                    if ($this->should_skip_file($file_path)) {
                        $skipped_files++;
                        continue;
                    }
                    
                    $all_files[] = $file_path;
                }
            }
        }
        
        // 2. Scan wp-includes directory
        $wp_includes_path = $wordpress_root . 'wp-includes';
        if (is_dir($wp_includes_path)) {
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($wp_includes_path, RecursiveDirectoryIterator::SKIP_DOTS)
            );
            
            foreach ($iterator as $file) {
                if ($file->isFile()) {
                    $file_path = $file->getPathname();
                    
                    // Skip files in excluded paths BEFORE adding to list
                    if ($this->should_skip_file($file_path)) {
                        $skipped_files++;
                        continue;
                    }
                    
                    $all_files[] = $file_path;
                }
            }
        }
        
        // 3. Scan root PHP files (wp-config.php, wp-load.php, etc.)
        $root_files = glob($wordpress_root . '*.php');
        if ($root_files) {
            foreach ($root_files as $file_path) {
                if (!$this->should_skip_file($file_path)) {
                    $all_files[] = $file_path;
                } else {
                    $skipped_files++;
                }
            }
        }
        
        $this->debug_log[] = '[Core Files] Found ' . count($all_files) . ' total WordPress core files (skipped ' . $skipped_files . ' files in excluded paths)';
        $this->total_files = count($all_files);
        
        $files_checked = 0;
        
        // Adaptive chunk size based on cold start status
        $chunk_size = $this->is_cold_start ? 50 : 100; // Smaller chunks for cold start
        $chunk = [];
        
        $this->debug_log[] = '[Core Files] Using chunk size: ' . $chunk_size . ($this->is_cold_start ? ' (cold start optimization)' : '');
        
        foreach ($all_files as $file_path) {
            $chunk[] = $file_path;
            
            if (count($chunk) >= $chunk_size) {
                $this->debug_log[] = '[Core Files] Processing chunk of ' . count($chunk) . ' files (total checked: ' . $files_checked . ')';
                $this->process_core_file_chunk($chunk, $checksums);
                $files_checked += count($chunk);
                $chunk = [];
                
                // Update progress
                $this->update_scan_progress($files_checked, 'Scanning WordPress core files');
                
                // Prevent timeout
                if ($this->should_break_scan()) {
                    $this->debug_log[] = '[Core Files] TIMEOUT: Breaking scan to prevent execution timeout';
                    break;
                }
            }
        }
        
        // Process remaining files
        if (!empty($chunk)) {
            $this->debug_log[] = '[Core Files] Processing final chunk of ' . count($chunk) . ' files';
            $this->process_core_file_chunk($chunk, $checksums);
            $files_checked += count($chunk);
        }
        
        $this->debug_log[] = '[Core Files] WordPress core files scan completed. Total files checked: ' . $files_checked;
        $this->scan_results['core_files'] = $files_checked;
        $this->scan_results['total_files_checked'] += $files_checked;
    }
    
    /**
     * Process a chunk of core files (Enhanced with Repository Verification)
     */
    private function process_core_file_chunk($files, $checksums) {
        $chunk_modified = 0;
        $chunk_unknown = 0;
        $chunk_verified = 0;
        
        // If no checksums available, skip verification but log warning
        if (empty($checksums)) {
            $this->debug_log[] = '[Core Files] WARNING: No checksums available - skipping repository verification';
            foreach ($files as $file) {
                $relative_path = str_replace(ABSPATH, '', $file);
                $this->debug_log[] = '[Core Files] SKIP: No checksums for verification: ' . $relative_path;
            }
            return;
        }
        
        $processed_files = 0;
        foreach ($files as $file) {
            // Performance throttling for file processing
            if (class_exists('VMPFence_Performance_Manager')) {
                VMPFence_Performance_Manager::throttle_processing($processed_files);
            }
            $processed_files++;
            
            // Normalize paths for cross-platform compatibility
            $normalized_file = str_replace('\\', '/', $file);
            $normalized_abspath = str_replace('\\', '/', ABSPATH);
            $relative_path = str_replace($normalized_abspath, '', $normalized_file);
            
            // Skip large files to prevent memory issues
            $file_size = filesize($file);
            if ($file_size > 5 * 1024 * 1024) { // Skip files > 5MB
                $this->debug_log[] = '[Core Files] SKIP: Large file (' . size_format($file_size) . '): ' . $relative_path;
                continue;
            }
            
            // Classify file type for enhanced analysis
            $file_type = $this->classify_file_type($relative_path, $checksums);
            
            $file_hash = md5_file($file);
            
            // Enhanced SHAC calculation for security analysis
            $shac_info = $this->calculate_enhanced_shac($file, $relative_path);
            
            // Content Pattern Analysis for all files
            $content_analysis = $this->content_pattern_analysis->analyze_file_content($file, $relative_path);
            
            // Repository-based verification
            if (isset($checksums[$relative_path])) {
                // File exists in WordPress checksums - verify integrity
                if ($checksums[$relative_path] !== $file_hash) {
                    $this->debug_log[] = '[Core Files] ISSUE: Modified WordPress core file: ' . $relative_path;
                    $this->debug_log[] = '[Core Files] Expected (repository): ' . substr($checksums[$relative_path], 0, 16) . '...';
                    $this->debug_log[] = '[Core Files] Actual (file): ' . substr($file_hash, 0, 16) . '...';
                    
                    // Add SHAC information to debug log
                    if ($shac_info) {
                        $this->debug_log[] = '[Core Files] SHAC: ' . $shac_info['shac_short'] . ' | Patterns: ' . implode(', ', $shac_info['suspicious_patterns']);
                    }
                    
                    // Determine severity based on file type
                    $severity = 'high'; // Core file modifications are serious
                    if (strpos($relative_path, 'wp-admin/') === 0 || strpos($relative_path, 'wp-includes/') === 0) {
                        $severity = 'critical'; // Core system files are critical
                    }
                    
                    // Include SHAC info in issue metadata
                    $issue_metadata = [
                        'expected_hash' => $checksums[$relative_path],
                        'actual_hash' => $file_hash,
                        'file_type' => $file_type,
                        'severity' => $severity,
                        'repository_verified' => true
                    ];
                    
                    // Add SHAC information to scan results
                    if ($shac_info) {
                        $issue_metadata['shac_hash'] = $shac_info['shac_hash'];
                        $issue_metadata['suspicious_patterns'] = $shac_info['suspicious_patterns'];
                        $issue_metadata['shac_analysis'] = $shac_info['analysis'];
                    }
                    
                    // Add Content Pattern Analysis to issue metadata
                    if ($content_analysis && $content_analysis['risk_score'] > 0) {
                        $issue_metadata['content_analysis'] = [
                            'threat_level' => $content_analysis['threat_level'],
                            'risk_score' => $content_analysis['risk_score'],
                            'patterns_found' => $content_analysis['patterns_found'],
                            'analysis_details' => $content_analysis['analysis_details']
                        ];
                        
                        // If content analysis indicates high risk, upgrade issue description
                        if ($content_analysis['should_create_issue']) {
                            $content_issue_desc = $this->content_pattern_analysis->generate_content_issue_description($content_analysis);
                            $this->log_file_issue($file, 'malicious_content', $content_issue_desc, $issue_metadata);
                            $this->debug_log[] = '[Content Analysis] MALICIOUS CONTENT: ' . $relative_path . ' (Risk Score: ' . $content_analysis['risk_score'] . ')';
                        }
                    }
                    
                    // Legitimacy Assessment for modified files
                    $legitimacy_context = [
                        'repository_verified' => true,
                        'change_type' => 'modification',
                        'file_type' => $file_type,
                        'content_analysis' => $content_analysis,
                        'is_known_file' => $this->is_file_known($file, $relative_path)
                    ];
                    
                    $legitimacy_assessment = $this->legitimacy_assessment->assess_file_legitimacy($file, $relative_path, $legitimacy_context);
                    
                    // Add legitimacy assessment to issue metadata
                    $issue_metadata['legitimacy_assessment'] = [
                        'legitimacy_level' => $legitimacy_assessment['legitimacy_level'],
                        'legitimacy_score' => $legitimacy_assessment['legitimacy_score'],
                        'confidence' => $legitimacy_assessment['confidence'],
                        'recommendation' => $legitimacy_assessment['recommendation']
                    ];
                    
                    // Create separate legitimacy issue if assessment is concerning
                    if ($this->legitimacy_assessment->should_create_legitimacy_issue($legitimacy_assessment)) {
                        $legitimacy_desc = $this->legitimacy_assessment->generate_legitimacy_issue_description($legitimacy_assessment);
                        $this->log_file_issue($file, 'legitimacy_concern', $legitimacy_desc, $issue_metadata);
                        $this->debug_log[] = '[Legitimacy Assessment] CONCERN: ' . $relative_path . ' (Level: ' . $legitimacy_assessment['legitimacy_level'] . ', Score: ' . $legitimacy_assessment['legitimacy_score'] . ')';
                    }
                    
                    $this->log_file_issue($file, 'modified', 'WordPress core file has been modified and differs from the official repository version', $issue_metadata);
                    $this->scan_results['modified_files']++;
                    $chunk_modified++;
                } else {
                    // File is correct - verified against repository
                    $this->debug_log[] = '[Core Files] OK: Core file verified against repository: ' . $relative_path;
                    $chunk_verified++;
                }
            } else {
                // File not in WordPress checksums - enhanced analysis with Unknown File Detection Engine
                
                // Use Unknown File Detection Engine for comprehensive analysis
                $unknown_analysis = $this->unknown_file_detection->analyze_unknown_file($file, $relative_path);
                
                // Only create database issues for actual threats (not all unknown files)
                if ($unknown_analysis['should_create_issue']) {
                    $this->debug_log[] = '[Core Files] THREAT: Unknown file flagged as security threat: ' . $relative_path . ' (Level: ' . $unknown_analysis['threat_level'] . ')';
                    
                    // Generate comprehensive issue description
                    $issue_description = $this->unknown_file_detection->generate_issue_description($unknown_analysis);
                    
                    // Determine severity mapping
                    $severity_map = [
                        'critical' => 'critical',
                        'high' => 'high',
                        'medium' => 'medium',
                        'low' => 'low'
                    ];
                    $severity = $severity_map[$unknown_analysis['threat_level']] ?? 'medium';
                    
                    // Enhanced metadata for unknown file threats
                    $issue_metadata = [
                        'file_type' => $file_type,
                        'severity' => $severity,
                        'threat_level' => $unknown_analysis['threat_level'],
                        'classification' => $unknown_analysis['classification'],
                        'threat_reasons' => $unknown_analysis['reasons'],
                        'location_analysis' => $this->analyze_file_location($relative_path)
                    ];
                    
                    // Add SHAC information if available
                    if ($shac_info) {
                        $issue_metadata['shac_hash'] = $shac_info['shac_hash'];
                        $issue_metadata['suspicious_patterns'] = $shac_info['suspicious_patterns'];
                        $issue_metadata['shac_analysis'] = $shac_info['analysis'];
                    }
                    
                    // Add Content Pattern Analysis to issue metadata
                    if ($content_analysis && $content_analysis['risk_score'] > 0) {
                        $issue_metadata['content_analysis'] = [
                            'threat_level' => $content_analysis['threat_level'],
                            'risk_score' => $content_analysis['risk_score'],
                            'patterns_found' => $content_analysis['patterns_found'],
                            'analysis_details' => $content_analysis['analysis_details']
                        ];
                        
                        // If content analysis indicates critical risk, create separate content issue
                        if ($content_analysis['should_create_issue']) {
                            $content_issue_desc = $this->content_pattern_analysis->generate_content_issue_description($content_analysis);
                            $this->log_file_issue($file, 'malicious_content', $content_issue_desc, $issue_metadata);
                            $this->debug_log[] = '[Content Analysis] MALICIOUS CONTENT: ' . $relative_path . ' (Risk Score: ' . $content_analysis['risk_score'] . ')';
                        }
                    }
                    
                    // Legitimacy Assessment for unknown threat files
                    $legitimacy_context = [
                        'repository_verified' => false,
                        'change_type' => 'unknown_file',
                        'file_type' => $file_type,
                        'content_analysis' => $content_analysis,
                        'unknown_analysis' => $unknown_analysis,
                        'is_known_file' => $this->is_file_known($file, $relative_path)
                    ];
                    
                    $legitimacy_assessment = $this->legitimacy_assessment->assess_file_legitimacy($file, $relative_path, $legitimacy_context);
                    
                    // Add legitimacy assessment to issue metadata
                    $issue_metadata['legitimacy_assessment'] = [
                        'legitimacy_level' => $legitimacy_assessment['legitimacy_level'],
                        'legitimacy_score' => $legitimacy_assessment['legitimacy_score'],
                        'confidence' => $legitimacy_assessment['confidence'],
                        'recommendation' => $legitimacy_assessment['recommendation']
                    ];
                    
                    $this->log_file_issue($file, 'unknown_threat', $issue_description, $issue_metadata);
                    $this->scan_results['unknown_files']++;
                    $chunk_unknown++;
                } else {
                    // File is unknown but not a threat - log for intelligence purposes only
                    $classification_msg = [
                        'known_legitimate' => 'File found in Known Files database',
                        'legitimate_unknown' => 'Legitimate file pattern (development, config, etc.)',
                        'unknown_benign' => 'Unknown file with no immediate threat indicators'
                    ];
                    $msg = $classification_msg[$unknown_analysis['classification']] ?? 'Unknown file classified as safe';
                    
                    $this->debug_log[] = '[Core Files] SAFE: ' . $relative_path . ' - ' . $msg;
                }
            }
        }
        
        if ($chunk_modified > 0 || $chunk_unknown > 0 || $chunk_verified > 0) {
            $this->debug_log[] = '[Core Files] Chunk results: ' . $chunk_verified . ' verified, ' . $chunk_modified . ' modified, ' . $chunk_unknown . ' unknown files';
            $this->debug_log[] = '[Core Files] Running totals - Modified: ' . $this->scan_results['modified_files'] . ', Unknown: ' . $this->scan_results['unknown_files'] . ', Total Issues: ' . $this->scan_results['issues_found'];
        }
    }
    
    /**
     * Analyze file location for security assessment
     */
    private function analyze_file_location($relative_path) {
        $analysis = [];
        
        if (strpos($relative_path, 'wp-admin/') === 0) {
            $analysis['location'] = 'WordPress Admin Directory';
            $analysis['risk_level'] = 'high';
            $analysis['reason'] = 'Files in wp-admin should only be official WordPress files';
        } elseif (strpos($relative_path, 'wp-includes/') === 0) {
            $analysis['location'] = 'WordPress Core Includes';
            $analysis['risk_level'] = 'high';
            $analysis['reason'] = 'Files in wp-includes should only be official WordPress files';
        } elseif (strpos($relative_path, 'wp-content/uploads/') === 0) {
            $analysis['location'] = 'Uploads Directory';
            $analysis['risk_level'] = 'critical';
            $analysis['reason'] = 'Executable files in uploads directory indicate compromise';
        } else {
            $analysis['location'] = 'Other WordPress Directory';
            $analysis['risk_level'] = 'medium';
            $analysis['reason'] = 'Unknown file in WordPress installation';
        }
        
        return $analysis;
    }
    
    /**
     * Scan plugins in chunks with repository verification
     */
    private function scan_plugins_chunked() {
        $this->debug_log[] = '[Plugins] Starting plugin update and repository integrity scan (Plugin Repository Verification)';
        
        $active_plugins = get_option('active_plugins', []);
        $all_plugins = get_plugins(); // Get all plugins (active and inactive)
        $plugin_count = count($all_plugins);
        $this->debug_log[] = '[Plugins] Found ' . $plugin_count . ' total plugins (' . count($active_plugins) . ' active)';
        
        // Check for plugin updates
        $plugin_updates = get_site_transient('update_plugins');
        $files_checked = 0;
        $updates_found = 0;
        $integrity_issues = 0;
        
        // First, check for available updates
        if ($plugin_updates && !empty($plugin_updates->response)) {
            $this->debug_log[] = '[Plugins] Checking ' . count($plugin_updates->response) . ' plugins for updates';
            foreach ($plugin_updates->response as $plugin_file => $update_data) {
                // Check if plugin should be excluded based on file path
                // Convert plugin file to relative path format (e.g., "plugin-dir/plugin.php" -> "wp-content/plugins/plugin-dir")
                $plugin_dir = dirname($plugin_file);
                $plugin_relative_path = 'wp-content/plugins/' . $plugin_dir;
                
                $this->debug_log[] = '[Plugins] Checking exclusion for: ' . $plugin_relative_path;
                if ($this->should_skip_file($plugin_relative_path)) {
                    $this->debug_log[] = '[Plugins] Skipped plugin update check (excluded): ' . $plugin_file;
                    continue;
                }
                $this->debug_log[] = '[Plugins] Processing plugin update: ' . $plugin_file;
                $plugin_name = $this->get_plugin_name($plugin_file);
                $current_version = $this->get_plugin_version($plugin_file);
                $new_version = $update_data->new_version ?? 'Unknown';
                
                // Get plugin slug for URL generation
                $plugin_slug = dirname($plugin_file);
                
                // Build comprehensive metadata
                $metadata = [
                    'current_version' => $current_version,
                    'new_version' => $new_version,
                    'plugin_name' => $plugin_name,
                    'plugin_slug' => $plugin_slug,
                    'plugin_url' => $update_data->url ?? "https://wordpress.org/plugins/{$plugin_slug}/",
                    'changelog_url' => "https://wordpress.org/plugins/{$plugin_slug}/#developers",
                    'update_package' => $update_data->package ?? '',
                    'requires' => $update_data->requires ?? '',
                    'tested' => $update_data->tested ?? '',
                    'requires_php' => $update_data->requires_php ?? '',
                    'security_update' => isset($update_data->security_update) ? ($update_data->security_update ? 'Yes' : 'No') : '',
                    'details_text' => "You need to upgrade '{$plugin_name}' to the newest version to ensure you have any security fixes the developer has released."
                ];
                
                $this->debug_log[] = '[Plugins] ISSUE: Plugin update available: ' . $plugin_name . ' (' . $current_version . ' -> ' . $new_version . ')';
                
                $this->log_file_issue('plugin:' . $plugin_file, 'plugin_update', "Plugin '{$plugin_name}' needs an upgrade ({$current_version} -> {$new_version})", $metadata);
                $updates_found++;
            }
        }
        
        $this->debug_log[] = '[Plugins] Found ' . $updates_found . ' plugin updates available';
        $this->scan_results['plugin_updates'] = $updates_found;
        
        // Plugin Repository Integrity Verification
        $this->debug_log[] = '[Plugins] Starting repository integrity verification for WordPress.org plugins';
        $integrity_issues += $this->verify_plugin_repository_integrity($active_plugins);
        
        // Count files in a few plugins for statistics (but don't flag as issues)
        foreach (array_slice($active_plugins, 0, 3) as $plugin) { // Check first 3 plugins for file count
            $plugin_dir = dirname(WP_PLUGIN_DIR . '/' . $plugin);
            $plugin_name = dirname($plugin);
            
            if (!is_dir($plugin_dir)) {
                continue;
            }
            
            $plugin_files = $this->get_directory_files_limited($plugin_dir, 30); // Limit files per plugin
            $files_checked += count($plugin_files);
            
            $this->debug_log[] = '[Plugins] Scanned ' . count($plugin_files) . ' files in plugin: ' . $plugin_name;
            
            if ($this->should_break_scan()) {
                $this->debug_log[] = '[Plugins] TIMEOUT: Breaking plugin scan to prevent execution timeout';
                break;
            }
        }
        
        $this->debug_log[] = '[Plugins] Plugin scan completed. Plugins checked: ' . $plugin_count . ', Files scanned: ' . $files_checked . ', Updates found: ' . $updates_found . ', Integrity issues: ' . $integrity_issues;
        $this->scan_results['plugins'] = $plugin_count; // Store plugin count, not file count
        $this->scan_results['plugin_integrity_issues'] = $integrity_issues;
        $this->scan_results['total_files_checked'] += $files_checked;
    }
    
    /**
     * Scan themes in chunks
     */
    private function scan_themes_chunked() {
        $this->debug_log[] = '[Themes] Starting theme update and integrity scan';
        
        // Get all themes
        $all_themes = wp_get_themes();
        $theme_count = count($all_themes);
        $this->debug_log[] = '[Themes] Found ' . $theme_count . ' total themes';
        
        // Check for theme updates
        $theme_updates = get_site_transient('update_themes');
        $files_checked = 0;
        $updates_found = 0;
        
        if ($theme_updates && !empty($theme_updates->response)) {
            $this->debug_log[] = '[Themes] Checking ' . count($theme_updates->response) . ' themes for updates';
            foreach ($theme_updates->response as $theme_slug => $update_data) {
                // Check if theme should be excluded based on file path
                $theme_relative_path = 'wp-content/themes/' . $theme_slug;
                
                $this->debug_log[] = '[Themes] Checking exclusion for: ' . $theme_relative_path;
                if ($this->should_skip_file($theme_relative_path)) {
                    $this->debug_log[] = '[Themes] Skipped theme update check (excluded): ' . $theme_slug;
                    continue;
                }
                $this->debug_log[] = '[Themes] Processing theme update: ' . $theme_slug;
                
                $theme = wp_get_theme($theme_slug);
                $theme_name = $theme->get('Name') ?: $theme_slug;
                $current_version = $theme->get('Version') ?: 'Unknown';
                $new_version = $update_data['new_version'] ?? 'Unknown';
                
                // Build comprehensive metadata
                $metadata = [
                    'current_version' => $current_version,
                    'new_version' => $new_version,
                    'theme_name' => $theme_name,
                    'theme_slug' => $theme_slug,
                    'theme_url' => $update_data['url'] ?? "https://wordpress.org/themes/{$theme_slug}/",
                    'changelog_url' => "https://wordpress.org/themes/{$theme_slug}/#developers",
                    'update_package' => $update_data['package'] ?? '',
                    'requires' => $update_data['requires'] ?? '',
                    'tested' => $update_data['tested'] ?? '',
                    'requires_php' => $update_data['requires_php'] ?? '',
                    'security_update' => isset($update_data['security_update']) ? ($update_data['security_update'] ? 'Yes' : 'No') : '',
                    'details_text' => "You need to upgrade '{$theme_name}' to the newest version to ensure you have any security fixes the developer has released."
                ];
                
                $this->debug_log[] = '[Themes] ISSUE: Theme update available: ' . $theme_name . ' (' . $current_version . ' -> ' . $new_version . ')';
                
                $this->log_file_issue('theme:' . $theme_slug, 'theme_update', "Theme '{$theme_name}' needs an upgrade ({$current_version} -> {$new_version})", $metadata);
                $updates_found++;
            }
        }
        
        $this->debug_log[] = '[Themes] Found ' . $updates_found . ' theme updates available';
        $this->scan_results['theme_updates'] = $updates_found;
        
        // Theme Repository Verification
        $this->debug_log[] = '[Themes] Starting repository integrity verification for WordPress.org themes';
        $integrity_issues = $this->verify_theme_repository_integrity($all_themes);
        $this->scan_results['theme_integrity_issues'] = $integrity_issues;
        
        // Count files in active theme for statistics (but don't flag as issues)
        $current_theme = get_stylesheet();
        $theme_dir = get_theme_root() . '/' . $current_theme;
        
        if (is_dir($theme_dir)) {
            $theme_files = $this->get_directory_files_limited($theme_dir, 50);
            $files_checked = count($theme_files);
            $this->debug_log[] = '[Themes] Scanned ' . $files_checked . ' files in active theme: ' . $current_theme;
        }
        
        $this->debug_log[] = '[Themes] Theme scan completed. Themes checked: ' . $theme_count . ', Files scanned: ' . $files_checked . ', Updates found: ' . $updates_found . ', Integrity issues: ' . $integrity_issues;
        $this->scan_results['themes'] = $theme_count; // Store theme count, not file count
        $this->scan_results['total_files_checked'] += $files_checked;
    }
    
    /**
     * Check for skipped paths due to scan settings
     */
    private function check_skipped_paths() {
        $this->debug_log[] = '[Skipped Paths] Checking for paths skipped due to scan settings';
        
        // Common paths that might be skipped in production
        $potential_skipped_paths = [
            'wp-content/uploads/',
            'wp-content/cache/',
            'wp-content/backup/',
            '.git/',
            'node_modules/'
        ];
        
        $skipped_count = 0;
        foreach ($potential_skipped_paths as $path) {
            $full_path = ABSPATH . $path;
            if (is_dir($full_path)) {
                // Simulate skipped path
                $this->debug_log[] = '[Skipped Paths] Path skipped due to scan settings: ' . $path;
                
                // Note: Only log to debug, don't save to database as these aren't real issues
                // $this->log_file_issue('skipped:' . $path, 'skipped_path', 'Path skipped for the malware scan due to scan settings', [
                //     'path' => $path,
                //     'reason' => 'Excluded from scan settings'
                // ]);
                
                $skipped_count++;
            }
        }
        
        if ($skipped_count > 0) {
            $this->debug_log[] = '[Skipped Paths] Found ' . $skipped_count . ' paths skipped due to scan settings';
        } else {
            $this->debug_log[] = '[Skipped Paths] No paths were skipped';
        }
    }
    
    /**
     * Check if a file path should be skipped during scanning
     * 
     * @param string $file_path Full file path
     * @return bool True if file should be skipped
     */
    private function should_skip_file($file_path) {
        // If the path is already relative (doesn't start with absolute path), use it as-is
        if (strpos($file_path, ABSPATH) !== 0 && strpos($file_path, 'wp-content/') === 0) {
            $relative_path = $file_path;
            $this->debug_log[] = '[File Skip] Using path as relative: ' . $relative_path;
        } else {
            // Normalize file path for absolute paths
            $normalized_file = str_replace('\\', '/', $file_path);
            
            // Normalize WordPress root path 
            $wordpress_root = str_replace('\\', '/', ABSPATH);
            $wordpress_root = rtrim($wordpress_root, '/') . '/'; // Ensure trailing slash
            
            // Get relative path from WordPress root
            if (strpos($normalized_file, $wordpress_root) === 0) {
                $relative_path = substr($normalized_file, strlen($wordpress_root));
            } else {
                // Fallback: try without trailing slash
                $wordpress_root_no_slash = rtrim($wordpress_root, '/');
                if (strpos($normalized_file, $wordpress_root_no_slash) === 0) {
                    $relative_path = substr($normalized_file, strlen($wordpress_root_no_slash));
                    $relative_path = ltrim($relative_path, '/');
                } else {
                    // Can't determine relative path, don't skip
                    return false;
                }
            }
        }
        
        // Paths that should be skipped (matching check_skipped_paths)
        $skipped_patterns = [
            'wp-content/uploads/',
            'wp-content/cache/',
            'wp-content/backup/',
            '.git/',
            'node_modules/'
        ];
        
        foreach ($skipped_patterns as $pattern) {
            if (strpos($relative_path, $pattern) === 0) {
                return true;
            }
        }
        
        // Check user-defined exclusion patterns from scan options
        if (isset($this->scan_options['scan_exclude']) && !empty($this->scan_options['scan_exclude'])) {
            $this->debug_log[] = '[File Skip] Checking exclusion patterns for: ' . $relative_path;
            $this->debug_log[] = '[File Skip] Available patterns: ' . $this->scan_options['scan_exclude'];
            
            // Split by any whitespace (spaces, tabs, newlines) and filter out empty values
            $exclusion_patterns = preg_split('/\s+/', trim($this->scan_options['scan_exclude']));
            $exclusion_patterns = array_filter($exclusion_patterns); // Remove empty elements
            
            $this->debug_log[] = '[File Skip] Parsed patterns: ' . implode(', ', $exclusion_patterns);
            
            foreach ($exclusion_patterns as $pattern) {
                $pattern = trim($pattern);
                
                // Skip empty patterns
                if (empty($pattern)) {
                    continue;
                }
                
                // Skip universal wildcard (would exclude everything)
                if ($pattern === '*') {
                    continue;
                }
                
                // Convert wildcard pattern to regex pattern
                $regex_pattern = preg_quote($pattern, '/');
                $regex_pattern = str_replace('\*', '.*', $regex_pattern);
                
                // Check different matching scenarios:
                
                // 1. Exact relative path match (e.g., "wp-config-sample.php" matches "wp-config-sample.php")
                if (preg_match('/^' . $regex_pattern . '$/i', $relative_path)) {
                    $this->debug_log[] = '[File Skip] Excluded by user pattern "' . $pattern . '" (full path): ' . $relative_path;
                    return true;
                }
                
                // 2. Filename-only match (e.g., "index.php" matches any "index.php" anywhere)
                $filename = basename($relative_path);
                if (preg_match('/^' . $regex_pattern . '$/i', $filename)) {
                    $this->debug_log[] = '[File Skip] Excluded by user pattern "' . $pattern . '" (filename): ' . $relative_path;
                    return true;
                }
                
                // 3. Directory prefix match (e.g., "wp-content/uploads/*" matches files in that directory)
                if (strpos($pattern, '*') !== false) {
                    // For patterns ending with /* or containing *, check if path starts with the prefix
                    $prefix_pattern = str_replace('*', '', $pattern);
                    $prefix_pattern = rtrim($prefix_pattern, '/');
                    
                    if (!empty($prefix_pattern)) {
                        $dir_prefix = $prefix_pattern . '/';
                        if (strpos($relative_path, $dir_prefix) === 0) {
                            $this->debug_log[] = '[File Skip] Excluded by user pattern "' . $pattern . '" (directory prefix): ' . $relative_path;
                            return true;
                        }
                        
                        // Also check if the path matches exactly (for directory names without trailing slash)
                        if ($relative_path === $prefix_pattern) {
                            $this->debug_log[] = '[File Skip] Excluded by user pattern "' . $pattern . '" (exact directory): ' . $relative_path;
                            return true;
                        }
                    }
                }
            }
        }
        
        return false;
    }
    
    /**
     * Scan wp-admin and wp-includes for files not bundled with WordPress
     * This identifies unknown/suspicious files in core directories
     */
    private function scan_core_unknown_files() {
        $this->debug_log[] = '[Core Unknown] Starting scan for unknown files in wp-admin and wp-includes';
        
        $checksums = $this->get_wordpress_checksums();
        if (empty($checksums)) {
            $this->debug_log[] = '[Core Unknown] WARNING: No checksums available - cannot identify unknown files';
            return;
        }
        
        $wordpress_root = ABSPATH;
        $core_directories = ['wp-admin', 'wp-includes'];
        $unknown_files_found = 0;
        $files_checked = 0;
        
        $this->debug_log[] = '[Core Unknown] Retrieved ' . count($checksums) . ' known core file checksums for WordPress ' . $this->wp_version;
        
        foreach ($core_directories as $dir) {
            $dir_path = $wordpress_root . $dir;
            if (!is_dir($dir_path)) {
                continue;
            }
            
            $this->debug_log[] = '[Core Unknown] Scanning directory: ' . $dir;
            
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($dir_path, RecursiveDirectoryIterator::SKIP_DOTS)
            );
            
            foreach ($iterator as $file) {
                if ($file->isFile()) {
                    $file_path = $file->getPathname();
                    
                    // Skip files in excluded paths
                    if ($this->should_skip_file($file_path)) {
                        continue;
                    }
                    
                    // Get relative path from WordPress root
                    // $original_file_path = $file_path;
                    // $original_abspath = ABSPATH;
                    $relative_path = str_replace(ABSPATH, '', $file_path);
                    $relative_path = str_replace('\\', '/', $relative_path);
                    
                    // Log path processing details for debugging
                    // if (strpos(basename($file_path), 'media-button') !== false) {
                    //     $this->debug_log[] = '[PATH DEBUG] Original file: ' . $original_file_path;
                    //     $this->debug_log[] = '[PATH DEBUG] ABSPATH: [' . $original_abspath . ']';
                    //     $this->debug_log[] = '[PATH DEBUG] After ABSPATH replace: [' . str_replace(ABSPATH, '', $file_path) . ']';
                    //     $this->debug_log[] = '[PATH DEBUG] Final relative path: [' . $relative_path . ']';
                    //     $this->debug_log[] = '[PATH DEBUG] Checksum lookup key: [' . $relative_path . ']';
                    //     $this->debug_log[] = '[PATH DEBUG] Exists in checksums: ' . (isset($checksums[$relative_path]) ? 'YES' : 'NO');
                    //     if (isset($checksums[$relative_path])) {
                    //         $this->debug_log[] = '[PATH DEBUG] Expected hash: ' . $checksums[$relative_path];
                    //     }
                    // }
                    
                    $files_checked++;
                    
                    // Check if this file is in WordPress checksums (known core file)
                    if (!isset($checksums[$relative_path])) {
                        // This is an unknown file in wp-admin or wp-includes
                        $unknown_files_found++;
                        
                        // Check if it's in the Known Files database (might be safe)
                        $is_known_safe = $this->known_files->is_known_file($file_path);
                        
                        if ($is_known_safe) {
                            $this->debug_log[] = '[Core Unknown] SAFE: Unknown file but found in Known Files database: ' . $relative_path;
                        } else {
                            $this->debug_log[] = '[Core Unknown] ISSUE: Unknown file in core directory (not bundled with WordPress): ' . $relative_path;
                            
                            // Increment unknown files counter
                            $this->scan_results['unknown_files']++;
                            
                            // Save issue to database
                            $this->log_file_issue(
                                $file_path,
                                'core_unknown',
                                'Unknown file in core directory',
                                "File found in WordPress core directory but not part of official WordPress distribution: {$relative_path}"
                            );
                        }
                        
                        // Update SHAC statistics for unknown files
                        $this->shac_stats['files_processed']++;
                        
                        // Basic pattern analysis for unknown files
                        $file_content = @file_get_contents($file_path);
                        if ($file_content && strlen($file_content) < 1024 * 1024) { // Only analyze files < 1MB
                            // Load suspicious patterns from JSON
                            require_once plugin_dir_path(__FILE__) . 'class-signature-loader.php';
                            $loader = VMPFence_Signature_Loader::get_instance();
                            $high_risk_functions = $loader->get('high_risk_functions');
                            
                            // Check for suspicious patterns
                            $suspicious_patterns = array_slice($high_risk_functions, 0, 5); // Get first 5 functions
                            foreach ($suspicious_patterns as $pattern) {
                                if (stripos($file_content, $pattern . '(') !== false) {
                                    $this->shac_stats['suspicious_patterns_found']++;
                                    $this->shac_stats['high_risk_files']++;
                                    break;
                                }
                            }
                        }
                    } else {
                        // This is a known WordPress core file, skip it
                        continue;
                    }
                    
                    // Update progress periodically
                    if ($files_checked % 100 === 0) {
                        $this->update_scan_progress($files_checked, 'Scanning core directories for unknown files');
                    }
                    
                    // Prevent timeout
                    if ($this->should_break_scan()) {
                        $this->debug_log[] = '[Core Unknown] TIMEOUT: Breaking scan to prevent execution timeout';
                        break 2;
                    }
                }
            }
        }
        
        $this->debug_log[] = '[Core Unknown] Core unknown files scan completed. Files checked: ' . $files_checked . ', Unknown files found: ' . $unknown_files_found;
        $this->scan_results['total_files_checked'] += $files_checked;
    }
    
    /**
     * Scan files outside WordPress installation
     */
    private function scan_outside_wordpress() {
        $this->debug_log[] = '[External Files] Starting scan outside WordPress installation';
        
        $outside_files_checked = 0;
        $outside_issues_found = 0;
        
        try {
            // Determine the path outside WordPress
            $wp_path = ABSPATH;
            $parent_path = dirname($wp_path);
            
            // Also check document root if available and different from parent
            $document_root = isset($_SERVER['DOCUMENT_ROOT']) ? sanitize_text_field(wp_unslash($_SERVER['DOCUMENT_ROOT'])) : null;
            
            $scan_paths = [];
            
            // Add parent directory if it exists and is readable
            if ($parent_path && $parent_path !== $wp_path && is_dir($parent_path) && is_readable($parent_path)) {
                $scan_paths[] = [
                    'path' => $parent_path,
                    'description' => 'Parent directory of WordPress installation'
                ];
            }
            
            // Add document root if it's different from parent and WordPress paths
            if ($document_root && 
                $document_root !== $wp_path && 
                $document_root !== $parent_path && 
                is_dir($document_root) && 
                is_readable($document_root)) {
                $scan_paths[] = [
                    'path' => $document_root,
                    'description' => 'Web server document root'
                ];
            }
            
            if (empty($scan_paths)) {
                $this->debug_log[] = '[External Files] No valid paths found outside WordPress installation';
                return;
            }
            
            foreach ($scan_paths as $scan_path_info) {
                $scan_path = $scan_path_info['path'];
                $description = $scan_path_info['description'];
                
                $this->debug_log[] = "[External Files] Scanning {$description}: {$scan_path}";
                
                // Get files in the outside directory (non-recursive for safety)
                $files = $this->get_outside_directory_files($scan_path);
                
                foreach ($files as $file_path) {
                    $outside_files_checked++;
                    
                    // Skip if it's the WordPress directory itself
                    if (realpath($file_path) === realpath($wp_path) || 
                        strpos(realpath($file_path), realpath($wp_path) . DIRECTORY_SEPARATOR) === 0) {
                        continue;
                    }
                    
                    // Check if file is suspicious
                    if ($this->is_outside_file_suspicious($file_path)) {
                        $outside_issues_found++;
                        
                        $relative_path = str_replace($scan_path, '', $file_path);
                        $relative_path = ltrim($relative_path, DIRECTORY_SEPARATOR);
                        
                        $this->debug_log[] = "[External Files] SUSPICIOUS: {$relative_path} outside WordPress installation";
                        
                        // Log the issue
                        $this->log_file_issue($file_path, 'suspicious_external_file', 
                            "Suspicious file found outside WordPress installation", [
                                'location' => $description,
                                'relative_path' => $relative_path,
                                'reason' => 'File found outside WordPress installation with suspicious characteristics'
                            ]);
                    }
                }
                
                $this->debug_log[] = "[External Files] Scanned {$description}: checked " . count($files) . " files";
            }
            
        } catch (Exception $e) {
            $this->debug_log[] = '[External Files] Error scanning outside WordPress: ' . $e->getMessage();
        }
        
        $this->debug_log[] = "[External Files] Outside scan complete: {$outside_files_checked} files checked, {$outside_issues_found} suspicious files found";
        
        // Update scan results
        $this->scan_results['total_files_checked'] += $outside_files_checked;
        $this->scan_results['external_files_checked'] = $outside_files_checked;
        $this->scan_results['external_issues_found'] = $outside_issues_found;
    }
    
    /**
     * Get files from outside directory (non-recursive for safety)
     */
    private function get_outside_directory_files($directory) {
        $files = [];
        
        if (!is_dir($directory) || !is_readable($directory)) {
            return $files;
        }
        
        try {
            $entries = scandir($directory);
            if ($entries === false) {
                return $files;
            }
            
            foreach ($entries as $entry) {
                if ($entry === '.' || $entry === '..') {
                    continue;
                }
                
                $full_path = $directory . DIRECTORY_SEPARATOR . $entry;
                
                if (is_file($full_path) && is_readable($full_path)) {
                    $files[] = $full_path;
                }
            }
            
        } catch (Exception $e) {
            $this->debug_log[] = '[External Files] Error reading directory: ' . $e->getMessage();
        }
        
        return $files;
    }
    
    /**
     * Check if an outside file is suspicious
     */
    private function is_outside_file_suspicious($file_path) {
        $filename = basename($file_path);
        $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
        
        // Whitelist for legitimate system files that should not be flagged
        $legitimate_files = [
            'index.php',      // Common XAMPP/server welcome pages
            'phpinfo.php',    // PHP info pages (though still worth monitoring)
            'info.php'        // Common PHP info file names
        ];
        
        // Check if this is a legitimate system file in common server directories
        if (in_array($filename, $legitimate_files)) {
            // Additional check: if it's in common server root directories, it's likely legitimate
            $parent_dir = basename(dirname($file_path));
            $server_dirs = ['htdocs', 'public_html', 'www', 'html'];
            
            if (in_array($parent_dir, $server_dirs)) {
                return false; // Don't flag legitimate server files
            }
        }
        
        // Suspicious file patterns commonly used by attackers
        $suspicious_patterns = [
            // Common malware file names
            '/^(shell|c99|r57|b374k|wso|adminer|phpmyadmin|bypass|backdoor).*\.php$/i',
            // Base64 encoded names
            '/^[a-zA-Z0-9+\/=]{10,}\.php$/i',
            // Very short cryptic names
            '/^[a-z0-9]{1,3}\.php$/i',
            // Common exploit file names (refined to be more specific)
            '/^(test|tmp|temp|upload|up|admin|login|data|config|wp|wordpress).*\.php$/i'
        ];
        
        foreach ($suspicious_patterns as $pattern) {
            if (preg_match($pattern, $filename)) {
                return true;
            }
        }
        
        // Check file extensions that shouldn't be outside WordPress
        $suspicious_extensions = ['php', 'php3', 'php4', 'php5', 'phtml', 'asp', 'aspx', 'jsp'];
        
        if (in_array($extension, $suspicious_extensions)) {
            // PHP files outside WordPress are generally suspicious
            return true;
        }
        
        // Check file content for suspicious patterns if it's readable and small enough
        if (is_readable($file_path) && filesize($file_path) < 1024 * 1024) { // Max 1MB
            $content = file_get_contents($file_path);
            if ($content !== false) {
                // Look for common malware signatures
                $malware_patterns = [
                    '/eval\s*\(/i',
                    '/base64_decode\s*\(/i',
                    '/shell_exec\s*\(/i',
                    '/system\s*\(/i',
                    '/exec\s*\(/i',
                    '/passthru\s*\(/i',
                    '/@include\s*\(/i',
                    '/@require\s*\(/i'
                ];
                
                foreach ($malware_patterns as $pattern) {
                    if (preg_match($pattern, $content)) {
                        return true;
                    }
                }
            }
        }
        
        return false;
    }
    
    /**
     * Get limited directory files
     */
    private function get_directory_files_limited($directory, $limit = 100) {
        $files = [];
        $count = 0;
        
        if (!is_dir($directory)) {
            return $files;
        }
        
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS)
        );
        
        foreach ($iterator as $file) {
            if ($file->isFile() && $count < $limit) {
                $file_path = $file->getPathname();
                
                // Skip files in excluded paths
                if ($this->should_skip_file($file_path)) {
                    continue;
                }
                
                $files[] = $file_path;
                $count++;
            }
            
            if ($count >= $limit) break;
        }
        
        return $files;
    }
    
    /**
     * Log file issue to database
     */
    private function log_file_issue($file_path, $issue_type, $description, $metadata = []) {
        global $wpdb;

        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        // Handle file path and get hash/size safely
        $relative_path = $file_path;
        
        // Handle different types of file paths
        if (is_string($file_path)) {
            if (strpos($file_path, 'plugin:') === 0 || strpos($file_path, 'theme:') === 0 || strpos($file_path, 'skipped:') === 0) {
                // These are identifier strings, not actual file paths
                $relative_path = $file_path;
            } else {
                // Regular file path - normalize for consistent duplicate detection
                $relative_path = str_replace(ABSPATH, '', $file_path);
                
                // For external files (outside WordPress), use the full normalized path
                if ($relative_path === $file_path) {
                    // File is outside WordPress installation - normalize the path for consistent comparison
                    $relative_path = str_replace('\\', '/', realpath($file_path) ?: $file_path);
                }
            }
        }
        
        $file_hash = null;
        $file_size = 0;
        
        // Only get hash and size for actual files that exist
        if (is_string($file_path) && 
            strpos($file_path, 'plugin:') !== 0 && 
            strpos($file_path, 'theme:') !== 0 && 
            strpos($file_path, 'skipped:') !== 0 &&
            file_exists($file_path) && 
            is_file($file_path)) {
            $file_hash = $metadata['actual_hash'] ?? md5_file($file_path);
            $file_size = filesize($file_path);
        } elseif (isset($metadata['actual_hash'])) {
            $file_hash = $metadata['actual_hash'];
        }
        
        // Build description with metadata (Enhanced with Repository Data)
        $full_description = $description;
        if (!empty($metadata)) {
            $meta_parts = [];
            
            // Add repository verification status
            if (isset($metadata['repository_verified'])) {
                $meta_parts[] = $metadata['repository_verified'] ? 'Repository Verified' : 'Not Repository Verified';
            }
            
            // Add severity if available
            if (isset($metadata['severity'])) {
                $meta_parts[] = 'Severity: ' . strtoupper($metadata['severity']);
            }
            
            // Add file type classification
            if (isset($metadata['file_type'])) {
                $meta_parts[] = 'Type: ' . $metadata['file_type'];
            }
            
            // Add location analysis
            if (isset($metadata['location_analysis']) && is_array($metadata['location_analysis'])) {
                $location_data = $metadata['location_analysis'];
                if (isset($location_data['location'])) {
                    $meta_parts[] = 'Location: ' . $location_data['location'];
                }
                if (isset($location_data['risk_level'])) {
                    $meta_parts[] = 'Risk: ' . strtoupper($location_data['risk_level']);
                }
            }
            
            // Add hash information
            if (isset($metadata['expected_hash']) && isset($metadata['actual_hash'])) {
                $meta_parts[] = 'Hash Mismatch: Expected ' . substr($metadata['expected_hash'], 0, 8) . 
                               '... Got ' . substr($metadata['actual_hash'], 0, 8) . '...';
            }
            
            // Add other metadata - ensure $metadata is an array
            if (is_array($metadata)) {
                foreach ($metadata as $key => $value) {
                    if (!in_array($key, ['actual_hash', 'expected_hash', 'repository_verified', 'severity', 'file_type', 'location_analysis']) && $value !== null) {
                        // Handle array values by converting them to string representations
                        if (is_array($value)) {
                            if (!empty($value)) {
                                $value_str = $this->array_to_string($value);
                                $meta_parts[] = "$key: $value_str";
                            }
                        } elseif (is_object($value)) {
                            $meta_parts[] = "$key: " . get_class($value);
                        } else {
                            $meta_parts[] = "$key: $value";
                        }
                    }
                }
            }
            
            if (!empty($meta_parts)) {
                $full_description .= ' | ' . implode(' | ', $meta_parts);
            }
        }

        // Check if this exact issue was previously ignored
        if ($this->handle_ignored_issue($relative_path, $issue_type, $description, $this->scan_results['scan_id'])) {
            return; // Issue was handled as ignored, skip normal processing
        }
        
        // Check if this issue is currently ignored (skip normal creation)
        if ($this->is_issue_ignored($relative_path, $issue_type, $description)) {
            $this->debug_log[] = '[' . current_time('H:i:s') . '] SKIP: File issue already ignored - ' . $relative_path;
            return;
        }

        // Check if this file has already been processed in current scan to prevent duplicates
        if (in_array($relative_path, $this->processed_files)) {
            $this->debug_log[] = '[' . current_time('H:i:s') . '] SKIP: File already processed in this scan - ' . $relative_path;
            return; // Skip duplicate processing
        }
        
        // Mark this file as processed
        $this->processed_files[] = $relative_path;

        // Calculate comprehensive severity rating
        $issue_data = [
            'relative_path' => $relative_path,
            'issue_type' => $issue_type,
            'metadata' => $metadata,
            'description' => $description,
            'file_hash' => $file_hash,
            'file_size' => $file_size
        ];
        
        $severity_assessment = $this->severity_rating->calculate_severity($issue_data);
        
        // Generate comprehensive severity description
        $severity_description = $this->severity_rating->generate_severity_description($severity_assessment);
        
        // Update full description with severity information
        $full_description .= ' | ' . $severity_description;

        // This is a new issue, create it as active
        $result = $wpdb->insert($issues_table, [
            'scan_id' => $this->scan_results['scan_id'],
            'file_path' => $relative_path,
            'issue_type' => 'file_changes', // All file scanner issues use 'file_changes'
            'type' => $issue_type, // Specific category (plugin_update, theme_update, modified, unknown, etc.)
            'severity' => $severity_assessment['severity_level'], // Use calculated severity level
            'description' => $description, // Clean description without metadata
            'file_hash' => $file_hash,
            'file_size' => $file_size,
            'detected_time' => current_time('mysql'),
            'status' => 'new'
        ]);
        
        if ($result === false) {
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Intentional for debugging
            // error_log("VMPFence: Database error inserting file issue: " . $wpdb->last_error);
        } else {
            // Only increment counter when issue is successfully inserted
            $this->scan_results['issues_found']++;
        }
    }
    
    /**
     * Map issue type to severity level
     */
    private function map_issue_type_to_severity($issue_type) {
        switch ($issue_type) {
            case 'modified':
                return 'high';
            case 'unknown':
                return 'critical';
            case 'plugin_update':
            case 'theme_update':
                return 'medium';
            case 'plugin_suspicious':
            case 'plugin_suspicious_file':
            case 'theme_suspicious':
            case 'theme_suspicious_file':
                return 'high';
            case 'skipped_path':
                return 'low';
            default:
                return 'medium';
        }
    }

    /**
     * Handle previously ignored issues - recreate them in current scan as ignored
     *
     * @param string $file_path File path
     * @param string $issue_type Issue type
     * @param string $description Issue description
     * @param int $scan_id Current scan ID
     * @return bool Whether issue was handled
     */
    private function handle_ignored_issue($file_path, $issue_type, $description, $scan_id) {
        global $wpdb;
        
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        // Check if this exact issue was previously ignored
        // For theme_update and plugin_update, check by file_path and type only
        if ($issue_type === 'theme_update' || $issue_type === 'plugin_update') {
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $ignored_issue = $wpdb->get_row($wpdb->prepare(
                "SELECT * FROM {$issues_table} WHERE file_path = %s AND issue_type = 'file_changes' AND type = %s AND status = 'ignored' ORDER BY detected_time DESC LIMIT 1",
                $file_path,
                $issue_type
            ));
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        } else {
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $ignored_issue = $wpdb->get_row($wpdb->prepare(
                "SELECT * FROM {$issues_table} WHERE file_path = %s AND issue_type = 'file_changes' AND type = %s AND description = %s AND status = 'ignored' ORDER BY detected_time DESC LIMIT 1",
                $file_path,
                $issue_type,
                $description
            ));
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        }
        
        if ($ignored_issue) {
            // Recreate the ignored issue in current scan with current description
            $insert_result = $wpdb->insert(
                $issues_table,
                [
                    'scan_id' => $scan_id,
                    'file_path' => $file_path,
                    'issue_type' => 'file_changes', // All file scanner issues use 'file_changes'
                    'type' => $issue_type, // Specific category
                    'severity' => $this->map_issue_type_to_severity($issue_type),
                    'description' => $description,
                    'status' => 'ignored',
                    'detected_time' => current_time('mysql'),
                    'resolved_time' => current_time('mysql')
                ],
                ['%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s']
            );
            
            if ($insert_result) {
                // For theme/plugin updates, clean up old ignored entries by file_path and type
                if ($issue_type === 'theme_update' || $issue_type === 'plugin_update') {
                    // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                    $wpdb->query($wpdb->prepare(
                        "DELETE FROM {$issues_table} WHERE file_path = %s AND issue_type = 'file_changes' AND type = %s AND status = 'ignored' AND id != %d",
                        $file_path,
                        $issue_type,
                        $wpdb->insert_id
                    ));
                    // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                } else {
                    // For other types, clean up by exact description match
                    // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                    $wpdb->query($wpdb->prepare(
                        "DELETE FROM {$issues_table} WHERE file_path = %s AND issue_type = 'file_changes' AND type = %s AND description = %s AND status = 'ignored' AND id != %d",
                        $file_path,
                        $issue_type,
                        $description,
                        $wpdb->insert_id
                    ));
                    // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                }
                
                $this->debug_log[] = '[' . current_time('H:i:s') . '] PRESERVED: Recreated ignored file issue - ' . $file_path;
                return true;
            }
        }
        
        return false;
    }

    /**
     * Check if an issue is already ignored
     */
    private function is_issue_ignored($file_path, $issue_type, $description) {
        global $wpdb;
        
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        // Normalize file path for comparison (same as in log_file_issue)
        $relative_path = $file_path;
        if (is_string($file_path) && 
            strpos($file_path, 'plugin:') !== 0 && 
            strpos($file_path, 'theme:') !== 0 && 
            strpos($file_path, 'skipped:') !== 0) {
            $relative_path = str_replace(ABSPATH, '', $file_path);
        }
        
        // For theme_update and plugin_update, check by file_path and type only
        // since version numbers change but the plugin/theme identity remains the same
        if ($issue_type === 'theme_update' || $issue_type === 'plugin_update') {
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$issues_table} WHERE file_path = %s AND issue_type = 'file_changes' AND type = %s AND status = 'ignored'",
                $relative_path,
                $issue_type
            ));
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        } else {
            // For other issue types, require exact description match
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $count = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$issues_table} WHERE file_path = %s AND issue_type = 'file_changes' AND type = %s AND description = %s AND status = 'ignored'",
                $relative_path,
                $issue_type,
                $description
            ));
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        }
        
        return $count > 0;
    }

    /**
     * Get issue severity
     */
    private function get_issue_severity($issue_type) {
        $severity_map = [
            'modified' => 'medium',
            'unknown' => 'high',
            'suspicious' => 'high',
            'malware' => 'critical'
        ];
        
        return $severity_map[$issue_type] ?? 'low';
    }
    
    /**
     * Update scan progress
     */
    private function update_scan_progress($files_scanned, $current_section = '') {
        // Get or calculate total files estimate
        $estimated_total = $this->get_total_files_estimate();
        
        update_option('vmpfence_scan_progress', [
            'status' => 'scanning',
            'files_scanned' => $files_scanned,
            'total_files' => $estimated_total,
            'current_section' => $current_section,
            'last_update' => time()
        ]);
    }
    
    /**
     * Get estimated total files for this WordPress installation (scan entire WordPress directory)
     */
    private function get_total_files_estimate() {
        static $cached_estimate = null;
        
        // If cache reset was forced, clear the cached estimate
        if (isset($this->force_file_count_refresh) && $this->force_file_count_refresh) {
            $cached_estimate = null;
            $this->force_file_count_refresh = false;
        }
        
        if ($cached_estimate !== null) {
            return $cached_estimate;
        }
        
        // Count ALL files in WordPress directory
        $wordpress_root = ABSPATH;
        $total_files = $this->count_files_in_directory($wordpress_root);
        
        // Cache the result to avoid recalculating
        $cached_estimate = max($total_files, 100); // Minimum 100 files
        
        return $cached_estimate;
    }
    
    /**
     * Count files in a directory (non-recursive to avoid memory issues)
     */
    private function count_files_in_directory($directory) {
        $count = 0;
        $max_count = 5000; // Safety limit to prevent excessive counting
        
        try {
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS),
                RecursiveIteratorIterator::LEAVES_ONLY
            );
            
            foreach ($iterator as $file) {
                if ($file->isFile()) {
                    $file_path = $file->getPathname();
                    
                    // Skip files in excluded paths when counting
                    if ($this->should_skip_file($file_path)) {
                        continue;
                    }
                    
                    $count++;
                    
                    // Stop counting if we hit the safety limit
                    if ($count >= $max_count) {
                        break;
                    }
                }
            }
        } catch (Exception $e) {
            // If counting fails, return a reasonable estimate based on what we've counted so far
            return max($count, 500);
        }
        
        return $count;
    }
    
    /**
     * Check if a file in core directory is suspicious
     */
    protected function is_suspicious_core_file($relative_path) {
        // Convert to forward slashes for consistent pattern matching
        $normalized_path = str_replace('\\', '/', $relative_path);
        
        // First, check if this is a legitimate WordPress core directory structure
        $core_directories = [
            'wp-admin/',
            'wp-includes/'
        ];
        
        $is_in_core_dir = false;
        foreach ($core_directories as $core_dir) {
            if (strpos($normalized_path, $core_dir) === 0) {
                $is_in_core_dir = true;
                break;
            }
        }
        
        // If not in core directories, not suspicious by this method
        if (!$is_in_core_dir) {
            return false;
        }
        
        // Allow all legitimate WordPress core patterns (be very conservative)
        $legitimate_patterns = [
            // Core admin files
            'wp-admin/',                      // All wp-admin files are legitimate
            'wp-includes/',                   // All wp-includes files are legitimate
        ];
        
        // Only flag files with suspicious naming patterns that are clearly not WordPress core
        $suspicious_patterns = [
            // Common malware/backdoor patterns
            '/wp-admin/.*\.(php|js|html)$/i',
            '/wp-includes/.*\.(php|js|html)$/i'
        ];
        
        // Look for obviously suspicious file naming patterns
        $filename = basename($normalized_path);
        $suspicious_names = [
            // Common backdoor/malware file names
            'shell.php',
            'backdoor.php', 
            'c99.php',
            'r57.php',
            'webshell.php',
            'bypass.php',
            'hack.php',
            'eval.php',
            'base64.php',
            // Files with random/encoded names
        ];
        
        // Check for suspicious file names
        $filename_lower = strtolower($filename);
        foreach ($suspicious_names as $suspicious_name) {
            if ($filename_lower === strtolower($suspicious_name)) {
                return true;
            }
        }
        
        // Check for files with suspicious extensions in wrong places
        $file_extension = strtolower(pathinfo($normalized_path, PATHINFO_EXTENSION));
        
        // Only flag executable files with clearly suspicious characteristics
        if (in_array($file_extension, ['php', 'php5', 'phtml', 'php7'])) {
            // Check for suspicious PHP file patterns
            if (preg_match('/[0-9a-f]{8,}\.php$/i', $filename) || // Random hex names
                preg_match('/^[0-9]+\.php$/i', $filename) ||        // Numeric names
                preg_match('/^[a-z]{1,3}\.php$/i', $filename) ||    // Very short names
                strpos($filename, '..') !== false ||                // Directory traversal
                strpos($filename, 'eval') !== false ||              // Eval functions
                strpos($filename, 'base64') !== false) {            // Base64 encoding
                return true;
            }
        }
        
        // For now, be very conservative - don't flag legitimate WordPress files
        // This significantly reduces false positives
        return false;
    }
    
    /**
     * Classify file type for security analysis 
     */
    private function classify_file_type($relative_path, $checksums) {
        // WordPress core file
        if (isset($checksums[$relative_path])) {
            return 'wordpress_core';
        }
        
        // Plugin file
        if (strpos($relative_path, 'wp-content/plugins/') === 0) {
            return 'plugin';
        }
        
        // Theme file
        if (strpos($relative_path, 'wp-content/themes/') === 0) {
            return 'theme';
        }
        
        // WordPress core directories
        if (strpos($relative_path, 'wp-admin/') === 0 || 
            strpos($relative_path, 'wp-includes/') === 0) {
            return 'core_directory';
        }
        
        // Upload files
        if (strpos($relative_path, 'wp-content/uploads/') === 0) {
            return 'upload';
        }
        
        // Root WordPress files
        $root_wp_files = ['wp-config.php', 'wp-load.php', 'wp-blog-header.php', 
                         'wp-cron.php', 'wp-login.php', 'index.php', '.htaccess'];
        if (in_array(basename($relative_path), $root_wp_files) && dirname($relative_path) === '.') {
            return 'wordpress_root';
        }
        
        return 'unknown';
    }
    
    /**
     * Enhanced suspicious file detection
     */
    private function is_enhanced_suspicious_file($relative_path, $file_type) {
        // Only flag files as suspicious if they're in locations that should be controlled
        
        // Files that should never exist in core directories
        $suspicious_patterns = [
            '/\.php\d+$/',              // .php5, .php7, etc.
            '/\.suspected$/',           // .suspected files
            '/\.bak$/',                 // Backup files
            '/\.backup$/',              // Backup files
            '/\.old$/',                 // Old files
            '/\.orig$/',                // Original files
            '/\.save$/',                // Save files
            '/\.tmp$/',                 // Temporary files
            '/\.log$/',                 // Log files in core
            '/\.sql$/',                 // SQL dumps in core
            '/shell\./i',               // Shell scripts
            '/backdoor/i',              // Backdoor keywords
            '/malware/i',               // Malware keywords
            '/hack/i',                  // Hack keywords
            '/\.htaccess\./',           // Suspicious htaccess variations
            '/wp-config\.php\./',       // Suspicious wp-config variations
        ];
        
        foreach ($suspicious_patterns as $pattern) {
            if (preg_match($pattern, $relative_path)) {
                return true;
            }
        }
        
        // ONLY flag files in core directories (wp-admin, wp-includes) as suspicious if not in checksums
        // Do NOT flag theme, plugin, or upload files as "unknown core files"
        if ($file_type === 'core_directory') {
            return true;
        }
        
        // PHP files in uploads directory (highly suspicious)
        if ($file_type === 'upload' && preg_match('/\.php\d*$/i', $relative_path)) {
            return true;
        }
        
        // All other files (themes, plugins, etc.) are not "unknown core files"
        return false;
    }
    
    /**
     * Get plugin name from plugin file path
     */
    private function get_plugin_name($plugin_file) {
        $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_file);
        return $plugin_data['Name'] ?? dirname($plugin_file);
    }
    
    /**
     * Get plugin version from plugin file path
     */
    private function get_plugin_version($plugin_file) {
        $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_file);
        return $plugin_data['Version'] ?? 'Unknown';
    }
    
    /**
     * Verify plugin repository integrity (Plugin Repository Verification)
     * Similar to WordPress core verification but for plugins from WordPress.org
     */
    private function verify_plugin_repository_integrity($active_plugins) {
        $integrity_issues = 0;
        $plugins_verified = 0;
        $wordpress_org_plugins = 0;
        $custom_premium_plugins = 0;
        $max_plugins_to_check = 5; // Increased limit since many will be skipped
        
        $this->debug_log[] = '[Plugin Integrity] Starting repository verification for WordPress.org plugins';
        
        foreach (array_slice($active_plugins, 0, $max_plugins_to_check) as $plugin_file) {
            if ($this->should_break_scan()) {
                $this->debug_log[] = '[Plugin Integrity] TIMEOUT: Breaking plugin integrity scan';
                break;
            }
            
            $plugin_slug = dirname($plugin_file);
            $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_file);
            $plugin_name = $plugin_data['Name'] ?? $plugin_slug;
            $plugin_version = $plugin_data['Version'] ?? 'Unknown';
            
            $this->debug_log[] = '[Plugin Integrity] Checking: ' . $plugin_name . ' (v' . $plugin_version . ')';
            
            // Get plugin information from WordPress.org API
            $plugin_info = $this->get_plugin_repository_info($plugin_slug, $plugin_version);
            
            if (!$plugin_info) {
                $custom_premium_plugins++;
                $this->debug_log[] = '[Plugin Integrity] SKIP: Plugin not from WordPress.org repository (custom/premium/commercial): ' . $plugin_name;
                
                // Still do basic suspicious pattern check for custom/premium plugins
                $basic_issues = $this->verify_plugin_files_basic($plugin_slug, $plugin_name);
                $integrity_issues += $basic_issues;
                continue;
            }
            
            // This is a WordPress.org plugin - do full verification
            $wordpress_org_plugins++;
            $plugin_issues = $this->verify_plugin_files($plugin_slug, $plugin_info);
            $integrity_issues += $plugin_issues;
            $plugins_verified++;
            
            $this->debug_log[] = '[Plugin Integrity] Verified WordPress.org plugin: ' . $plugin_name . ' - Found ' . $plugin_issues . ' integrity issues';
        }
        
        $this->debug_log[] = '[Plugin Integrity] Repository verification completed:';
        $this->debug_log[] = '[Plugin Integrity] - WordPress.org plugins: ' . $wordpress_org_plugins . ' (verified)';
        $this->debug_log[] = '[Plugin Integrity] - Custom/Premium plugins: ' . $custom_premium_plugins . ' (basic scan only)';
        $this->debug_log[] = '[Plugin Integrity] - Total integrity issues: ' . $integrity_issues;
        
        return $integrity_issues;
    }
    
    /**
     * Get plugin information from WordPress.org API
     */
    private function get_plugin_repository_info($plugin_slug, $version) {
        // Use WordPress.org Plugin API (similar to core checksums API)
        $api_url = 'https://api.wordpress.org/plugins/info/1.0/' . $plugin_slug . '.json';
        
        $response = wp_remote_get($api_url, [
            'timeout' => 10,
            'user-agent' => 'VMPFence-Security-Scanner/1.0'
        ]);
        
        if (is_wp_error($response)) {
            $this->debug_log[] = '[Plugin API] ERROR: Failed to fetch plugin info for ' . $plugin_slug . ': ' . $response->get_error_message();
            return false;
        }
        
        $response_code = wp_remote_retrieve_response_code($response);
        
        // Handle 404 - Plugin not found in WordPress.org repository
        if ($response_code === 404) {
            $this->debug_log[] = '[Plugin API] INFO: Plugin not found in WordPress.org repository (likely custom/premium): ' . $plugin_slug;
            return false; // Not an error, just not a WordPress.org plugin
        }
        
        // Handle other HTTP errors
        if ($response_code !== 200) {
            $this->debug_log[] = '[Plugin API] ERROR: HTTP ' . $response_code . ' response for plugin: ' . $plugin_slug;
            return false;
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (!$data || !isset($data['slug'])) {
            $this->debug_log[] = '[Plugin API] ERROR: Invalid JSON response for plugin: ' . $plugin_slug;
            return false;
        }
        
        $this->debug_log[] = '[Plugin API] SUCCESS: Retrieved plugin info for ' . $plugin_slug . ' from WordPress.org';
        return $data;
    }
    
    /**
     * Verify specific plugin files against repository information
     */
    private function verify_plugin_files($plugin_slug, $plugin_info) {
        $issues_found = 0;
        
        // Check main plugin file integrity
        $plugin_dir = WP_PLUGIN_DIR . '/' . $plugin_slug;
        $main_file = $plugin_dir . '/' . $plugin_slug . '.php';
        
        if (file_exists($main_file)) {
            $this->debug_log[] = '[Plugin Integrity] Scanning main file: ' . basename($main_file);
            
            $file_content = file_get_contents($main_file);
            $suspicious_patterns = [
                '/eval\s*\(/i' => 'eval() function usage',
                '/base64_decode\s*\(/i' => 'base64_decode() function usage',
                '/shell_exec\s*\(/i' => 'shell_exec() function usage',
                '/system\s*\(/i' => 'system() function usage',
                '/\$_GET\[.*?\].*?eval/i' => 'GET parameter to eval',
                '/\$_POST\[.*?\].*?eval/i' => 'POST parameter to eval'
            ];
            
            foreach ($suspicious_patterns as $pattern => $description) {
                if (preg_match($pattern, $file_content)) {
                    $this->debug_log[] = '[Plugin Integrity] ISSUE: Suspicious pattern detected in ' . $plugin_slug . ': ' . $description;
                    
                    $this->log_file_issue($main_file, 'plugin_modified', 'Plugin main file contains suspicious patterns that may indicate modification or compromise', [
                        'plugin_name' => $plugin_info['name'] ?? $plugin_slug,
                        'plugin_version' => $plugin_info['version'] ?? 'Unknown',
                        'severity' => 'high',
                        'pattern_detected' => $description
                    ]);
                    $issues_found++;
                    break; // Only report once per file
                }
            }
            
            if ($issues_found === 0) {
                $this->debug_log[] = '[Plugin Integrity] OK: No suspicious patterns detected in main file';
            }
        } else {
            $this->debug_log[] = '[Plugin Integrity] WARNING: Main plugin file not found: ' . $main_file;
        }
        
        // Quick check for suspicious executable files (limit to 5 files to prevent hanging)
        $file_count = 0;
        $max_files = 5;
        
        if (is_dir($plugin_dir)) {
            $iterator = new DirectoryIterator($plugin_dir);
            foreach ($iterator as $file) {
                if ($file_count >= $max_files) break;
                
                if ($file->isFile() && !$file->isDot()) {
                    $file_path = $file->getPathname();
                    $filename = $file->getFilename();
                    
                    // Skip files in excluded paths (though unlikely in plugin directories)
                    if ($this->should_skip_file($file_path)) {
                        continue;
                    }
                    
                    // Check for suspicious file types
                    if (preg_match('/\.(exe|bat|cmd|sh|py|rb|jar|war)$/i', $filename)) {
                        $this->debug_log[] = '[Plugin Integrity] ISSUE: Suspicious file type in plugin ' . $plugin_slug . ': ' . $filename;
                        
                        $this->log_file_issue($file->getPathname(), 'plugin_suspicious_file', 'Suspicious file type found in plugin directory', [
                            'plugin_name' => $plugin_info['name'] ?? $plugin_slug,
                            'file_type' => pathinfo($filename, PATHINFO_EXTENSION),
                            'severity' => 'medium'
                        ]);
                        $issues_found++;
                    }
                    
                    $file_count++;
                }
            }
        }
        
        return $issues_found;
    }
    
    /**
     * Basic verification for custom/premium plugins (not from WordPress.org)
     */
    private function verify_plugin_files_basic($plugin_slug, $plugin_name) {
        $issues_found = 0;
        
        // Check main plugin file for basic suspicious patterns
        $plugin_dir = WP_PLUGIN_DIR . '/' . $plugin_slug;
        $main_file = $plugin_dir . '/' . $plugin_slug . '.php';
        
        if (file_exists($main_file)) {
            $this->debug_log[] = '[Plugin Integrity] Basic scan for custom/premium plugin: ' . basename($main_file);
            
            $file_content = file_get_contents($main_file);
            
            // Only check for the most dangerous patterns in custom plugins
            $critical_patterns = [
                '/eval\s*\(\s*base64_decode/i' => 'encoded eval() execution',
                '/system\s*\(\s*\$_/i' => 'direct system command execution from user input',
                '/shell_exec\s*\(\s*\$_/i' => 'direct shell execution from user input',
                '/file_get_contents\s*\(\s*["\']\s*http/i' => 'remote file inclusion attempt'
            ];
            
            foreach ($critical_patterns as $pattern => $description) {
                if (preg_match($pattern, $file_content)) {
                    $this->debug_log[] = '[Plugin Integrity] CRITICAL: Dangerous pattern in custom plugin ' . $plugin_slug . ': ' . $description;
                    
                    $this->log_file_issue($main_file, 'plugin_suspicious', 'Custom/Premium plugin contains dangerous patterns', [
                        'plugin_name' => $plugin_name,
                        'plugin_type' => 'custom/premium',
                        'severity' => 'critical',
                        'pattern_detected' => $description
                    ]);
                    $issues_found++;
                    break; // Only report once per file
                }
            }
            
            if ($issues_found === 0) {
                $this->debug_log[] = '[Plugin Integrity] OK: No critical patterns detected in custom plugin';
            }
        }
        
        return $issues_found;
    }
    
    /**
     * Theme Repository Verification
     * Verify theme integrity against WordPress.org repository
     */
    private function verify_theme_repository_integrity($all_themes) {
        $this->debug_log[] = '[Theme Integrity] Starting repository verification for WordPress.org themes';
        
        $integrity_issues = 0;
        $themes_verified = 0;
        $wordpress_org_themes = 0;
        $custom_premium_themes = 0;
        
        foreach ($all_themes as $theme_slug => $theme_object) {
            // Timeout protection
            if ($this->should_break_scan()) {
                $this->debug_log[] = '[Theme Integrity] TIMEOUT: Breaking theme integrity scan';
                break;
            }
            
            $theme_name = $theme_object->get('Name') ?: $theme_slug;
            $theme_version = $theme_object->get('Version') ?: 'Unknown';
            
            $this->debug_log[] = '[Theme Integrity] Checking: ' . $theme_name . ' (v' . $theme_version . ')';
            
            // Get theme information from WordPress.org API
            $theme_info = $this->get_theme_repository_info($theme_slug, $theme_version);
            
            if (!$theme_info) {
                $custom_premium_themes++;
                $this->debug_log[] = '[Theme Integrity] SKIP: Theme not from WordPress.org repository (custom/premium/commercial): ' . $theme_name;
                
                // Still do basic suspicious pattern check for custom/premium themes
                $basic_issues = $this->verify_theme_files_basic($theme_slug, $theme_name);
                $integrity_issues += $basic_issues;
                continue;
            }
            
            // This is a WordPress.org theme - do full verification
            $wordpress_org_themes++;
            $theme_issues = $this->verify_theme_files($theme_slug, $theme_info);
            $integrity_issues += $theme_issues;
            $themes_verified++;
            
            $this->debug_log[] = '[Theme Integrity] Verified WordPress.org theme: ' . $theme_name . ' - Found ' . $theme_issues . ' integrity issues';
        }
        
        $this->debug_log[] = '[Theme Integrity] Repository verification completed:';
        $this->debug_log[] = '[Theme Integrity] - WordPress.org themes: ' . $wordpress_org_themes . ' (verified)';
        $this->debug_log[] = '[Theme Integrity] - Custom/Premium themes: ' . $custom_premium_themes . ' (basic scan only)';
        $this->debug_log[] = '[Theme Integrity] - Total integrity issues: ' . $integrity_issues;
        
        return $integrity_issues;
    }
    
    /**
     * Get theme information from WordPress.org API
     */
    private function get_theme_repository_info($theme_slug, $version) {
        // Use WordPress.org Theme API - correct endpoint format
        $api_url = 'https://api.wordpress.org/themes/info/1.1/?request[slug]=' . $theme_slug . '&action=theme_information';
        
        $response = wp_remote_get($api_url, [
            'timeout' => 10,
            'user-agent' => 'VMPFence-Security-Scanner/1.0'
        ]);
        
        if (is_wp_error($response)) {
            $this->debug_log[] = '[Theme API] ERROR: Failed to fetch theme info for ' . $theme_slug . ': ' . $response->get_error_message();
            return false;
        }
        
        $response_code = wp_remote_retrieve_response_code($response);
        
        // Handle 404 - Theme not found in WordPress.org repository
        if ($response_code === 404) {
            $this->debug_log[] = '[Theme API] INFO: Theme not found in WordPress.org repository (likely custom/premium): ' . $theme_slug;
            return false; // Not an error, just not a WordPress.org theme
        }
        
        // Handle other HTTP errors
        if ($response_code !== 200) {
            $this->debug_log[] = '[Theme API] ERROR: HTTP ' . $response_code . ' response for theme: ' . $theme_slug;
            return false;
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        // Check for API error response
        if (isset($data['error'])) {
            $this->debug_log[] = '[Theme API] INFO: Theme not found in WordPress.org repository (likely custom/premium): ' . $theme_slug;
            return false; // Not an error, just not a WordPress.org theme
        }
        
        if (!$data || !isset($data['slug'])) {
            $this->debug_log[] = '[Theme API] ERROR: Invalid JSON response for theme: ' . $theme_slug;
            return false;
        }
        
        $this->debug_log[] = '[Theme API] SUCCESS: Retrieved theme info for ' . $theme_slug . ' from WordPress.org';
        return $data;
    }
    
    /**
     * Verify specific theme files against repository information
     */
    private function verify_theme_files($theme_slug, $theme_info) {
        $issues_found = 0;
        
        // Check main theme files integrity
        $theme_dir = get_theme_root() . '/' . $theme_slug;
        $main_files = ['style.css', 'index.php', 'functions.php'];
        
        foreach ($main_files as $filename) {
            $file_path = $theme_dir . '/' . $filename;
            
            if (file_exists($file_path)) {
                $this->debug_log[] = '[Theme Integrity] Scanning main file: ' . $filename;
                
                $file_content = file_get_contents($file_path);
                $suspicious_patterns = [
                    '/eval\s*\(/i' => 'eval() function usage',
                    '/base64_decode\s*\(/i' => 'base64_decode() function usage',
                    '/shell_exec\s*\(/i' => 'shell_exec() function usage',
                    '/system\s*\(/i' => 'system() function usage',
                    '/\$_GET\[.*?\].*?eval/i' => 'GET parameter to eval',
                    '/\$_POST\[.*?\].*?eval/i' => 'POST parameter to eval',
                    '/file_get_contents\s*\(\s*["\']http/i' => 'remote file inclusion',
                    '/curl_exec\s*\(/i' => 'curl execution'
                ];
                
                foreach ($suspicious_patterns as $pattern => $description) {
                    if (preg_match($pattern, $file_content)) {
                        $this->debug_log[] = '[Theme Integrity] ISSUE: Suspicious pattern detected in ' . $theme_slug . '/' . $filename . ': ' . $description;
                        
                        $this->log_file_issue($file_path, 'theme_suspicious', "Suspicious pattern in theme file: {$description}", [
                            'theme_slug' => $theme_slug,
                            'theme_name' => $theme_info['name'] ?? $theme_slug,
                            'pattern' => $description,
                            'file' => $filename
                        ]);
                        
                        $issues_found++;
                    }
                }
                
                $this->debug_log[] = '[Theme Integrity] OK: No suspicious patterns detected in ' . $filename;
            }
        }
        
        return $issues_found;
    }
    
    /**
     * Basic scan for custom/premium themes (limited verification)
     */
    private function verify_theme_files_basic($theme_slug, $theme_name) {
        $this->debug_log[] = '[Theme Integrity] Basic scan for custom/premium theme: ' . $theme_slug;
        
        $issues_found = 0;
        $theme_dir = get_theme_root() . '/' . $theme_slug;
        $main_files = ['style.css', 'index.php', 'functions.php'];
        
        foreach ($main_files as $filename) {
            $file_path = $theme_dir . '/' . $filename;
            
            if (file_exists($file_path)) {
                $file_content = file_get_contents($file_path);
                
                // Only check for critical malware patterns
                $critical_patterns = [
                    '/eval\s*\(\s*base64_decode/i' => 'encoded eval execution',
                    '/shell_exec\s*\(/i' => 'shell execution',
                    '/system\s*\(/i' => 'system command execution',
                    '/\$_GET\[.*?\].*?eval/i' => 'GET parameter to eval',
                    '/\$_POST\[.*?\].*?eval/i' => 'POST parameter to eval'
                ];
                
                foreach ($critical_patterns as $pattern => $description) {
                    if (preg_match($pattern, $file_content)) {
                        $this->debug_log[] = '[Theme Integrity] CRITICAL: Malicious pattern in custom theme ' . $theme_slug . '/' . $filename . ': ' . $description;
                        
                        $this->log_file_issue($file_path, 'theme_suspicious_file', "Critical malicious pattern in custom theme: {$description}", [
                            'theme_slug' => $theme_slug,
                            'theme_name' => $theme_name,
                            'pattern' => $description,
                            'file' => $filename
                        ]);
                        
                        $issues_found++;
                    }
                }
            }
        }
        
        if ($issues_found === 0) {
            $this->debug_log[] = '[Theme Integrity] OK: No critical patterns detected in custom theme';
        }
        
        return $issues_found;
    }
    
    /**
     * Check if scan should break (timeout protection with cold start awareness)
     */
    private function should_break_scan() {
        static $start_time;
        static $is_cold_start_check;
        static $max_execution_time;
        
        if (!$start_time) {
            $start_time = time();
            $is_cold_start_check = $this->is_cold_start !== null ? $this->is_cold_start : false;
            // Give more time for cold starts
            $max_execution_time = $is_cold_start_check ? 150 : 90; // 150s for cold start, 90s for warm
        }
        
        $elapsed = time() - $start_time;
        $should_break = $elapsed > $max_execution_time;
        
        if ($should_break && $is_cold_start_check) {
            $this->debug_log[] = '[Cold Start] TIMEOUT after ' . $elapsed . 's (cold start limit: ' . $max_execution_time . 's)';
        }
        
        return $should_break;
    }
    
    /**
     * Complete scan
     */
    private function complete_scan($scan_id) {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'vmpfence_scan_results';
        
        // Get comprehensive statistics from all engines
        $severity_stats = $this->get_severity_rating_stats();
        $legitimacy_stats = $this->legitimacy_assessment->get_assessment_stats();
        $content_stats = $this->content_pattern_analysis->get_analysis_stats();
        $unknown_stats = $this->unknown_file_detection->get_detection_stats();
        $threat_stats = $this->threat_intelligence->get_threat_statistics();
        $shac_stats = $this->scan_results['shac_statistics'] ?? [];
        
        $comprehensive_scan_data = [
            'stats' => [
                'core_files_checked' => $this->scan_results['core_files'],
                'plugins_checked' => $this->scan_results['plugins'],
                'themes_checked' => $this->scan_results['themes']
            ],
            'severity_analysis' => [
                'critical_issues' => $severity_stats['critical_issues'] ?? 0,
                'high_issues' => $severity_stats['high_issues'] ?? 0,
                'medium_issues' => $severity_stats['medium_issues'] ?? 0,
                'low_issues' => $severity_stats['low_issues'] ?? 0,
                'issues_rated' => $severity_stats['issues_rated'] ?? 0,
                'avg_rating_time' => $severity_stats['avg_rating_time'] ?? '0ms',
                'severity_distribution' => $severity_stats['severity_distribution'] ?? []
            ],
            'engine_statistics' => [
                'shac' => $shac_stats,
                'threat_intelligence' => $threat_stats,
                'unknown_file_detection' => $unknown_stats,
                'content_pattern_analysis' => $content_stats,
                'legitimacy_assessment' => $legitimacy_stats,
                'severity_rating' => $severity_stats
            ]
        ];
        
        $wpdb->update(
            $table_name,
            [
                'total_files' => $this->scan_results['total_files_checked'],
                'issues_found' => $this->scan_results['issues_found'],
                'scan_status' => 'completed',
                'scan_data' => json_encode($comprehensive_scan_data)
            ],
            ['id' => $scan_id],
            ['%d', '%d', '%s', '%s'],
            ['%d']
        );
        
        update_option('vmpfence_last_file_scan', current_time('mysql'));
        delete_option('vmpfence_scan_progress');
    }
    
    /**
     * Mark scan as failed
     */
    private function fail_scan($scan_id, $error_message) {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'vmpfence_scan_results';
        
        $wpdb->update(
            $table_name,
            [
                'scan_status' => 'failed',
                'scan_data' => json_encode(['error' => $error_message])
            ],
            ['id' => $scan_id],
            ['%s', '%s'],
            ['%d']
        );
        
        delete_option('vmpfence_scan_progress');
    }
    
    /**
     * Get WordPress checksums from API
     */
    private function get_wordpress_checksums() {
        // FORCE FRESH DATA: Clear cache to get latest API response after bug fix
        delete_transient('vmpfence_wp_checksums_' . $this->wp_version);
        //$this->debug_log[] = '[Repository] Cleared cached checksums to force fresh API data';
        
        // Try to get cached checksums first
        $checksums = get_transient('vmpfence_wp_checksums_' . $this->wp_version);
        
        if (false === $checksums) {
            $this->debug_log[] = '[Repository] Fetching WordPress checksums for version: ' . $this->wp_version;
            
            // Primary API endpoint
            $api_url = "https://api.wordpress.org/core/checksums/1.0/?version={$this->wp_version}";
            
            // Enhanced request with proper headers and error handling
            $response = wp_remote_get($api_url, [
                'timeout' => 30,
                'user-agent' => 'VMPFence Security Scanner/1.0',
                'headers' => [
                    'Accept' => 'application/json',
                    'Cache-Control' => 'no-cache'
                ]
            ]);
            
            if (is_wp_error($response)) {
                $this->debug_log[] = '[Repository] ERROR: Failed to fetch checksums - ' . $response->get_error_message();
                return $this->get_fallback_checksums();
            }
            
            $response_code = wp_remote_retrieve_response_code($response);
            if ($response_code !== 200) {
                $this->debug_log[] = '[Repository] ERROR: API returned HTTP ' . $response_code;
                return $this->get_fallback_checksums();
            }
            
            $body = wp_remote_retrieve_body($response);
            $data = json_decode($body, true);
            
            if (!$data || !isset($data['checksums']) || !is_array($data['checksums'])) {
                $this->debug_log[] = '[Repository] ERROR: Invalid API response format';
                return $this->get_fallback_checksums();
            }
            
            // WordPress API returns checksums nested under version key
            if (isset($data['checksums'][$this->wp_version])) {
                $checksums = $data['checksums'][$this->wp_version];
            } else {
                $this->debug_log[] = '[Repository] ERROR: Version ' . $this->wp_version . ' not found in API response';
                $this->debug_log[] = '[Repository] Available versions: ' . implode(', ', array_keys($data['checksums']));
                return $this->get_fallback_checksums();
            }
            
            //$this->debug_log[] = '[Repository] API Response Debug: Found ' . count($checksums) . ' checksums in response';
            
            // Validate checksums data
            if (empty($checksums)) {
                $this->debug_log[] = '[Repository] WARNING: Empty checksums received for version ' . $this->wp_version;
                $this->debug_log[] = '[Repository] This may indicate an unreleased or development version';
                return $this->get_fallback_checksums();
            }
            
            // Check if we got suspiciously few checksums (WordPress should have 1000+ core files)
            if (count($checksums) < 500) {
                $this->debug_log[] = '[Repository] WARNING: Suspiciously few checksums (' . count($checksums) . ') for WordPress ' . $this->wp_version;
                $this->debug_log[] = '[Repository] This may indicate incomplete API data or unreleased version';
                // Still use the checksums we have, but log the concern
            }
            
            // Cache for 24 hours
            set_transient('vmpfence_wp_checksums_' . $this->wp_version, $checksums, 24 * HOUR_IN_SECONDS);
            
            $this->debug_log[] = '[Repository] Successfully fetched ' . count($checksums) . ' core file checksums';
        } else {
            $this->debug_log[] = '[Repository] Using cached checksums for version: ' . $this->wp_version;
        }
        
        return $checksums ?: [];
    }
    
    /**
     * Get fallback checksums when API is unavailable
     */
    private function get_fallback_checksums() {
        $this->debug_log[] = '[Repository] Attempting fallback checksum retrieval';
        
        // Try alternative API endpoint
        $fallback_url = "https://api.wordpress.org/core/version-check/1.7/";
        $response = wp_remote_get($fallback_url, ['timeout' => 15]);
        
        if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
            $body = wp_remote_retrieve_body($response);
            $data = json_decode($body, true);
            
            if (isset($data['offers']) && is_array($data['offers'])) {
                foreach ($data['offers'] as $offer) {
                    if (isset($offer['version']) && $offer['version'] === $this->wp_version) {
                        $this->debug_log[] = '[Repository] Found version info in fallback API';
                        // Return empty array to indicate we should skip core verification
                        // rather than flag all files as suspicious
                        return [];
                    }
                }
            }
        }
        
        $this->debug_log[] = '[Repository] Fallback failed - will skip core file verification';
        return [];
    }
    
    /**
     * Calculate scan totals
     */
    private function calculate_totals() {
        // Already calculated in chunked methods
    }
    
    /**
     * Get latest scan results
     */
    public function get_latest_scan_results() {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'vmpfence_scan_results';
        
        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $latest_scan = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT * FROM {$table_name} WHERE scan_type = %s ORDER BY scan_time DESC LIMIT 1",
                'file_changes'
            ),
            ARRAY_A
        );
        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        
        if ($latest_scan) {
            $latest_scan['scan_data'] = json_decode($latest_scan['scan_data'], true);
            return $latest_scan;
        }
        
        return null;
    }
    
    /**
     * Get scan issues
     */
    public function get_scan_issues($scan_id = null, $status = 'new') {
        global $wpdb;
        
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        if ($scan_id) {
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$issues_table} WHERE scan_id = %d AND status = %s ORDER BY severity DESC, detected_time DESC",
                    $scan_id,
                    $status
                ),
                ARRAY_A
            );
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        }
        
        // Get issues from latest scan
        $latest_scan = $this->get_latest_scan_results();
        if ($latest_scan) {
            return $this->get_scan_issues($latest_scan['id'], $status);
        }
        
        return [];
    }
    
    /**
     * Get active issues count
     */
    public function get_active_issues_count($scan_id = null) {
        global $wpdb;
        
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        if ($scan_id) {
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            return $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT COUNT(*) FROM {$issues_table} WHERE scan_id = %d AND status = 'new'",
                    $scan_id
                )
            );
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        }
        
        // Get count from latest scan
        $latest_scan = $this->get_latest_scan_results();
        if ($latest_scan) {
            return $this->get_active_issues_count($latest_scan['id']);
        }
        
        return 0;
    }
    
    /**
     * Get ignored issues count
     */
    public function get_ignored_issues_count($scan_id = null) {
        global $wpdb;
        
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        if ($scan_id) {
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            return $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT COUNT(*) FROM {$issues_table} WHERE scan_id = %d AND status = 'ignored'",
                    $scan_id
                )
            );
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        }
        
        // Get count from latest scan
        $latest_scan = $this->get_latest_scan_results();
        if ($latest_scan) {
            return $this->get_ignored_issues_count($latest_scan['id']);
        }
        
        return 0;
    }
    
    /**
     * Get ignored issues (should get ALL ignored issues regardless of scan_id)
     */
    public function get_ignored_issues($scan_id = null) {
        global $wpdb;
        
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        // Get ALL ignored issues for file-related issue types, regardless of scan_id
        // Ignored issues should persist across scans
        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        return $wpdb->get_results(
            "SELECT * FROM {$issues_table} WHERE issue_type IN ('file_changes', 'plugin_update', 'theme_update') AND status = 'ignored' ORDER BY detected_time DESC",
            ARRAY_A
        );
        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    }
    
    /**
     * Get debug logs including Known Files logs
     */
    public function get_debug_log() {
        // Include Known Files debug logs
        $known_files_logs = $this->known_files->get_debug_log();
        if (!empty($known_files_logs)) {
            $combined_logs = array_merge($this->debug_log, $known_files_logs);
            return $combined_logs;
        }
        
        return $this->debug_log;
    }
    
    /**
     * Get Known Files statistics
     */
    public function get_known_files_stats() {
        return $this->known_files->get_known_files_stats();
    }
    
    /**
     * Rebuild Known Files database
     */
    public function rebuild_known_files_database() {
        $this->debug_log[] = '[Known Files] Manual rebuild requested';
        $result = $this->known_files->update_known_files();
        
        if ($result) {
            $stats = $this->known_files->get_known_files_stats();
            $this->debug_log[] = '[Known Files] Rebuild completed: ' . $stats['total'] . ' files tracked';
            return $stats;
        }
        
        $this->debug_log[] = '[Known Files] Rebuild failed';
        return false;
    }
    
    /**
     * Detect if this is a cold start (first scan after server restart)
     */
    private function is_cold_start() {
        // Check multiple indicators for cold start
        $last_scan = get_option('vmpfence_last_scan_time', 0);
        
        // If no previous scan in last 30 minutes, treat as cold start
        if ($last_scan == 0 || (time() - $last_scan) > 1800) {
            return true;
        }
        
        // Check if this is first scan after WordPress load
        $warmup_test = wp_cache_get('vmpfence_cache_warmup_test');
        if ($warmup_test === false) {
            wp_cache_set('vmpfence_cache_warmup_test', time(), '', 1800); // 30 minutes
            return true;
        }
        
        return false;
    }
    
    /**
     * Apply cold start optimizations
     */
    private function apply_cold_start_optimizations() {
        // 1. Warm up database connections
        $this->warmup_database_connections();
        
        // 2. Initialize file system cache
        $this->warmup_file_system_cache();
        
        // 3. Set scan timing for cold start
        update_option('vmpfence_last_scan_time', time());
        
        $this->debug_log[] = '[Cold Start] Applied performance optimizations for first scan';
    }
    
    /**
     * Warm up database connections
     */
    private function warmup_database_connections() {
        global $wpdb;
        
        // Execute simple queries to warm up MySQL
        $wpdb->get_var("SELECT 1");
        
        // Warm up VMPFence tables if they exist
        $tables = ['vmpfence_known_files', 'vmpfence_scan_results', 'vmpfence_scan_issues'];
        foreach ($tables as $table) {
            $table_name = $wpdb->prefix . $table;
            // Check if table exists before querying
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $table_exists = $wpdb->get_var("SHOW TABLES LIKE '{$table_name}'");
            if ($table_exists) {
                $wpdb->get_var("SELECT COUNT(*) FROM {$table_name} LIMIT 1");
            }
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        }
        
        $this->debug_log[] = '[Cold Start] Database connections warmed up';
    }
    
    /**
     * Warm up file system cache
     */
    private function warmup_file_system_cache() {
        // Access key directories to warm up file system cache
        $key_dirs = [
            ABSPATH,
            ABSPATH . 'wp-admin/',
            ABSPATH . 'wp-includes/',
            WP_CONTENT_DIR . '/plugins/',
            WP_CONTENT_DIR . '/themes/'
        ];
        
        foreach ($key_dirs as $dir) {
            if (is_dir($dir)) {
                // Just access directory to warm up cache
                @scandir($dir);
            }
        }
        
        $this->debug_log[] = '[Cold Start] File system cache warmed up';
    }
    
    /**
     * Enhanced SHAC calculation with security analysis
     */
    private function calculate_enhanced_shac($file_path, $relative_path) {
        // Skip SHAC for very large files during scanning to prevent timeouts
        $file_size = filesize($file_path);
        if ($file_size > 10 * 1024 * 1024) { // Skip files > 10MB during scanning
            return null;
        }
        
        // Get SHAC from Known Files system
        $start_time = microtime(true);
        
        // Use reflection to access private method for SHAC calculation
        $reflection = new ReflectionClass($this->known_files);
        $calculate_shac_method = $reflection->getMethod('calculate_shac');
        $calculate_shac_method->setAccessible(true);
        
        $shac_hash = $calculate_shac_method->invoke($this->known_files, $file_path);
        $calculation_time = microtime(true) - $start_time;
        
        if (!$shac_hash) {
            return null;
        }
        
        // Convert binary hash to hex for display
        $shac_hex = bin2hex($shac_hash);
        $shac_short = substr($shac_hex, 0, 16) . '...';
        
        // Basic pattern analysis for PHP files
        $suspicious_patterns = [];
        $threat_analysis = null;
        
        if (pathinfo($file_path, PATHINFO_EXTENSION) === 'php' && $file_size < 1024 * 1024) { // Only for PHP files < 1MB
            $suspicious_patterns = $this->analyze_file_patterns($file_path);
            
            // Add threat intelligence analysis
            $threat_analysis = $this->threat_intelligence->analyze_file_content($file_path);
        }
        
        // Analysis summary with threat intelligence
        $analysis = [
            'file_size' => $this->format_file_size($file_size),
            'calculation_time' => round($calculation_time * 1000, 2) . 'ms',
            'pattern_count' => count($suspicious_patterns),
            'risk_level' => $this->assess_file_risk($suspicious_patterns, $relative_path),
            'threat_intelligence' => $threat_analysis
        ];
        
        // Update SHAC statistics
        $this->shac_stats['files_processed']++;
        $this->shac_stats['total_calculation_time'] += $calculation_time;
        $this->shac_stats['suspicious_patterns_found'] += count($suspicious_patterns);
        if ($analysis['risk_level'] === 'high' || $analysis['risk_level'] === 'critical') {
            $this->shac_stats['high_risk_files']++;
        }
        
        return [
            'shac_hash' => $shac_hex,
            'shac_short' => $shac_short,
            'suspicious_patterns' => $suspicious_patterns,
            'analysis' => $analysis
        ];
    }
    
    /**
     * Analyze file for suspicious patterns
     */
    private function analyze_file_patterns($file_path) {
        $content = file_get_contents($file_path);
        if (!$content) {
            return [];
        }
        
        $patterns = [];
        
        // Check for suspicious PHP functions
        $suspicious_functions = [
            'eval(' => 'eval_function',
            'base64_decode(' => 'base64_decode',
            'shell_exec(' => 'shell_execution',
            'system(' => 'system_call',
            'exec(' => 'exec_function',
            'passthru(' => 'passthru_function'
        ];
        
        foreach ($suspicious_functions as $function => $pattern_name) {
            if (stripos($content, $function) !== false) {
                $patterns[] = $pattern_name;
            }
        }
        
        // Advanced malware patterns
        if (preg_match('/\b(eval|exec|system)\s*\(\s*\$_(GET|POST|REQUEST)\[/i', $content)) {
            $patterns[] = 'direct_execution_vulnerability';
        }
        
        if (preg_match('/base64_decode\s*\(\s*["\'][A-Za-z0-9+\/=]{50,}/i', $content)) {
            $patterns[] = 'encoded_payload';
        }
        
        return array_unique($patterns);
    }
    
    /**
     * Assess file risk level based on patterns and location
     */
    private function assess_file_risk($patterns, $relative_path) {
        if (empty($patterns)) {
            return 'low';
        }
        
        $risk_score = 0;
        
        // Pattern-based scoring
        foreach ($patterns as $pattern) {
            switch ($pattern) {
                case 'eval_function':
                case 'direct_execution_vulnerability':
                    $risk_score += 3;
                    break;
                case 'shell_execution':
                case 'system_call':
                case 'exec_function':
                    $risk_score += 2;
                    break;
                case 'encoded_payload':
                    $risk_score += 2;
                    break;
                default:
                    $risk_score += 1;
            }
        }
        
        // Location-based scoring
        if (strpos($relative_path, 'wp-admin/') === 0 || strpos($relative_path, 'wp-includes/') === 0) {
            $risk_score += 2; // Higher risk in core directories
        }
        
        if (strpos($relative_path, 'wp-content/uploads/') === 0) {
            $risk_score += 3; // Very high risk in uploads
        }
        
        // Risk level determination
        if ($risk_score >= 5) {
            return 'critical';
        } elseif ($risk_score >= 3) {
            return 'high';
        } elseif ($risk_score >= 1) {
            return 'medium';
        }
        
        return 'low';
    }
    
    /**
     * Format file size for display
     */
    private function format_file_size($bytes) {
        $units = ['B', 'KB', 'MB', 'GB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= pow(1024, $pow);
        return round($bytes, 2) . ' ' . $units[$pow];
    }
    
    /**
     * Calculate overall risk level based on SHAC statistics
     */
    private function calculate_overall_risk_level() {
        $total_files = $this->shac_stats['files_processed'];
        $high_risk = $this->shac_stats['high_risk_files'];
        $patterns = $this->shac_stats['suspicious_patterns_found'];
        
        if ($total_files == 0) {
            return 'unknown';
        }
        
        $risk_percentage = ($high_risk / $total_files) * 100;
        $pattern_density = ($patterns / $total_files) * 100;
        
        if ($risk_percentage > 1 || $pattern_density > 5) {
            return 'high';
        } elseif ($risk_percentage > 0.1 || $pattern_density > 1) {
            return 'medium';
        } else {
            return 'low';
        }
    }
    
    /**
     * Get intelligence recommendation based on analysis
     */
    private function get_intelligence_recommendation() {
        $high_risk = $this->shac_stats['high_risk_files'];
        $patterns = $this->shac_stats['suspicious_patterns_found'];
        
        if ($high_risk > 10) {
            return 'Manual review recommended for ' . $high_risk . ' high-risk files with multiple suspicious patterns.';
        } elseif ($high_risk > 0) {
            return 'Consider reviewing ' . $high_risk . ' files flagged as high-risk for potential security concerns.';
        } elseif ($patterns > 50) {
            return 'Large number of suspicious patterns detected (' . $patterns . '). Most are likely legitimate, but monitoring is advised.';
        } else {
            return 'Intelligence analysis complete. No immediate concerns detected, but continue regular monitoring.';
        }
    }
    
    /**
     * Recursively convert array to string for metadata display
     */
    private function array_to_string($array, $depth = 0) {
        if ($depth > 3) {
            return '[deeply nested array]';
        }
        
        $string_values = [];
        foreach ($array as $item) {
            if (is_array($item)) {
                $string_values[] = $this->array_to_string($item, $depth + 1);
            } elseif (is_object($item)) {
                $string_values[] = get_class($item);
            } else {
                $string_values[] = (string)$item;
            }
        }
        
        return implode(', ', $string_values);
    }
    
    /**
     * Get Severity Rating System statistics
     */
    public function get_severity_rating_stats() {
        return $this->severity_rating->get_severity_stats();
    }
    
    /**
     * Get Severity Rating debug log
     */
    public function get_severity_rating_debug_log() {
        return $this->severity_rating->get_debug_log();
    }
    
    /**
     * Sort scan issues by severity priority
     */
    public function sort_issues_by_severity($issues) {
        return $this->severity_rating->sort_issues_by_severity($issues);
    }
    
    /**
     * Get enhanced scan results with severity distribution
     */
    public function get_enhanced_scan_results_with_severity($scan_id = null) {
        $results = $this->get_scan_results($scan_id);
        
        // Add severity statistics
        $severity_stats = $this->get_severity_rating_stats();
        $results['severity_distribution'] = $severity_stats['severity_distribution'] ?? [];
        $results['severity_summary'] = [
            'critical_issues' => $severity_stats['critical_issues'] ?? 0,
            'high_issues' => $severity_stats['high_issues'] ?? 0,
            'medium_issues' => $severity_stats['medium_issues'] ?? 0,
            'low_issues' => $severity_stats['low_issues'] ?? 0,
            'total_rated' => $severity_stats['issues_rated'] ?? 0
        ];
        
        // Get issues sorted by severity
        $issues = $this->get_scan_issues($scan_id);
        $results['issues_by_severity'] = $this->sort_issues_by_severity($issues);
        
        return $results;
    }
}
