<?php
/**
 * VMPFence User Security Scanner
 *
 * Analyzes WordPress user accounts for security vulnerabilities including
 * username risks, account configurations, and provides framework for future
 * password strength implementation.
 *
 * @package VMPFence
 * @since 1.0.0
 */

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

class VMPFence_User_Security_Scanner {
    
    /**
     * Scan type identifier
     * @var string
     */
    private $scan_type = 'user_security';
    
    /**
     * Current admin list cache
     * @var array
     */
    private $current_admin_list = array();
    
    /**
     * Suspicious admin username patterns
     * These patterns match common malicious admin usernames created by attackers
     * @var array
     */
    private $suspicious_admin_patterns = [
        '/^admin[0-9]*$/',           // admin, admin1, admin123
        '/^administrator[0-9]*$/',   // administrator, administrator1
        '/^root[0-9]*$/',            // root, root1, root123
        '/^test[0-9]*$/',            // test, test1, test123
        '/^demo[0-9]*$/',            // demo, demo1, demo123
        '/^guest[0-9]*$/',           // guest, guest1
        '/^user[0-9]*$/',            // user, user1, user123
        '/^support[0-9]*$/',         // support, support1
        '/^service[0-9]*$/',         // service, service1
        '/^wp[0-9]*$/',              // wp, wp1, wp123
        '/^backup[0-9]*$/',          // backup, backup1
        '/^temp[0-9]*$/',            // temp, temp1, temp123
        '/^default[0-9]*$/',         // default, default1
        '/^system[0-9]*$/',          // system, system1
        '/^operator[0-9]*$/',        // operator, operator1
        '/^manager[0-9]*$/',         // manager, manager1
        '/^webmaster[0-9]*$/',       // webmaster, webmaster1
        '/^owner[0-9]*$/',           // owner, owner1
        '/^master[0-9]*$/',          // master, master1
        '/^superuser[0-9]*$/',       // superuser, superuser1
        '/^dev[0-9]*$/',             // dev, dev1, dev123
        '/^developer[0-9]*$/',       // developer, developer1
        '/^api[0-9]*$/',             // api, api1, api123
    ];
    
    /**
     * Common risky usernames list (kept for backward compatibility)
     * @var array
     */
    private $risky_usernames = [
        'admin', 'administrator', 'root', 'test', 'demo', 'guest',
        'user', 'manager', 'support', 'service', 'operator',
        'wp-admin', 'wordpress', 'wp', 'blog', 'website', 'owner',
        'webmaster', 'superuser', 'dev', 'developer', 'api',
        'backup', 'mail', 'email', 'ftp', 'ssh', 'login'
    ];
    
    /**
     * Common weak passwords list (for future password strength implementation)
     * @var array
     */
    private $common_weak_passwords = [
        'password', 'password1', 'password123', '123456', '123456789', 'qwerty',
        'abc123', 'password1!', 'admin', 'administrator', 'root', 'test',
        'guest', 'user', 'demo', 'welcome', 'letmein', '1234567890',
        'qwertyuiop', 'asdfghjkl', 'zxcvbnm', 'monkey', 'dragon', 'master',
        'superman', 'batman', 'football', 'baseball', 'basketball', 'soccer',
        'princess', 'flower', 'sunshine', 'rainbow', 'shadow', 'silver',
        'golden', 'winner', 'login', 'pass', 'secret', 'trustno1',
        'Password', 'Password1', 'Admin123', 'Test123', 'Welcome1',
        '12345678', '1234567', '123123', '111111', '000000', 'password!',
        'pass123', 'admin123', 'root123', 'guest123', 'test123'
    ];
    
    /**
     * Dictionary words to check against (for future password strength implementation)
     * @var array
     */
    private $dictionary_words = [
        'house', 'green', 'black', 'white', 'red', 'blue', 'yellow',
        'love', 'home', 'family', 'friend', 'happy', 'computer',
        'internet', 'email', 'phone', 'mobile', 'windows', 'linux',
        'apple', 'google', 'facebook', 'twitter', 'instagram', 'wordpress'
    ];
    
    /**
     * Minimum password length for security (for future implementation)
     * @var int
     */
    private $minimum_secure_length = 12;
    
    /**
     * Debug mode flag
     * @var bool
     */
    private $debug = false;
    
    /**
     * Debug log array
     * @var array
     */
    private $debug_log = [];
    
    /**
     * Scan options
     * @var array
     */
    private $scan_options = null;
    
    /**
     * Constructor
     */
    public function __construct() {
        $this->debug = defined('WP_DEBUG') && WP_DEBUG;
    }
    
    /**
     * Run the user security scan
     *
     * @param array $scan_options Optional scan configuration options
     * @return array Scan results
     */
    public function run_scan($scan_options = null) {
        $start_time = microtime(true);
        $this->debug_log[] = '[' . current_time('H:i:s') . '] Starting User Security Analysis';
        $this->log_debug("Starting user security scan");
        
        // Load performance manager if available
        $use_performance_controls = false;
        if (class_exists('VMPFence_Performance_Manager')) {
            $use_performance_controls = true;
        }
        
        // If scan options provided, respect them
        if ($scan_options) {
            $this->scan_options = $scan_options;
            $this->debug_log[] = '[' . current_time('H:i:s') . '] User Security Scanner: Scan options loaded';
        }
        
        try {
            // Clear previous scan data
            $this->clear_previous_scan_data();
            $this->debug_log[] = '[' . current_time('H:i:s') . '] Previous user security scan data cleared';
            
            // Initialize admin monitoring
            $this->initialize_admin_monitoring();
            
            $scan_results = [];
            $users_checked = 0;
            $vulnerabilities_found = 0;
            $checks_executed = [];
            $checks_failed = [];
            
            // Track which checks are executed - respecting scan options
            $checks_to_run = [];
            
            // Password strength check - controlled by scansEnabled_passwds
            if (isset($this->scan_options['scansEnabled_passwds']) && $this->scan_options['scansEnabled_passwds']) {
                $checks_to_run['check_password_strength'] = 'Password Strength Analysis';
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] User Security: Password strength check disabled by configuration';
            }
            
            // Suspicious admin users - ONLY controlled by scansEnabled_suspiciousAdminUsers
            if (!$this->scan_options || !isset($this->scan_options['scansEnabled_suspiciousAdminUsers']) || $this->scan_options['scansEnabled_suspiciousAdminUsers']) {
                $checks_to_run['check_suspicious_admin_users'] = 'Suspicious Admin Users (Outside WordPress)';
            } else {
                $this->debug_log[] = '[' . current_time('H:i:s') . '] User Security: Suspicious admin users check disabled by configuration';
            }
            
            foreach ($checks_to_run as $method => $description) {
                try {
                    $this->debug_log[] = '[Scan Controller] Executing: ' . $description;
                    $issues_before = count($scan_results);
                    
                    if ($method === 'check_password_strength') {
                        $password_issues = $this->check_password_strength();
                        $scan_results = array_merge($scan_results, $password_issues);
                        $users_checked += count(get_users(['role' => 'administrator']));
                    } elseif ($method === 'check_suspicious_admin_users') {
                        $admin_issues = $this->check_suspicious_admin_users();
                        $scan_results = array_merge($scan_results, $admin_issues);
                        $users_checked += count($this->get_current_admins());
                    }
                    
                    $issues_after = count($scan_results);
                    $new_issues = $issues_after - $issues_before;
                    
                    $checks_executed[] = $method;
                    $this->debug_log[] = '[Scan Controller] ✓ Completed: ' . $description . ' (found ' . $new_issues . ' issues)';
                    
                } catch (Exception $e) {
                    $checks_failed[] = $method;
                    $this->debug_log[] = '[Scan Controller] ✗ FAILED: ' . $description . ' - Error: ' . $e->getMessage();
                } catch (Error $e) {
                    $checks_failed[] = $method;
                    $this->debug_log[] = '[Scan Controller] ✗ FATAL ERROR: ' . $description . ' - Error: ' . $e->getMessage();
                }
            }
            
            $this->debug_log[] = '[User Security] Analyzed ' . $users_checked . ' user accounts';
            
            // Log execution summary
            $total_checks = count($checks_to_run);
            $successful_checks = count($checks_executed);
            $failed_checks = count($checks_failed);
            
            $this->debug_log[] = '[Scan Controller] === EXECUTION SUMMARY ===';
            $this->debug_log[] = '[Scan Controller] Total checks planned: ' . $total_checks;
            $this->debug_log[] = '[Scan Controller] Successful checks: ' . $successful_checks;
            $this->debug_log[] = '[Scan Controller] Failed checks: ' . $failed_checks;
            
            if (!empty($checks_failed)) {
                $this->debug_log[] = '[Scan Controller] Failed check methods: ' . implode(', ', $checks_failed);
            }
            
            // Save scan results
            $this->save_scan_results($scan_results, $users_checked);
            $this->debug_log[] = '[User Security] Saved ' . count($scan_results) . ' security issues to database';
            
            $scan_time = round((microtime(true) - $start_time), 2);
            $this->debug_log[] = '[' . current_time('H:i:s') . '] User Security Analysis Complete - Found ' . count($scan_results) . ' vulnerabilities in ' . $scan_time . 's';
            $this->log_debug("User security scan completed in {$scan_time} seconds");
            
            $result = [
                'success' => true,
                'users_checked' => $users_checked,
                'issues_found' => count($scan_results),
                'vulnerabilities_found' => $vulnerabilities_found,
                'scan_time' => $scan_time,
                'scan_type' => $this->scan_type,
                'debug_log' => $this->debug_log,
                'checks_executed' => $checks_executed,
                'checks_failed' => $checks_failed
            ];
            
            return $result;
            
        } catch (Exception $e) {
            $this->debug_log[] = '[' . current_time('H:i:s') . '] SCAN ERROR: ' . $e->getMessage();
            $this->log_debug("User security scan error: " . $e->getMessage());
            return [
                'success' => false,
                'error' => $e->getMessage(),
                'scan_type' => $this->scan_type,
                'debug_log' => $this->debug_log
            ];
        }
    }
    
    /**
     * Get all WordPress users
     *
     * @return array Array of WP_User objects
     */
    private function get_all_users() {
        $users = get_users([
            'number' => -1, // Get all users
            'fields' => 'all'
        ]);
        
        return $users;
    }
    
    /**
     * Analyze a user's security configuration
     *
     * @param WP_User $user WordPress user object
     * @return array Array of security issues found
     */
    private function analyze_user_security($user) {
        $issues = [];
        
        $this->debug_log[] = '[User Security] Analyzing user: ' . $user->user_login . ' (ID: ' . $user->ID . ')';
        
        // Check for risky usernames (security risk)
        if ($this->is_risky_username($user->user_login)) {
            $this->debug_log[] = '[User Security] VULNERABILITY: Risky username detected - ' . $user->user_login;
            $issues[] = [
                'type' => 'weak_username',
                'severity' => 'high',
                'title' => 'High-Risk Username Detected',
                'description' => "User '{$user->user_login}' uses a common/predictable username that significantly increases brute force attack risk.",
                'details' => "Username: {$user->user_login} (ID: {$user->ID}) - This username is commonly targeted by automated attacks",
                'recommendation' => 'Change this username to something unique and unpredictable, or implement strong password policies and 2FA.',
                'user_id' => $user->ID,
                'username' => $user->user_login,
                'user_role' => implode(', ', $user->roles)
            ];
        }
        
        // Check for admin users with simple usernames
        if ($this->is_admin_user($user) && $this->is_simple_username($user->user_login)) {
            $this->debug_log[] = '[User Security] VULNERABILITY: Admin with simple username - ' . $user->user_login;
            $issues[] = [
                'type' => 'admin_weak',
                'severity' => 'critical',
                'title' => 'Administrator with Weak Username',
                'description' => "Administrator '{$user->user_login}' has a simple username that could be easily guessed by attackers.",
                'details' => "Admin Username: {$user->user_login} (ID: {$user->ID}) - Simple usernames on admin accounts pose extreme security risks",
                'recommendation' => 'Admin users must have complex, non-predictable usernames. Consider creating a new admin account with a strong username.',
                'user_id' => $user->ID,
                'username' => $user->user_login,
                'user_role' => implode(', ', $user->roles)
            ];
        }
        
        // Check if user email matches username (potential security risk)
        if ($user->user_login === $user->user_email || 
            strpos($user->user_email, $user->user_login . '@') === 0) {
            $this->debug_log[] = '[User Security] VULNERABILITY: Username-email pattern match - ' . $user->user_login;
            $issues[] = [
                'type' => 'email_match',
                'severity' => 'medium',
                'title' => 'Username Predictable from Email',
                'description' => "User '{$user->user_login}' has a username that matches their email pattern, making it easier for attackers to guess.",
                'details' => "Username: {$user->user_login}, Email: {$user->user_email} - Pattern matching increases attack surface",
                'recommendation' => 'Use different usernames and email addresses to reduce predictability and enumeration risks.',
                'user_id' => $user->ID,
                'username' => $user->user_login,
                'user_role' => implode(', ', $user->roles)
            ];
        }
        
        // Check for users without proper display names (enumeration risk)
        if (empty($user->display_name) || $user->display_name === $user->user_login) {
            $this->debug_log[] = '[User Security] VULNERABILITY: Username exposed as display name - ' . $user->user_login;
            $issues[] = [
                'type' => 'name_exposed',
                'severity' => 'low',
                'title' => 'Username Enumeration Risk',
                'description' => "User '{$user->user_login}' has their username exposed as display name, enabling user enumeration attacks.",
                'details' => "Username/Display Name: {$user->user_login} - This exposure facilitates targeted attacks",
                'recommendation' => 'Set a different display name to prevent username enumeration and reduce attack targeting.',
                'user_id' => $user->ID,
                'username' => $user->user_login,
                'user_role' => implode(', ', $user->roles)
            ];
        }
        
        // Check for numeric-only usernames (weak pattern)
        if (is_numeric($user->user_login)) {
            $this->debug_log[] = '[User Security] VULNERABILITY: Numeric-only username - ' . $user->user_login;
            $issues[] = [
                'type' => 'numeric_username',
                'severity' => 'medium',
                'title' => 'Numeric-Only Username Pattern',
                'description' => "User '{$user->user_login}' uses a numeric-only username which is easily guessable through enumeration.",
                'details' => "Numeric Username: {$user->user_login} (ID: {$user->ID}) - Sequential numeric usernames are predictable",
                'recommendation' => 'Use alphanumeric usernames with mixed characters to increase security.',
                'user_id' => $user->ID,
                'username' => $user->user_login,
                'user_role' => implode(', ', $user->roles)
            ];
        }
        
        return $issues;
    }
    
    /**
     * Check if username is risky (common attack targets)
     *
     * @param string $username Username to check
     * @return bool True if risky
     */
    private function is_risky_username($username) {
        return in_array(strtolower($username), array_map('strtolower', $this->risky_usernames));
    }
    
    /**
     * Check if username is too simple
     *
     * @param string $username Username to check
     * @return bool True if simple
     */
    private function is_simple_username($username) {
        // Check for very short usernames
        if (strlen($username) < 4) {
            return true;
        }
        
        // Check for numeric only
        if (is_numeric($username)) {
            return true;
        }
        
        // Check for simple patterns like user1, admin1, test123
        if (preg_match('/^(user|admin|test|demo|guest|root)\d*$/i', $username)) {
            return true;
        }
        
        // Check for keyboard patterns
        $keyboard_patterns = ['qwerty', 'asdf', 'zxcv', '123456', 'abcdef'];
        foreach ($keyboard_patterns as $pattern) {
            if (stripos($username, $pattern) !== false) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Check if user has admin privileges
     *
     * @param WP_User $user WordPress user object
     * @return bool True if admin
     */
    private function is_admin_user($user) {
        return in_array('administrator', $user->roles) || user_can($user, 'manage_options');
    }
    
    /**
     * Check admin account security issues
     *
     * @return array Array of admin security issues
     */
    private function check_admin_account_security() {
        $issues = [];
        
        // Check for multiple admin users (security concern)
        $admin_users = get_users(['role' => 'administrator']);
        $this->debug_log[] = '[User Security] Found ' . count($admin_users) . ' administrator accounts';
        
        if (count($admin_users) > 3) {
            $this->debug_log[] = '[User Security] WARNING: Excessive admin accounts detected (' . count($admin_users) . ')';
            $issues[] = [
                'type' => 'excessive_admins',
                'severity' => 'medium',
                'title' => 'Too Many Administrator Accounts',
                'description' => 'Your site has ' . count($admin_users) . ' administrator accounts, which increases security risk and attack surface.',
                'details' => 'Admin users: ' . implode(', ', array_map(function($u) { return $u->user_login; }, $admin_users)),
                'recommendation' => 'Limit administrator accounts to only necessary users. Use lower privilege roles (Editor, Author) when full admin access is not required.',
                'user_count' => count($admin_users)
            ];
        }
        
        // Check for admin user with ID 1 (common attack target)
        $admin_user_1 = get_user_by('id', 1);
        if ($admin_user_1 && in_array('administrator', $admin_user_1->roles)) {
            $this->debug_log[] = '[User Security] WARNING: Admin user with ID 1 detected - ' . $admin_user_1->user_login;
            $issues[] = [
                'type' => 'admin_user_id_1',
                'severity' => 'high',
                'title' => 'Administrator User with ID 1',
                'description' => "Administrator user '{$admin_user_1->user_login}' has user ID 1, which is the primary target for automated attacks.",
                'details' => "Username: {$admin_user_1->user_login}, ID: 1 - This is the default WordPress admin account creation pattern",
                'recommendation' => 'Create a new admin user with a different ID and username, then demote or remove this account.',
                'user_id' => 1,
                'username' => $admin_user_1->user_login
            ];
        }
        
        // Check for admin users with no recent activity (potential security risk)
        foreach ($admin_users as $admin) {
            $last_login = get_user_meta($admin->ID, 'last_login', true);
            if (empty($last_login)) {
                $this->debug_log[] = '[User Security] WARNING: Admin user with no login history - ' . $admin->user_login;
                $issues[] = [
                    'type' => 'inactive_admin',
                    'severity' => 'low',
                    'title' => 'Administrator with No Login History',
                    'description' => "Administrator '{$admin->user_login}' has no recorded login activity, which may indicate an unused or compromised account.",
                    'details' => "Username: {$admin->user_login} (ID: {$admin->ID}) - No login metadata found",
                    'recommendation' => 'Review this admin account and remove it if not actively used, or ensure it has proper security measures.',
                    'user_id' => $admin->ID,
                    'username' => $admin->user_login
                ];
            }
        }
        
        return $issues;
    }
    
    /**
     * Check for user enumeration risks
     *
     * @return array Array of enumeration security issues
     */
    private function check_user_enumeration_risks() {
        $issues = [];
        
        // Check for sequential user IDs with exposed usernames
        $users = get_users(['number' => 10, 'orderby' => 'ID', 'order' => 'ASC']);
        $sequential_pattern = true;
        
        for ($i = 1; $i < count($users); $i++) {
            if ($users[$i]->ID != $users[$i-1]->ID + 1) {
                $sequential_pattern = false;
                break;
            }
        }
        
        if ($sequential_pattern && count($users) > 5) {
            $this->debug_log[] = '[User Security] WARNING: Sequential user ID pattern detected';
            $issues[] = [
                'type' => 'sequential_ids',
                'severity' => 'low',
                'title' => 'Sequential User ID Pattern',
                'description' => 'Your site uses sequential user IDs, which makes user enumeration attacks easier to execute.',
                'details' => 'User IDs follow predictable sequential pattern: ' . implode(', ', array_map(function($u) { return $u->ID; }, array_slice($users, 0, 5))),
                'recommendation' => 'Consider implementing user ID obfuscation or ensure REST API user endpoints are properly secured.',
                'pattern_detected' => 'sequential'
            ];
        }
        
        // Check for REST API user enumeration risk
        if (rest_url('wp/v2/users')) {
            $this->debug_log[] = '[User Security] INFO: REST API user endpoints are available';
            $issues[] = [
                'type' => 'api_exposure',
                'severity' => 'low',
                'title' => 'REST API User Enumeration Possible',
                'description' => 'WordPress REST API user endpoints are accessible, potentially allowing username enumeration.',
                'details' => 'REST API endpoint available: ' . rest_url('wp/v2/users'),
                'recommendation' => 'Consider disabling REST API user endpoints or implementing access controls to prevent unauthorized enumeration.',
                'endpoint' => rest_url('wp/v2/users')
            ];
        }
        
        return $issues;
    }
    
    /**
     * Clear previous scan data for this scan type
     */
    private function clear_previous_scan_data() {
        global $wpdb;
        
        $this->debug_log[] = '[User Security] Starting cleanup of previous scan data';
        
        // 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'",  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $this->scan_type
        ));
        
        $this->debug_log[] = '[User Security] Deleted ' . $deleted_issues . ' previous user security issues';
        
        // 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",  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $this->scan_type
        ));
        
        $this->debug_log[] = '[User Security] Deleted ' . $deleted_results . ' previous scan result records';
        $this->log_debug("Cleared previous user security scan data from both issues and results tables");
    }
    
    /**
     * Save scan results to database
     *
     * @param array $results Scan results to save
     * @param int $users_checked Total number of users checked during scan
     */
    private function save_scan_results($results, $users_checked = 0) {
        global $wpdb;
        
        $this->debug_log[] = '[User Security] Saving scan results - ' . count($results) . ' issues found, ' . $users_checked . ' users checked';
        
        // Always save scan summary to scan_results table (even with 0 issues)
        $scan_results_table = $wpdb->prefix . 'vmpfence_scan_results';
        $scan_result_id = $wpdb->insert(
            $scan_results_table,
            [
                'scan_type' => 'user_security',
                'scan_time' => current_time('mysql'),
                'total_files' => 0, // User security scans don't scan files
                'issues_found' => count($results),
                'scan_status' => 'completed',
                'scan_data' => wp_json_encode([
                    'users_scanned' => $users_checked, // Use actual users checked, not issues found
                    'scan_type' => 'user_security'
                ])
            ]
        );
        
        if ($scan_result_id === false) {
            $this->debug_log[] = '[User Security] ERROR: Failed to insert scan summary: ' . $wpdb->last_error;
            $this->log_debug('Error saving scan summary: ' . $wpdb->last_error);
            return;
        } else {
            $this->debug_log[] = '[User Security] Successfully inserted scan summary with ID: ' . $wpdb->insert_id . ' (issues: ' . count($results) . ', users: ' . $users_checked . ')';
        }
        
        $scan_id = $wpdb->insert_id;
        
        // Only save individual issues if there are any
        if (empty($results)) {
            $this->debug_log[] = '[User Security] No user security issues to save (scan completed successfully with 0 issues)';
            $this->log_debug("No user security issues found");
            return;
        }
        
        // Save individual issues to scan_issues table
        $scan_issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        $successful_inserts = 0;
        foreach ($results as $index => $result) {
            $recommendation = isset($result['recommendation']) ? $result['recommendation'] : 'Review and address this security issue.';
            $description = $result['title'] . ': ' . $result['description'] . ' Details: ' . $result['details'] . ' Solution: ' . $recommendation;
            
            // First check if this issue should be recreated as ignored
            if ($this->handle_ignored_issue('', 'user_security', $description, $scan_id)) {
                continue; // Issue was handled as ignored, skip normal processing
            }
            
            // Check if this issue is currently ignored (skip normal creation)
            if ($this->is_issue_ignored('', 'user_security', $description)) {
                $this->debug_log[] = '[User Security] SKIP: User security issue already ignored - ' . $result['title'];
                $this->log_debug('SKIP: User security issue already ignored - ' . $result['title']);
                continue;
            }

            $insert_result = $wpdb->insert(
                $scan_issues_table,
                [
                    'scan_id' => $scan_id,
                    'file_path' => '', // Not applicable for user security
                    'issue_type' => 'user_security',
                    'type' => $result['type'] ?? 'user_account', // Use specific type from issue
                    'severity' => $this->map_issue_type_to_severity('user_security'),
                    'description' => $description,
                    'detected_time' => current_time('mysql'),
                    'status' => 'new'
                ]
            );
            
            if ($insert_result === false) {
                $this->debug_log[] = '[User Security] ERROR: Failed to insert issue ' . $index . ': ' . $wpdb->last_error;
                $this->log_debug('Error saving user security issue: ' . $wpdb->last_error);
            } else {
                $successful_inserts++;
                $this->debug_log[] = '[User Security] Successfully inserted issue ' . $index . ' with ID: ' . $wpdb->insert_id . ' - Type: ' . ($result['type'] ?? 'user_account');
            }
        }
        
        $this->debug_log[] = '[User Security] Saved ' . $successful_inserts . ' out of ' . count($results) . ' user security issues to database';
        $this->log_debug("Saved scan summary (ID: " . $scan_id . ") and " . $successful_inserts . " user security issues to database");
    }
    
    /**
     * Check if an issue is already ignored
     */
    private function is_issue_ignored($file_path, $issue_type, $description) {
        global $wpdb;
        $scan_issues_table = $wpdb->prefix . 'vmpfence_scan_issues';
        
        $count = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM $scan_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
     * @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
        $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' => $ignored_issue->type ?? 'user_account', // Preserve the specific type
                    '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 user_security - ' . $description;
                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 'user_security':
                return 'high';
            default:
                return 'medium';
        }
    }
    
    /**
     * Map text severity to numeric value for database storage
     *
     * @param string $severity Severity text (critical, high, medium, low)
     * @return int Numeric severity value
     */
    private function map_severity_to_number($severity) {
        switch (strtolower($severity)) {
            case 'critical':
                return 4;
            case 'high':
                return 3;
            case 'medium':
                return 2;
            case 'low':
                return 1;
            default:
                return 2; // Default to medium
        }
    }
    
    /**
     * Get user security statistics
     *
     * @return array Statistics about user security
     */
    public function get_user_security_stats() {
        global $wpdb;
        
        $total_users = count(get_users(['fields' => 'ID']));
        $admin_users = count(get_users(['role' => 'administrator']));
        
        $table = $wpdb->prefix . 'vmpfence_scan_issues';
        $issues_count = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$table} WHERE issue_type = %s AND status != 'ignored'",  // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            'user_security'
        ));
        
        return [
            'total_users' => $total_users,
            'admin_users' => $admin_users,
            'security_issues' => (int) $issues_count,
            'security_score' => $this->calculate_user_security_score($total_users, $issues_count)
        ];
    }
    
    /**
     * Calculate user security score
     *
     * @param int $total_users Total number of users
     * @param int $issues_count Number of security issues
     * @return int Security score (0-100)
     */
    private function calculate_user_security_score($total_users, $issues_count) {
        if ($total_users === 0) {
            return 100;
        }
        
        $issue_ratio = $issues_count / $total_users;
        $score = max(0, 100 - ($issue_ratio * 50)); // Less penalty than password issues
        
        return (int) round($score);
    }
    
    /**
     * Log debug messages
     *
     * @param string $message Debug message
     */
    private function log_debug($message) {
        if ($this->debug) {
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Using error_log for debugging purposes
            // error_log("VMPFence User Security Scanner: " . $message);
        }
    }
    
    /**
     * Get scan type identifier
     *
     * @return string Scan type
     */
    public function get_scan_type() {
        return $this->scan_type;
    }
    
    /**
     * Check password strength for all users using REAL password hash cracking
     * 
     * This implements the approach as follows:
     * 1. Get user password hashes from database
     * 2. Test common weak passwords against the hashes
     * 3. Use WordPress's PasswordHash class for verification
     */
    private function check_password_strength() {
        $this->log_debug("Starting REAL password strength checking with hash cracking");
        $issues = [];
        
        // Load WordPress password hashing library
        require_once(ABSPATH . 'wp-includes/class-phpass.php');
        $password_hasher = new PasswordHash(8, true);
        
        // Get all users with elevated privileges
        $users = get_users([
            'role__in' => ['administrator', 'editor', 'author']
        ]);
        
        $this->debug_log[] = '[Password Strength] Starting password hash cracking on ' . count($users) . ' users with elevated privileges';
        
        $processed_users = 0;
        foreach ($users as $user) {
            // Performance: Throttle processing in low resource mode
            if (class_exists('VMPFence_Performance_Manager')) {
                VMPFence_Performance_Manager::throttle_processing($processed_users);
            }
            
            $this->debug_log[] = '[Password Strength] Testing password hash for user: ' . $user->user_login;
            
            // Get the user's password hash from database
            $password_hash = $user->user_pass;
            
            // Determine severity based on user role
            $user_roles = $user->roles;
            $is_admin = in_array('administrator', $user_roles);
            $severity = $is_admin ? 'critical' : 'high';
            $capability = $is_admin ? 'administrator' : (in_array('editor', $user_roles) ? 'editor' : 'author');
            
            // Test dictionary words against the password hash
            $weak_passwords_to_test = $this->get_password_dictionary($user);
            $cracked_password = null;
            
            $processed_passwords = 0;
            foreach ($weak_passwords_to_test as $test_password) {
                // Performance: Throttle dictionary attack processing
                if (class_exists('VMPFence_Performance_Manager') && $processed_passwords > 0) {
                    VMPFence_Performance_Manager::throttle_processing($processed_passwords);
                }
                
                // Use WordPress's CheckPassword method to test if hash matches
                if ($password_hasher->CheckPassword($test_password, $password_hash)) {
                    $cracked_password = $test_password;
                    break;
                }
                $processed_passwords++;
            }
            
            // If we cracked the password, create an issue
            if ($cracked_password !== null) {
                $issue = [
                    'type' => 'weak_password_cracked',
                    'severity' => $severity,
                    'title' => 'Weak Password Found (Cracked)',
                    'description' => sprintf(
                        'User "%s" with "%s" access has a weak password that was successfully cracked',
                        esc_html($user->user_login),
                        esc_html($capability)
                    ),
                    'details' => sprintf(
                        'The password for user "%s" (role: %s) was successfully cracked during dictionary attack. The weak password found was: "%s". This represents a serious security risk.',
                        esc_html($user->user_login),
                        esc_html($capability),
                        esc_html($cracked_password)
                    ),
                    'file_path' => 'WordPress Users',
                    'location' => 'User Management',
                    'user_id' => $user->ID,
                    'username' => $user->user_login,
                    'user_registered' => $user->user_registered,
                    'cracked_password' => $cracked_password,
                    'user_capability' => $capability,
                    'recommendation' => 'Change this password immediately to a strong, unique password',
                    'category' => 'Password Security (Hash Cracking)'
                ];
                
                $issues[] = $issue;
                $this->debug_log[] = '[Password Strength] CRITICAL: Successfully cracked password for user: ' . $user->user_login . ' (password: ' . $cracked_password . ')';
            } else {
                $this->debug_log[] = '[Password Strength] SECURE: Could not crack password for user: ' . $user->user_login;
            }
            
            $processed_users++;
        }
        
        $this->debug_log[] = '[Password Strength] Password cracking completed. Cracked ' . count($issues) . ' weak passwords';
        
        // Performance: Limit issues if configured
        if (class_exists('VMPFence_Performance_Manager')) {
            $issues = VMPFence_Performance_Manager::limit_issues($issues);
        }
        
        return $issues;
    }
    
    /**
     * Get password dictionary for testing
     * Returns different word sets based on user role
     */
    private function get_password_dictionary($user) {
        // Base dictionary of most common weak passwords
        $base_dictionary = [
            'password',
            'Password',
            'passwd',
            'admin',
            'administrator',
            'super',
            'superuser',
            'supervisor',
            'root',
            'manager',
            'mgr',
            '1234567890',
            '123456789',
            '12345678',
            '1234567',
            '123456',
            '12345',
            '1234',
            '123',
            'password123',
            'abc123',
            'qwerty',
            'asdf',
            'zxcv',
            'password1',
            'admin123',
            'root123',
            'test',
            'demo',
            'guest',
            'user',
            'letmein',
            'welcome',
            'welcome1',
            'changeme',
            'secret',
            'login',
            'pass',
            '000000',
            '111111',
            '222222',
            'aaaaaa',
            'wordpress',
            'wp-admin'
        ];
        
        // For admins/editors, test more passwords
        if (in_array('administrator', $user->roles) || in_array('editor', $user->roles)) {
            // Add username-based passwords
            $username_variants = [
                $user->user_login,
                $user->user_login . '123',
                $user->user_login . '1',
                $user->user_login . '!',
                $user->display_name
            ];
            
            return array_merge($base_dictionary, $username_variants);
        } else {
            // For other users, just test the username
            return [$user->user_login];
        }
    }
    
    /**
     * DEPRECATED: This method has been replaced with real password hash cracking
     * Left here for reference but no longer used
     */
    private function check_weak_password_indicators($user) {
        $indicators = [];
        
        // Check if username suggests weak password
        $username = strtolower($user->user_login);
        $common_weak_usernames = ['admin', 'administrator', 'root', 'test', 'demo', 'user'];
        
        if (in_array($username, $common_weak_usernames)) {
            $indicators[] = 'Common administrative username (often paired with weak passwords)';
        }
        
        // Check user creation date (new users might have default passwords)
        $registration_date = strtotime($user->user_registered);
        $days_since_registration = (time() - $registration_date) / (24 * 60 * 60);
        
        if ($days_since_registration < 7) {
            $indicators[] = 'Recently created account (may still have default/temporary password)';
        }
        
        // Check if display name equals username (might indicate default setup)
        if (strtolower($user->display_name) === strtolower($user->user_login)) {
            $indicators[] = 'Display name same as username (suggests minimal security setup)';
        }
        
        // Check email pattern for generic emails
        $email_domain = substr(strchr($user->user_email, '@'), 1);
        $generic_domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', 'test.com', 'example.com'];
        
        if (in_array($email_domain, $generic_domains) && in_array($username, $common_weak_usernames)) {
            $indicators[] = 'Generic email domain with common username (security risk pattern)';
        }
        
        return $indicators;
    }

    /**
     * FUTURE IMPLEMENTATION: Password strength check simulation
     * 
     * This method is prepared for future password strength implementation
     * when password cracking capabilities are added to the plugin.
     *
     * @param string $password Plain text password to check
     * @return array Password analysis results
     */
    public function analyze_password_strength($password) {
        $score = 0;
        $issues = [];
        $suggestions = [];
        
        // Length check
        if (strlen($password) < 8) {
            $issues[] = 'Password is too short (minimum 8 characters)';
        } elseif (strlen($password) < $this->minimum_secure_length) {
            $issues[] = 'Password should be at least ' . $this->minimum_secure_length . ' characters';
        } else {
            $score += 20;
        }
        
        // Character variety
        if (preg_match('/[a-z]/', $password)) $score += 10;
        else $suggestions[] = 'Add lowercase letters';
        
        if (preg_match('/[A-Z]/', $password)) $score += 10;
        else $suggestions[] = 'Add uppercase letters';
        
        if (preg_match('/[0-9]/', $password)) $score += 10;
        else $suggestions[] = 'Add numbers';
        
        if (preg_match('/[^a-zA-Z0-9]/', $password)) $score += 20;
        else $suggestions[] = 'Add special characters';
        
        // Common password check
        if (in_array(strtolower($password), array_map('strtolower', $this->common_weak_passwords))) {
            $score = 0;
            $issues[] = 'This is a commonly used weak password';
        }
        
        // Dictionary word check
        foreach ($this->dictionary_words as $word) {
            if (stripos($password, $word) !== false) {
                $score -= 15;
                $issues[] = "Contains dictionary word: {$word}";
                break;
            }
        }
        
        $score = max(0, min(100, $score));
        
        if ($score >= 80) $strength = 'Strong';
        elseif ($score >= 60) $strength = 'Good';
        elseif ($score >= 40) $strength = 'Fair';
        else $strength = 'Weak';
        
        return [
            'score' => $score,
            'strength' => $strength,
            'issues' => $issues,
            'suggestions' => $suggestions,
            'note' => 'This is a simulation - actual password strength scanning requires password hash cracking capabilities'
        ];
    }
    
    /**
     * FUTURE IMPLEMENTATION: Real password strength scanning
     * 
     * This method is a placeholder for future implementation of actual
     * 
     *
     * @return array Results of password strength scan
     */
    public function scan_password_strength() {
        // TODO: Implement actual password cracking methodology
        // This would require:
        // 1. Extract password hashes from WordPress database
        // 2. Apply dictionary attacks with common passwords
        // 3. Use pattern-based guessing algorithms
        // 4. Attempt computational brute force on weak passwords
        // 5. Compare against known breach databases
        // 6. Report crackable passwords with severity levels
        
        return [
            'implemented' => false,
            'message' => 'Real password strength scanning requires additional implementation',
            'requirements' => [
                'Password hash extraction capabilities',
                'Dictionary attack algorithms',
                'Computational brute force tools',
                'Breach database integration',
                'Significant processing resources'
            ],
            'note' => 'Current implementation focuses on username and account security analysis'
        ];
    }
    
    /**
     * Initialize admin monitoring system
     * Creates initial baseline of admin users when first run
     */
    private function initialize_admin_monitoring() {
        // Check if we already have a baseline admin list
        $logged_admins = $this->get_logged_admins();
        if (empty($logged_admins)) {
            // Create initial baseline - all current admins are "legitimate"
            $this->create_initial_admin_list();
            $this->debug_log[] = '[User Security] Created initial admin baseline for suspicious user detection';
        }
    }
    
    /**
     * Create initial admin list baseline
     * All current admins are considered "legitimate" and added to baseline
     */
    public function create_initial_admin_list() {
        $current_admins = $this->get_current_admins();
        $admin_baseline = array();
        
        foreach ($current_admins as $user_id => $user) {
            $admin_baseline[$user_id] = 1;
        }
        
        // Store baseline in WordPress options 
        update_option('vmpfence_admin_user_baseline', $admin_baseline, false);
        
        $this->debug_log[] = '[User Security] Stored ' . count($admin_baseline) . ' admin users in baseline';
    }
    
    /**
     * Get current admin users
     * Handles both single site and multisite configurations
     * 
     * @param bool $force_reload Force reload from database
     * @return array Array of WP_User objects keyed by user ID
     */
    public function get_current_admins($force_reload = false) {
        if (empty($this->current_admin_list) || $force_reload) {
            require_once(ABSPATH . WPINC . '/user.php');
            
            $this->current_admin_list = array();
            
            if (is_multisite()) {
                // Handle multisite - get admins from all sites
                // Get all sites in the network (WordPress 4.6.0+)
                $sites = get_sites(array('network_id' => null));
                
                // Get admins from each site
                foreach ($sites as $site_row) {
                    $site_row_array = (array) $site_row;
                    $user_query = new WP_User_Query(array(
                        'blog_id' => $site_row_array['blog_id'],
                        'role' => 'administrator',
                    ));
                    $users = $user_query->get_results();
                    
                    if (is_array($users)) {
                        foreach ($users as $user) {
                            $this->current_admin_list[$user->ID] = $user;
                        }
                    }
                }
                
                // Add super admins who might not be site admins
                $super_admins = get_super_admins();
                foreach ($super_admins as $user_login) {
                    $user = get_user_by('login', $user_login);
                    if ($user) {
                        $this->current_admin_list[$user->ID] = $user;
                    }
                }
            } else {
                // Single site - get administrators
                $user_query = new WP_User_Query(array(
                    'role' => 'administrator',
                ));
                $users = $user_query->get_results();
                
                if (is_array($users)) {
                    foreach ($users as $user) {
                        $this->current_admin_list[$user->ID] = $user;
                    }
                }
            }
        }
        
        return $this->current_admin_list;
    }
    
    /**
     * Get logged admins baseline
     * Returns the baseline admin list created during initial scan
     * 
     * @return array Array of user IDs in baseline
     */
    public function get_logged_admins() {
        $logged_admins = get_option('vmpfence_admin_user_baseline', false);
        if (!is_array($logged_admins)) {
            $logged_admins = array();
        }
        return $logged_admins;
    }
    
    /**
     * Check for new admin users created outside WordPress
     * Compares current admins against baseline to detect suspicious additions
     * 
     * @return array Array of user IDs for admins created outside WordPress
     */
    public function check_new_admins() {
        $logged_admins = $this->get_logged_admins();
        $current_admins = $this->get_current_admins();
        $suspicious_admins = array();
        
        foreach ($current_admins as $admin_id => $admin_user) {
            // If admin is NOT in baseline, they were "created outside WordPress"
            if (!array_key_exists($admin_id, $logged_admins)) {
                $suspicious_admins[] = $admin_id;
            }
        }
        
        return empty($suspicious_admins) ? false : $suspicious_admins;
    }
    
    /**
     * Main suspicious admin users detection
     * Combines baseline comparison with pattern matching
     * 
     * @return array Array of security issues found
     */
    public function check_suspicious_admin_users() {
        $issues = array();
        
        // 1. Check for admins created outside WordPress (baseline comparison)
        $suspicious_new_admins = $this->check_new_admins();
        if (is_array($suspicious_new_admins)) {
            foreach ($suspicious_new_admins as $user_id) {
                $user = new WP_User($user_id);
                
                $issues[] = array(
                    'type' => 'suspicious_admin_outside_wp',
                    'severity' => 'high',
                    'title' => 'Admin Created Outside WordPress',
                    'description' => sprintf(
                        'An admin user with the username %s was created outside of WordPress.',
                        esc_html($user->user_login)
                    ),
                    'details' => sprintf(
                        'An admin user with the username %s was created outside of WordPress. It\'s possible a plugin could have created the account, but if you do not recognize the user, we suggest you remove it.',
                        esc_html($user->user_login)
                    ),
                    'file_path' => 'WordPress Users',
                    'location' => 'User Management',
                    'user_id' => $user_id,
                    'username' => $user->user_login,
                    'user_registered' => $user->user_registered,
                    'created_via' => 'Outside WordPress (not in baseline)'
                );
                
                $this->debug_log[] = '[User Security] CRITICAL: Admin created outside WordPress - ' . $user->user_login;
            }
        }
        
        // 2. Check current admins against suspicious username patterns
        $current_admins = $this->get_current_admins();
        foreach ($current_admins as $user_id => $admin_user) {
            // Check against suspicious admin username patterns
            foreach ($this->suspicious_admin_patterns as $pattern) {
                if (preg_match($pattern, $admin_user->user_login)) {
                    $issues[] = array(
                        'type' => 'suspicious_admin_username',
                        'severity' => 'high',
                        'title' => 'Suspicious Admin Username',
                        'description' => sprintf(
                            'An admin user with a suspicious username %s was found.',
                            esc_html($admin_user->user_login)
                        ),
                        'details' => sprintf(
                            'An admin user with a suspicious username %s was found. Administrator accounts with usernames similar to this are commonly seen created by hackers. It\'s possible a plugin could have created the account, but if you do not recognize the user, we suggest you remove it.',
                            esc_html($admin_user->user_login)
                        ),
                        'file_path' => 'WordPress Users',
                        'location' => 'User Management',
                        'user_id' => $user_id,
                        'username' => $admin_user->user_login,
                        'user_registered' => $admin_user->user_registered,
                        'pattern_matched' => $pattern
                    );
                    
                    $this->debug_log[] = '[User Security] WARNING: Suspicious admin username pattern - ' . $admin_user->user_login;
                    break; // Only report once per user
                }
            }
        }
        
        return $issues;
    }
    
    /**
     * Add admin to baseline (when legitimately created through WordPress)
     * 
     * 
     * @param int $user_id User ID to add to baseline
     */
    public function add_admin_to_baseline($user_id) {
        $logged_admins = $this->get_logged_admins();
        if (!array_key_exists($user_id, $logged_admins)) {
            $logged_admins[$user_id] = 1;
            update_option('vmpfence_admin_user_baseline', $logged_admins, false);
        }
    }
    
    /**
     * Remove admin from baseline (when admin is deleted)
     * 
     * 
     * @param int $user_id User ID to remove from baseline
     */
    public function remove_admin_from_baseline($user_id) {
        $logged_admins = $this->get_logged_admins();
        $current_admins = $this->get_current_admins();
        
        // Only remove if user is in baseline AND not currently an admin
        if (array_key_exists($user_id, $logged_admins) && !array_key_exists($user_id, $current_admins)) {
            unset($logged_admins[$user_id]);
            update_option('vmpfence_admin_user_baseline', $logged_admins, false);
        }
    }
}
