<?php
/**
 * VMPFence Vulnerability Scanner
 *
 * Analyzes WordPress installation for known vulnerabilities in core, plugins, and themes
 * using local-only processing. No external API calls are made.
 *
 * @package VMPFence
 * @since 1.0.0
 * @since 2.2.4 -- SQL Query fix
 */

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

class VMPFence_Vulnerability_Scanner {
    
    /**
     * Scan type identifier
     * @var string
     */
    private $scan_type = 'vulnerability';
    
    /**
     * Debug mode flag
     * @var bool
     */
    private $debug = false;
    
    /**
     * Debug log array
     * @var array
     */
    private $debug_log = [];
    
    /**
     * Scan options
     * @var array
     */
    private $scan_options = null;
    
    /**
     * Enhanced vulnerability patterns with CVSS-like scoring
     * @var array
     */
    private $vulnerability_patterns = [
        'core' => [
            // Known vulnerable WordPress versions with specific CVE data
            'critical_vulnerabilities' => [
                '6.0' => ['cvss' => 9.8, 'cve' => 'CVE-2022-21663', 'description' => 'WordPress Core 6.0.0 SQL Injection'],
                '5.9' => ['cvss' => 8.8, 'cve' => 'CVE-2022-21664', 'description' => 'WordPress Core 5.9.0 Cross-Site Scripting'],
                '5.8' => ['cvss' => 7.5, 'cve' => 'CVE-2021-39200', 'description' => 'WordPress Core 5.8.0 Path Traversal'],
                '5.7' => ['cvss' => 8.1, 'cve' => 'CVE-2021-29447', 'description' => 'WordPress Core 5.7.0 XXE in Media Library'],
                '5.6' => ['cvss' => 9.0, 'cve' => 'CVE-2021-29448', 'description' => 'WordPress Core 5.6.0 Object Injection'],
            ],
            'version_ranges' => [
                '4.x' => ['max_cvss' => 9.5, 'severity' => 'critical', 'description' => 'WordPress 4.x series has multiple critical vulnerabilities'],
                '5.0-5.5' => ['max_cvss' => 8.5, 'severity' => 'high', 'description' => 'WordPress 5.0-5.5 contains known high-severity vulnerabilities'],
                '5.6-5.8' => ['max_cvss' => 7.5, 'severity' => 'high', 'description' => 'WordPress 5.6-5.8 has documented security issues'],
                '5.9-6.0' => ['max_cvss' => 6.5, 'severity' => 'medium', 'description' => 'WordPress 5.9-6.0 lacks recent security patches']
            ]
        ],
        'plugin_indicators' => [
            'suspicious_patterns' => [
                'keywords' => ['nulled', 'cracked', 'free premium', 'warez', 'leaked', 'pirated'],
                'severity' => 'critical',
                'cvss' => 9.0,
                'description' => 'Plugin from untrusted source may contain malicious code'
            ],
            // NOTE: Abandonment/update indicators removed - handled by Update Scanner to prevent duplicates
            'known_vulnerable_plugins' => [
                // Common vulnerable plugins - would be updated from public DBs
                'revslider' => ['versions' => ['<5.4.8'], 'cvss' => 8.5, 'cve' => 'CVE-2020-11292'],
                'contact-form-7' => ['versions' => ['<5.1.1'], 'cvss' => 6.5, 'cve' => 'CVE-2020-35489'],
                'elementor' => ['versions' => ['<3.0.16'], 'cvss' => 7.5, 'cve' => 'CVE-2020-25073'],
                'yoast-seo' => ['versions' => ['<14.9'], 'cvss' => 6.1, 'cve' => 'CVE-2020-35942']
            ]
        ]
    ];
    
    /**
     * CVSS severity constants
     */
    const VULN_SEVERITY_CRITICAL = 90; // CVSS 9.0-10.0
    const VULN_SEVERITY_HIGH = 70;     // CVSS 7.0-8.9  
    const VULN_SEVERITY_MEDIUM = 40;   // CVSS 4.0-6.9
    const VULN_SEVERITY_LOW = 10;      // CVSS 0.1-3.9
    const VULN_SEVERITY_NONE = 0;      // CVSS 0.0
    
    /**
     * Public vulnerability databases for future integration
     * @var array
     */
    private $public_vuln_apis = [
        'nvd_api' => 'https://services.nvd.nist.gov/rest/json/cves/2.0', // NIST National Vulnerability Database
        'wpvulndb_api' => 'https://wpscan.com/api/v3', // WPScan Vulnerability Database (requires API key)
        'cvedetails_api' => 'https://www.cvedetails.com/api/', // CVE Details API
        'vulndb_api' => 'https://vulndb.cyberriskanalytics.com' // VulnDB (commercial but has free tier)
    ];
    
    /**
     * Constructor
     */
    public function __construct() {
        $this->debug = defined('WP_DEBUG') && WP_DEBUG;
    }
    
    /**
     * Run the vulnerability scan
     *
     * @param array $scan_options Optional scan configuration options
     * @return array Scan results
     */
    public function run_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') . '] Vulnerability Scanner: Performance controls initialized';
        }
        
        $start_time = microtime(true);
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Starting Vulnerability Scan (Local-Only Mode)';
        
        // If scan options provided, respect them
        if ($scan_options) {
            $this->scan_options = $scan_options;
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Vulnerability Scanner: Scan options loaded';
        }
        
        // Clear previous scan data
        $this->clear_previous_scan_data();
        
        $results = [
            'issues_found' => 0,
            'issues' => [],
            'scanned_count' => 0,
            'scan_type' => $this->scan_type,
            'debug_log' => []
        ];
        
        try {
            // 1. Check WordPress Core
            if (!$this->scan_options || !isset($this->scan_options['scansEnabled_vuln_core']) || $this->scan_options['scansEnabled_vuln_core']) {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Checking WordPress core vulnerabilities...';
                $core_issues = $this->scan_wordpress_core();
                $results['issues'] = array_merge($results['issues'], $core_issues);
                $results['scanned_count'] += 1; // Core counted as 1 item
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Vulnerability Scanner: Core vulnerabilities scan disabled by configuration';
            }
            
            // 2. Check Plugins
            if (!$this->scan_options || !isset($this->scan_options['scansEnabled_vuln_plugins']) || $this->scan_options['scansEnabled_vuln_plugins']) {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Checking plugin vulnerabilities...';
                $plugin_results = $this->scan_plugins();
                $results['issues'] = array_merge($results['issues'], $plugin_results['issues']);
                $results['scanned_count'] += $plugin_results['scanned_count'];
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Vulnerability Scanner: Plugin vulnerabilities scan disabled by configuration';
            }
            
            // 3. Check Themes
            if (!$this->scan_options || !isset($this->scan_options['scansEnabled_vuln_themes']) || $this->scan_options['scansEnabled_vuln_themes']) {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Checking theme vulnerabilities...';
                $theme_results = $this->scan_themes();
                $results['issues'] = array_merge($results['issues'], $theme_results['issues']);
                $results['scanned_count'] += $theme_results['scanned_count'];
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Vulnerability Scanner: Theme vulnerabilities scan disabled by configuration';
            }
            
            // NOTE: Update checking is handled by Update Scanner to prevent duplicate database entries
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Skipping update checks - handled by Update Scanner';
            
            $results['issues_found'] = count($results['issues']);
            
            // Create stats for database storage
            $results['stats'] = [
                'total_components' => $results['scanned_count'],
                'wordpress_core' => 1,
                'plugins_scanned' => count(get_plugins()),
                'themes_scanned' => count(wp_get_themes()),
                'scan_duration' => 0 // Will be calculated after scan
            ];
            
            // Save scan results
            $this->save_scan_results($results);
            
        } catch (Exception $e) {
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Error during vulnerability scan: ' . $e->getMessage();
            // error_log('VMPFence Vulnerability Scanner Error: ' . $e->getMessage());
        }
        
        $end_time = microtime(true);
        $scan_duration = round($end_time - $start_time, 2);
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Vulnerability scan completed in ' . $scan_duration . ' seconds';
        
        // Update scan duration in stats if they exist
        if (isset($results['stats'])) {
            $results['stats']['scan_duration'] = $scan_duration;
        }
        
        $results['debug_log'] = $this->debug_log;
        
        // Apply performance controls to limit issues if enabled
        if (class_exists('VMPFence_Performance_Manager')) {
            $results['issues'] = VMPFence_Performance_Manager::limit_issues($results['issues']);
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Performance Manager: Limited issues to ' . count($results['issues']);
        }
        
        return [
            'issues_found' => count($results['issues']),
            'issues' => $results['issues'],
            'scanned_count' => $results['scanned_count'],
            'scan_type' => $this->scan_type,
            'debug_log' => $this->debug_log
        ];
    }
    
    /**
     * Scan WordPress core for vulnerabilities with enhanced detection
     *
     * @return array Issues found
     */
    private function scan_wordpress_core() {
        $issues = [];
        
        // Get WordPress version
        global $wp_version;
        $current_version = $wp_version;
        
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Current WordPress version: ' . $current_version;
        
        // Check against specific known vulnerable versions
        foreach ($this->vulnerability_patterns['core']['critical_vulnerabilities'] as $vuln_version => $vuln_data) {
            if (version_compare($current_version, $vuln_version, '=')) {
                $issue = [
                    'type' => 'core_vulnerability',
                    'severity' => $this->cvssToSeverity($vuln_data['cvss']),
                    'title' => 'WordPress Core Vulnerability Detected',
                    'description' => $vuln_data['description'],
                    'details' => "WordPress {$current_version} contains a known vulnerability: {$vuln_data['cve']}",
                    'location' => 'WordPress Core',
                    'recommendation' => 'Update WordPress immediately to patch this security vulnerability',
                    'version' => $current_version,
                    'cvss_score' => $vuln_data['cvss'],
                    'cve_id' => $vuln_data['cve'],
                    'vulnerability_link' => "https://cve.mitre.org/cgi-bin/cvename.cgi?name={$vuln_data['cve']}"
                ];
                
                $issues[] = $issue;
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Found specific core vulnerability: ' . $vuln_data['cve'] . ' (CVSS: ' . $vuln_data['cvss'] . ')';
            }
        }
        
        // Check against version ranges
        foreach ($this->vulnerability_patterns['core']['version_ranges'] as $range => $range_data) {
            if ($this->isVersionInRange($current_version, $range)) {
                $issue = [
                    'type' => 'core_vulnerability_range',
                    'severity' => $range_data['severity'],
                    'title' => 'WordPress Core Security Risk',
                    'description' => $range_data['description'],
                    'details' => "WordPress {$current_version} is in vulnerable range {$range} with maximum CVSS score of {$range_data['max_cvss']}",
                    'location' => 'WordPress Core',
                    'recommendation' => 'Update WordPress to the latest version to address known security issues',
                    'version' => $current_version,
                    'cvss_score' => $range_data['max_cvss'],
                    'version_range' => $range
                ];
                
                $issues[] = $issue;
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Found core vulnerability in range: ' . $range . ' (Max CVSS: ' . $range_data['max_cvss'] . ')';
                break; // Only report one range match
            }
        }
        
        return $issues;
    }
    
    /**
     * Scan plugins for vulnerabilities with enhanced detection (Security-focused only)
     * Note: File integrity is handled by File Scanner - this focuses on known vulnerabilities
     *
     * @return array Results with issues and scanned count
     */
    private function scan_plugins() {
        $issues = [];
        $scanned_count = 0;
        
        // Get all plugins
        if (!function_exists('get_plugins')) {
            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
        }
        
        $all_plugins = get_plugins();
        $active_plugins = get_option('active_plugins', []);
        
        $processed_plugins = 0;
        foreach ($all_plugins as $plugin_file => $plugin_data) {
            // Performance throttling for plugin processing
            if (class_exists('VMPFence_Performance_Manager')) {
                VMPFence_Performance_Manager::throttle_processing($processed_plugins);
            }
            $processed_plugins++;
            
            $scanned_count++;
            $is_active = in_array($plugin_file, $active_plugins);
            $plugin_slug = $this->extractPluginSlug($plugin_file);
            
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Scanning plugin vulnerabilities: ' . $plugin_data['Name'] . ' v' . $plugin_data['Version'] . ($is_active ? ' (active)' : ' (inactive)');
            
            // **PRIMARY FOCUS: Check against known vulnerable plugins only**
            $vuln_issues = $this->checkKnownVulnerablePlugins($plugin_slug, $plugin_data, $plugin_file, $is_active);
            $issues = array_merge($issues, $vuln_issues);
            
            // **SECONDARY: Check for obvious suspicious patterns (nulled/cracked plugins)**
            // Note: General plugin integrity/abandonment is handled by File Scanner
            $suspicious_issues = $this->check_plugin_security_patterns_only($plugin_file, $plugin_data, $is_active);
            $issues = array_merge($issues, $suspicious_issues);
        }
        
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Vulnerability scan completed: ' . $scanned_count . ' plugins, found ' . count($issues) . ' security vulnerabilities';
        
        return [
            'issues' => $issues,
            'scanned_count' => $scanned_count
        ];
    }
    
    /**
     * Scan themes for vulnerabilities (Security-focused only)  
     * Note: File integrity is handled by File Scanner - this focuses on known vulnerabilities
     *
     * @return array Results with issues and scanned count
     */
    private function scan_themes() {
        $issues = [];
        $scanned_count = 0;
        
        // Get all themes
        if (!function_exists('wp_get_themes')) {
            require_once(ABSPATH . 'wp-includes/theme.php');
        }
        
        $all_themes = wp_get_themes();
        $current_theme = get_stylesheet();
        
        $processed_themes = 0;
        foreach ($all_themes as $theme_slug => $theme_obj) {
            // Performance throttling for theme processing
            if (class_exists('VMPFence_Performance_Manager')) {
                VMPFence_Performance_Manager::throttle_processing($processed_themes);
            }
            $processed_themes++;
            
            $scanned_count++;
            $is_active = ($theme_slug === $current_theme);
            
            $theme_data = [
                'Name' => $theme_obj->get('Name'),
                'Version' => $theme_obj->get('Version'),
                'Description' => $theme_obj->get('Description'),
                'Author' => $theme_obj->get('Author')
            ];
            
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Scanning theme vulnerabilities: ' . $theme_data['Name'] . ' v' . $theme_data['Version'] . ($is_active ? ' (active)' : ' (inactive)');
            
            // **FOCUS: Check for obvious suspicious patterns only (nulled/cracked themes)**
            // Note: General theme integrity/abandonment is handled by File Scanner
            $theme_issues = $this->check_theme_security_patterns_only($theme_slug, $theme_data, $is_active);
            $issues = array_merge($issues, $theme_issues);
        }
        
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Theme vulnerability scan completed: ' . $scanned_count . ' themes, found ' . count($issues) . ' security issues';
        
        return [
            'issues' => $issues,
            'scanned_count' => $scanned_count
        ];
    }
    
    /**
     * Check plugin for suspicious patterns (enhanced)
     *
     * @param string $plugin_file Plugin file path
     * @param array $plugin_data Plugin metadata
     * @param bool $is_active Whether plugin is active
     * @return array Issues found
     */
    private function check_plugin_suspicious_patterns($plugin_file, $plugin_data, $is_active) {
        $issues = [];
        $suspicious_data = $this->vulnerability_patterns['plugin_indicators']['suspicious_patterns'];
        $search_text = strtolower($plugin_data['Name'] . ' ' . $plugin_data['Description']);
        
        foreach ($suspicious_data['keywords'] as $keyword) {
            if (strpos($search_text, $keyword) !== false) {
                $issue = [
                    'type' => 'suspicious_plugin',
                    'severity' => $suspicious_data['severity'],
                    'title' => 'Suspicious Plugin Detected',
                    'description' => $suspicious_data['description'],
                    'details' => "Plugin '{$plugin_data['Name']}' contains suspicious keyword: {$keyword}",
                    'location' => $plugin_file,
                    'recommendation' => 'Remove this plugin and install from official WordPress repository',
                    'plugin_name' => $plugin_data['Name'],
                    'plugin_version' => $plugin_data['Version'],
                    'is_active' => $is_active,
                    'suspicious_keyword' => $keyword,
                    'cvss_score' => $suspicious_data['cvss']
                ];
                $issues[] = $issue;
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Suspicious plugin found: ' . $plugin_data['Name'] . ' (keyword: ' . $keyword . ')';
            }
        }
        
        return $issues;
    }
    
    /**
     * Check theme for suspicious patterns (enhanced)
     *
     * @param string $theme_slug Theme slug
     * @param array $theme_data Theme metadata
     * @param bool $is_active Whether theme is active
     * @return array Issues found
     */
    private function check_theme_suspicious_patterns($theme_slug, $theme_data, $is_active) {
        $issues = [];
        $suspicious_data = $this->vulnerability_patterns['plugin_indicators']['suspicious_patterns'];
        $search_text = strtolower($theme_data['Name'] . ' ' . $theme_data['Description']);
        
        foreach ($suspicious_data['keywords'] as $keyword) {
            if (strpos($search_text, $keyword) !== false) {
                $issue = [
                    'type' => 'suspicious_theme',
                    'severity' => $suspicious_data['severity'],
                    'title' => 'Suspicious Theme Detected',
                    'description' => 'Theme may be from untrusted or pirated source',
                    'details' => "Theme '{$theme_data['Name']}' contains suspicious keyword: {$keyword}",
                    'location' => $theme_slug,
                    'recommendation' => 'Remove this theme and install from official WordPress repository',
                    'theme_name' => $theme_data['Name'],
                    'theme_version' => $theme_data['Version'],
                    'is_active' => $is_active,
                    'suspicious_keyword' => $keyword,
                    'cvss_score' => $suspicious_data['cvss']
                ];
                $issues[] = $issue;
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Suspicious theme found: ' . $theme_data['Name'] . ' (keyword: ' . $keyword . ')';
            }
        }
        
        return $issues;
    }
    
    /**
     * Check theme for security-focused suspicious patterns only  
     * (NOT general integrity issues - those are handled by File Scanner)
     *
     * @param string $theme_slug The theme slug
     * @param array $theme_data Theme information
     * @param bool $is_active Whether theme is active
     * @return array Issues found
     */
    private function check_theme_security_patterns_only($theme_slug, $theme_data, $is_active) {
        $issues = [];
        $suspicious_data = $this->vulnerability_patterns['plugin_indicators']['suspicious_patterns'];
        $search_text = strtolower($theme_data['Name'] . ' ' . $theme_data['Description']);
        
        // **SECURITY FOCUS**: Only flag obvious security/piracy indicators
        // General integrity, abandonment handled by File Scanner
        foreach ($suspicious_data['keywords'] as $keyword) {
            if (strpos($search_text, $keyword) !== false) {
                $issue = [
                    'type' => 'suspicious_theme',
                    'severity' => $suspicious_data['severity'],
                    'title' => 'Suspicious Theme Detected - Security Risk',
                    'description' => 'Theme may be from untrusted or pirated source (security vulnerability)',
                    'details' => "Theme '{$theme_data['Name']}' contains suspicious keyword: {$keyword}. This could indicate a nulled/cracked theme which often contains malicious code.",
                    'location' => $theme_slug,
                    'recommendation' => 'URGENT: Remove this theme immediately and install from official WordPress repository',
                    'theme_name' => $theme_data['Name'],
                    'theme_version' => $theme_data['Version'],
                    'is_active' => $is_active,
                    'suspicious_keyword' => $keyword,
                    'cvss_score' => $suspicious_data['cvss']
                ];
                $issues[] = $issue;
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Security risk - suspicious theme found: ' . $theme_data['Name'] . ' (keyword: ' . $keyword . ')';
            }
        }
        
        return $issues;
    }
    
    /**
     * Convert CVSS score to severity level
     *
     * @param float $cvss_score CVSS score 0.0-10.0
     * @return string Severity level
     */
    private function cvssToSeverity($cvss_score) {
        $score_int = floor($cvss_score * 10);
        if ($score_int >= self::VULN_SEVERITY_CRITICAL) {
            return 'critical';
        } else if ($score_int >= self::VULN_SEVERITY_HIGH) {
            return 'high';
        } else if ($score_int >= self::VULN_SEVERITY_MEDIUM) {
            return 'medium';
        } else if ($score_int >= self::VULN_SEVERITY_LOW) {
            return 'low';
        }
        return 'none';
    }
    
    /**
     * Check if version is in a given range
     *
     * @param string $version Version to check
     * @param string $range Range like "4.x", "5.0-5.5", etc.
     * @return bool Whether version is in range
     */
    private function isVersionInRange($version, $range) {
        if (strpos($range, 'x') !== false) {
            // Handle ranges like "4.x"
            $major_version = substr($range, 0, strpos($range, '.'));
            return strpos($version, $major_version . '.') === 0;
        } else if (strpos($range, '-') !== false) {
            // Handle ranges like "5.0-5.5"
            list($min_version, $max_version) = explode('-', $range);
            return version_compare($version, $min_version, '>=') && version_compare($version, $max_version, '<=');
        }
        return false;
    }
    
    /**
     * Extract plugin slug from plugin file path
     *
     * @param string $plugin_file Plugin file path
     * @return string Plugin slug
     */
    private function extractPluginSlug($plugin_file) {
        if (preg_match('/^([^\/]+)\//', $plugin_file, $matches)) {
            return $matches[1];
        } else if (preg_match('/^([^\/.]+)\.php$/', $plugin_file, $matches)) {
            return $matches[1];
        }
        return dirname($plugin_file);
    }
    
    /**
     * Check plugins against known vulnerability database
     *
     * @param string $plugin_slug Plugin slug
     * @param array $plugin_data Plugin metadata
     * @param string $plugin_file Plugin file path
     * @param bool $is_active Whether plugin is active
     * @return array Issues found
     */
    private function checkKnownVulnerablePlugins($plugin_slug, $plugin_data, $plugin_file, $is_active) {
        $issues = [];
        
        if (isset($this->vulnerability_patterns['plugin_indicators']['known_vulnerable_plugins'][$plugin_slug])) {
            $vuln_info = $this->vulnerability_patterns['plugin_indicators']['known_vulnerable_plugins'][$plugin_slug];
            $current_version = $plugin_data['Version'];
            
            // Check if current version is in vulnerable range
            foreach ($vuln_info['versions'] as $vuln_version_range) {
                if ($this->isVersionVulnerable($current_version, $vuln_version_range)) {
                    $issue = [
                        'type' => 'plugin_vulnerability',
                        'severity' => $this->cvssToSeverity($vuln_info['cvss']),
                        'title' => 'Known Plugin Vulnerability',
                        'description' => "Plugin contains a known security vulnerability",
                        'details' => "Plugin '{$plugin_data['Name']}' version {$current_version} has a known vulnerability with CVSS score {$vuln_info['cvss']}",
                        'location' => $plugin_file,
                        'recommendation' => 'Update plugin to the latest version immediately',
                        'plugin_name' => $plugin_data['Name'],
                        'plugin_version' => $current_version,
                        'is_active' => $is_active,
                        'cvss_score' => $vuln_info['cvss'],
                        'cve_id' => $vuln_info['cve'],
                        'vulnerability_link' => "https://cve.mitre.org/cgi-bin/cvename.cgi?name={$vuln_info['cve']}"
                    ];
                    $issues[] = $issue;
                    $this->debug_log[] = '[' . current_time('H:i:s') . '] Found known vulnerable plugin: ' . $plugin_slug . ' v' . $current_version . ' (' . $vuln_info['cve'] . ')';
                }
            }
        }
        
        return $issues;
    }
    
    /**
     * Check plugin for security-focused suspicious patterns only
     * (NOT general integrity issues - those are handled by File Scanner)
     *
     * @param string $plugin_file Plugin file path
     * @param array $plugin_data Plugin information
     * @param bool $is_active Whether plugin is active
     * @return array Issues found
     */
    private function check_plugin_security_patterns_only($plugin_file, $plugin_data, $is_active) {
        $issues = [];
        $plugin_slug = dirname($plugin_file);
        
        // **SECURITY FOCUS**: Only check for obvious nulled/cracked/malicious patterns
        // General integrity, abandonment, etc. is handled by File Scanner
        
        $suspicious_data = $this->vulnerability_patterns['plugin_indicators']['suspicious_patterns'];
        $search_text = strtolower($plugin_data['Name'] . ' ' . $plugin_data['Description']);
        
        // Check for suspicious keywords indicating nulled/cracked plugins
        foreach ($suspicious_data['keywords'] as $keyword) {
            if (strpos($search_text, $keyword) !== false) {
                $issue = [
                    'type' => 'suspicious_plugin',
                    'severity' => $suspicious_data['severity'],
                    'title' => 'Suspicious Plugin Detected - Security Risk',
                    'description' => 'Plugin may be from untrusted or pirated source (security vulnerability)',
                    'details' => "Plugin '{$plugin_data['Name']}' contains suspicious keyword: {$keyword}. This could indicate a nulled/cracked plugin which often contains malicious code.",
                    'location' => $plugin_file,
                    'recommendation' => 'URGENT: Deactivate and remove this plugin immediately. Install from official WordPress repository.',
                    'plugin_name' => $plugin_data['Name'],
                    'plugin_version' => $plugin_data['Version'],
                    'is_active' => $is_active,
                    'suspicious_keyword' => $keyword,
                    'cvss_score' => $suspicious_data['cvss']
                ];
                $issues[] = $issue;
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Security risk - suspicious plugin found: ' . $plugin_data['Name'] . ' (keyword: ' . $keyword . ')';
            }
        }
        
        return $issues;
    }
    
    /**
     * Check if version is vulnerable based on version range
     *
     * @param string $current_version Current plugin version
     * @param string $vuln_range Vulnerable version range like "<5.4.8"
     * @return bool Whether version is vulnerable
     */
    private function isVersionVulnerable($current_version, $vuln_range) {
        if (strpos($vuln_range, '<') === 0) {
            $compare_version = substr($vuln_range, 1);
            return version_compare($current_version, $compare_version, '<');
        } else if (strpos($vuln_range, '<=') === 0) {
            $compare_version = substr($vuln_range, 2);
            return version_compare($current_version, $compare_version, '<=');
        } else if (strpos($vuln_range, '=') === 0) {
            $compare_version = substr($vuln_range, 1);
            return version_compare($current_version, $compare_version, '=');
        }
        return false;
    }
    
    /**
     * Clear previous scan data for this scan type
     */
    private function clear_previous_scan_data() {
        global $wpdb;
        
        // Clear previous scan issues from new table structure
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        $deleted_issues = $wpdb->query($wpdb->prepare(
            "DELETE FROM {$issues_table} WHERE issue_type = %s AND status != 'ignored'", 'vulnerability'  // 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", 'vulnerability'  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        ));
        
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Cleared previous vulnerability scan data from both issues and results tables';
    }
    
    /**
     * Save scan results to database
     *
     * @param array $results Scan results
     */
    private function save_scan_results($results) {
        global $wpdb;
        
        // First, save scan summary to scan_results table
        $scan_results_table = $wpdb->prefix . 'vmpfence_scan_results';
        $scan_result_id = $wpdb->insert(
            $scan_results_table,
            [
                'scan_type' => 'vulnerability',
                'scan_time' => current_time('mysql'),
                'total_files' => $results['stats']['total_components'],
                'issues_found' => count($results['issues']),
                'scan_status' => 'completed',
                'scan_data' => wp_json_encode($results['stats'])
            ]
        );
        
        if ($scan_result_id === false) {
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Error saving scan results summary: ' . $wpdb->last_error;
            return;
        }
        
        $scan_id = $wpdb->insert_id;
        
        // Then save individual issues to scan_issues table
        $scan_issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        foreach ($results['issues'] as $issue) {
            $description = $issue['title'] . ': ' . $issue['description'];
            
            // For suspicious_plugin type, create enhanced description with detailed information
            if ($issue['type'] === 'suspicious_plugin' && isset($issue['plugin_name'])) {
                $detailed_info = [
                    'basic_description' => $description,
                    'plugin_name' => $issue['plugin_name'] ?? '',
                    'plugin_version' => $issue['plugin_version'] ?? '',
                    'suspicious_keyword' => $issue['suspicious_keyword'] ?? '',
                    'details' => $issue['details'] ?? '',
                    'recommendation' => $issue['recommendation'] ?? ''
                ];
                $description = json_encode($detailed_info);
            }
            
            // First check if this issue should be recreated as ignored
            if ($this->handle_ignored_issue($issue['location'], 'vulnerability', $description, $scan_id, $issue['type'])) {
                continue; // Issue was handled as ignored, skip normal processing
            }
            
            // Check if this issue is currently ignored (skip normal creation)
            if ($this->is_issue_ignored($issue['location'], 'vulnerability', $description)) {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] SKIP: Vulnerability already ignored - ' . $issue['location'];
                continue;
            }

            $insert_result = $wpdb->insert(
                $scan_issues_table,
                [
                    'scan_id' => $scan_id,
                    'file_path' => $issue['location'],
                    'issue_type' => 'vulnerability', // Broad category
                    'type' => $issue['type'], // Specific vulnerability type
                    'severity' => $issue['severity'], // Use the issue's specific severity
                    'description' => $description,
                    'detected_time' => current_time('mysql'),
                    'status' => 'new'
                ]
            );
            
            if ($insert_result === false) {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] Error saving issue: ' . $wpdb->last_error;
            }
        }
        
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Saved scan summary (ID: ' . $scan_id . ') and ' . count($results['issues']) . ' vulnerability issues to database';
    }

    /**
     * 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';
        
        $count = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$issues_table} WHERE file_path = %s AND issue_type = %s AND description = %s AND status = 'ignored'",  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $file_path,
            $issue_type,
            $description
        ));
        
        return $count > 0;
    }
    
    /**
     * 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
     * @param string $type Specific vulnerability type
     * @return bool Whether issue was handled
     */
    private function handle_ignored_issue($file_path, $issue_type, $description, $scan_id, $type = null) {
        global $wpdb;
        
        $issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        // Check if this exact issue was previously ignored
        $ignored_issue = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$issues_table} WHERE file_path = %s AND issue_type = %s AND description = %s AND status = 'ignored' ORDER BY detected_time DESC LIMIT 1",  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $file_path,
            $issue_type,
            $description
        ));
        
        if ($ignored_issue) {
            // Recreate the ignored issue in current scan
            $insert_result = $wpdb->insert(
                $issues_table,
                [
                    'scan_id' => $scan_id,
                    'file_path' => $file_path,
                    'issue_type' => $issue_type,
                    'type' => $type ?? $ignored_issue->type ?? 'vulnerability', // Use provided type or fallback
                    'severity' => $ignored_issue->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) {
                // Clean up old ignored entries for this same issue (keep only the latest)
                $wpdb->query($wpdb->prepare(
                    "DELETE FROM {$issues_table} WHERE file_path = %s AND issue_type = %s AND description = %s AND status = 'ignored' AND id != %d",  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
                    $file_path,
                    $issue_type,
                    $description,
                    $wpdb->insert_id
                ));
                
                $this->debug_log[] = '[' . current_time('H:i:s') . '] PRESERVED: Recreated ignored vulnerability - ' . $file_path;
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Map issue type to severity level
     *
     * @param string $issue_type Issue type
     * @return string Severity level
     */
    private function map_issue_type_to_severity($issue_type) {
        switch ($issue_type) {
            case 'vulnerability':
                return 'high';
            default:
                return 'medium';
        }
    }
    
    /**
     * Get scan type identifier
     *
     * @return string Scan type
     */
    public function get_scan_type() {
        return $this->scan_type;
    }
    
    /**
     * Future: Integrate with public vulnerability databases
     * This method can be called periodically to update vulnerability patterns
     * from public sources like NIST NVD, WPScan DB, etc.
     */
    public function updateVulnerabilityDatabase() {
        $this->debug_log[] = '[' . current_time('H:i:s') . '] TODO: Implement automatic vulnerability database updates from public APIs';
        
        // TODO: Future implementation could include:
        // 1. Fetch from NIST NVD API: https://services.nvd.nist.gov/rest/json/cves/2.0
        // 2. Update WordPress.org plugin/theme vulnerabilities
        // 3. Integrate with WPScan vulnerability database
        // 4. Cache results locally to reduce API calls
        // 5. Update $this->vulnerability_patterns with fresh data
        
        return false; // Not implemented yet
    }
    
    /**
     * Check if an enhanced vulnerability database is available
     * 
     * @return bool Whether enhanced database is available
     */
    public function hasEnhancedDatabase() {
        // This would check if we have access to real-time vulnerability data
        return false; // Currently using local patterns only
    }
}
