<?php
/**
 * Brute Force Additional Option Controller
 *
 * @package VMPFence
 * @since 2.0.0
 * @since 2.2.1 Updated text-domain to vmpfence-security
 * @since 2.2.6 Added password strength checking on profile updates with email alerts to admins
 */

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

/**
 * VMPFence Brute Force Additional Option Controller
 * 
 * Handles WordPress authentication integration
 * Hooks into WordPress login system to detect and prevent login security issues
 */
class VMPFence_Brute_Force_Additional_Option_Controller {

    /**
     * Brute Force Model instance
     *
     * @var VMPFence_Brute_Force_Model
     */
    private $model;

    /**
     * Constructor
     */
    public function __construct() {
        $this->model = new VMPFence_Brute_Force_Model();
        $this->init_hooks();
    }

    /**
     * Initialize WordPress hooks
     */
    private function init_hooks() {
        
        // Hook into WordPress authentication system
        add_filter('authenticate', array($this, 'mask_login_errors'), 99,3);

        // For public registration (wp-login.php?action=register)
        add_filter('registration_errors', array($this, 'prevent_admin_username_registration'), 10, 3);

        // For admin "Add User" functionality 
        add_action('user_profile_update_errors', array($this, 'prevent_admin_username_admin'), 10, 3);

        // Username discovery prevention hooks
        add_action('init', array($this, 'disable_username_discovery'), 1);
        
        // Application passwords control
        add_action('init', array($this, 'disable_app_passwords'), 1);
        
        // Block bad POST requests (blank User-Agent and Referer)
        add_action('init', array($this, 'block_bad_post_requests'), -1);
        
        // Password strength checking on profile updates
        if (is_admin()) {
            add_action('profile_update', array($this, 'check_password_strength_on_update'), 99, 2);
        }
    }
    
    /**
     * Mask login errors to prevent username enumeration
     * Hooks into authenticate filter with priority 99
     *
     * @param null|WP_User|WP_Error|null $user WP_User or WP_Error object from previous callbacks
     * @param string                $username Username for authentication
     * @param string                $password Password for authentication
     * @return WP_User|WP_Error WP_User on success, WP_Error with masked message on failure
     */
    public function mask_login_errors($user, $username, $password) {
        // Skip if don't_reveal_users is disabled
        if (!VMPFence_Config::get('dont_reveal_users', 1)) {
            return $user;
        }

        // Only mask specific error codes that reveal username information
        if (is_wp_error($user)) {
            $error_code = $user->get_error_code();
        
            // Check if this is a username enumeration error
            if (in_array($error_code, array('invalid_username', 'invalid_email', 'incorrect_password', 'authentication_failed'))) {
                // Return standardized error message that doesn't reveal if username exists
                return new WP_Error(
                    'incorrect_password',
                    sprintf(
                        /* translators: 1. WordPress username. 2. Password reset URL. */
                        wp_kses(
                            __('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%2$s" title="Password Lost and Found">Lost your password</a>?', 'vmpfence-security'),
                            array('strong' => array(), 'a' => array('href' => array(), 'title' => array()))
                        ),
                        $username,
                        wp_lostpassword_url()
                    )
                );
            }
        }

        return $user;
    }

    /**
     * Prevent registration of 'admin' username if it doesn't already exist
     *
     * @param WP_Error $errors Registration errors object
     * @param string $sanitized_user_login Sanitized username
     * @param string $user_email User email
     * @return WP_Error Modified errors object
     */
    public function prevent_admin_username_registration($errors, $sanitized_user_login, $user_email) {
        // Skip if prevent_admin_username is disabled
        if (!VMPFence_Config::get('prevent_admin_username', 1)) {
            return $errors;
        }
    
        // Check if someone is trying to register as 'admin'
        if (strtolower($sanitized_user_login) === 'admin') {
            // Check if 'admin' user already exists
            if (!username_exists('admin')) {
                // Block registration - admin username doesn't exist and shouldn't be created
                $errors->add(
                    'username_admin_blocked',
                    __('<strong>ERROR</strong>: The username "admin" is not available for registration.', 'vmpfence-security')
                );
            }
            // If admin user already exists, let WordPress handle the "username already exists" error
        }
    
        return $errors;
    }

    /**
    * Prevent admin username creation in WordPress admin "Add User"
    *
    * @param WP_Error $errors Error object
    * @param bool $update Whether this is a user update
    * @param object $user User data object
    */
    public function prevent_admin_username_admin($errors, $update, $user) {
        // Only check for new users (not updates)
        if ($update) {
            return;
        }
    
        // Skip if prevent_admin_username is disabled
        if (!VMPFence_Config::get('prevent_admin_username', 1)) {
            return;
        }
        
        // Get username from POST data
        $username = isset($_POST['user_login']) ? sanitize_user($_POST['user_login']) : '';
        
        // Check if someone is trying to create 'admin' user
        if (strtolower($username) === 'admin') {
            if (!username_exists('admin')) {
                $errors->add(
                    'username_admin_blocked',
                    __('<strong>ERROR</strong>: The username "admin" is not available for registration.', 'vmpfence-security')
                );
            }
        }
    }

    /**
     * Main username discovery prevention method
     * Called on 'init' hook with priority 1
     */
    public function disable_username_discovery() {
        // Skip if prevent_username_discovery is disabled
        if (!VMPFence_Config::get('prevent_username_discovery', 1)) {
            return;
        }

        // Skip in admin area
        if (is_admin()) {
            return;
        }

        // Apply all username discovery prevention measures
        $this->prevent_author_scanning();
        $this->prevent_rest_api_users();
        $this->prevent_oembed_author_leak();
        $this->prevent_xml_sitemap_users();
    }

    /**
     * Prevent author scanning via ?author=N URLs
     */
    private function prevent_author_scanning() {
        add_action('parse_request', array($this, 'block_author_scanning'), 20);
    }

    /**
     * Block author scanning requests
     *
     * @param WP $wp WordPress environment object
     */
    public function block_author_scanning($wp) {
        // Skip in admin area
        if (is_admin()) {
            return;
        }

        // Check for author query parameter (numeric ID)
        if (isset($wp->query_vars['author']) && 
            !empty($wp->query_vars['author']) && 
            is_numeric($wp->query_vars['author'])) {
            
            // Block with 403 Forbidden
            status_header(403);
            wp_die(__('Forbidden', 'vmpfence-security'), 'Forbidden', array('response' => 403));
        }

        // Check for author_name query (pretty permalinks)
        if (isset($wp->query_vars['author_name']) && 
            !empty($wp->query_vars['author_name'])) {
            
            // Block with 403 Forbidden
            status_header(403);
            wp_die(__('Forbidden', 'vmpfence-security'), 'Forbidden', array('response' => 403));
        }
    }

    /**
     * Prevent WordPress REST API users endpoint access
     */
    private function prevent_rest_api_users() {
        add_filter('rest_authentication_errors', array($this, 'block_rest_users_endpoint'), 20);
    }

    /**
     * Block REST API users endpoint
     *
     * @param WP_Error|null|bool $result Current authentication result
     * @return WP_Error|null|bool Modified result
     */
    public function block_rest_users_endpoint($result) {
        // Return existing error if already set
        if (is_wp_error($result)) {
            return $result;
        }

        // Get current REST route
        $route = '';
        if (isset($GLOBALS['wp']->query_vars['rest_route'])) {
            $route = $GLOBALS['wp']->query_vars['rest_route'];
        }

        // Block users endpoint access
        if (preg_match('#^/wp/v\d+/users(?:/.*)?$#', $route)) {
            
            return new WP_Error(
                'rest_cannot_access',
                __('Sorry, you are not allowed to access this endpoint.', 'vmpfence-security'),
                array('status' => 401)
            );
        }

        return $result;
    }

    /**
     * Prevent author information leaks in oEmbed responses
     */
    private function prevent_oembed_author_leak() {
        add_filter('oembed_response_data', array($this, 'remove_author_from_oembed'), 20, 2);
    }

    /**
     * Remove author information from oEmbed responses
     *
     * @param array $data oEmbed response data
     * @param WP_Post $post Post object
     * @return array Modified oEmbed data
     */
    public function remove_author_from_oembed($data, $post) {
        // Remove author information from oEmbed response
        if (isset($data['author_name'])) {
            unset($data['author_name']);
        }
        
        if (isset($data['author_url'])) {
            unset($data['author_url']);
        }

        return $data;
    }

    /**
     * Prevent users from appearing in WordPress XML sitemaps
     */
    private function prevent_xml_sitemap_users() {
        add_action('wp_sitemaps_add_provider', array($this, 'disable_sitemap_users'), 20, 2);
        
        // Alternative approach - hook when sitemaps are being generated
        add_action('template_redirect', array($this, 'remove_users_sitemap_on_request'), 1);
    }

    /**
     * Remove users sitemap provider
     *
     * @param WP_Sitemaps_Provider $provider Sitemap provider object
     * @param string $name Provider name
     */
    public function disable_sitemap_users($provider, $name) {
        if ($name === 'users') {
            // Remove users sitemap provider
            if (function_exists('wp_sitemaps') && wp_sitemaps()->registry) {
                wp_sitemaps()->registry->remove_provider('users');
            }
        }
    }
    
    /**
     * Remove users sitemap when template_redirect fires (during sitemap requests)
     */
    public function remove_users_sitemap_on_request() {
        // Only process on sitemap requests
        if (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], 'wp-sitemap') !== false) {
            // Check if this is a users sitemap request and block it directly
            if (strpos($_SERVER['REQUEST_URI'], 'wp-sitemap-users') !== false) {
                status_header(404);
                wp_die(__('Not Found', 'vmpfence-security'), 'Not Found', array('response' => 404));
                return;
            }
            
            // For main sitemap, try to modify the providers
            global $wp_sitemaps;
            
            if ($wp_sitemaps && isset($wp_sitemaps->registry) && isset($wp_sitemaps->registry->providers)) {
                // Remove users provider from the registry
                if (isset($wp_sitemaps->registry->providers['users'])) {
                    unset($wp_sitemaps->registry->providers['users']);
                }
            }
        }
    }

    /**
     * Disable WordPress Application Passwords
     * Called on 'init' hook with priority 1
     */
    public function disable_app_passwords() {
        // Skip if disable_app_passwords is not enabled
        if (!VMPFence_Config::get('disable_app_passwords', 1)) {
            return;
        }

        // Globally disable application passwords
        add_filter('wp_is_application_passwords_available', '__return_false');
        
        // Add user profile messages
        add_action('edit_user_profile', array($this, 'show_disabled_app_passwords_message'), -1);
        add_action('show_user_profile', array($this, 'show_disabled_app_passwords_message'), -1);
        
        // Override authorization page messages
        $this->override_app_password_authorization();
    }

    /**
     * Show message on user profile pages that application passwords are disabled
     */
    public function show_disabled_app_passwords_message() {
        $is_admin = current_user_can('manage_options');
        
        echo '<h2>' . esc_html__('Application Passwords', 'vmpfence-security') . '</h2>';
        echo '<table class="form-table" role="presentation">';
        echo '<tr>';
        echo '<th>' . esc_html__('Status', 'vmpfence-security') . '</th>';
        echo '<td>';
        echo '<p>' . esc_html__('Application passwords have been disabled by VMPFence for enhanced security.', 'vmpfence-security') . '</p>';
        
        if (!$is_admin) {
            echo '<p>' . esc_html__('The site administrator can change this security setting.', 'vmpfence-security') . '</p>';
        } else {
            $options_url = admin_url('admin.php?page=vmpfence-firewall&view=options');
            echo '<p><a href="' . esc_url($options_url) . '" class="button">' . 
                 esc_html__('Manage VMPFence Security Settings', 'vmpfence-security') . '</a></p>';
        }
        
        echo '</td>';
        echo '</tr>';
        echo '</table>';
    }

    /**
     * Override authorization page error messages for application passwords
     */
    private function override_app_password_authorization() {
        // Only override on the authorization page
        if (!empty($_SERVER['SCRIPT_FILENAME']) && 
            $_SERVER['SCRIPT_FILENAME'] === ABSPATH . 'wp-admin/authorize-application.php') {
            
            add_filter('wp_die_handler', array($this, 'custom_app_password_die_handler'), 10, 1);
        }
    }

    /**
     * Custom wp_die handler for application password authorization attempts
     *
     * @param callable|null $handler Current die handler
     * @return callable Custom die handler
     */
    public function custom_app_password_die_handler($handler = null) {
        return function($message, $title, $args) {
            // Replace the default WordPress message with our custom one
            if ($message === 'Application passwords are not available.') {
                $message = esc_html__('Application passwords have been disabled by VMPFence for enhanced security.', 'vmpfence-security');
                $title = esc_html__('Application Passwords Disabled', 'vmpfence-security');
            }
            
            // Use the default WordPress die handler with our custom message
            _default_wp_die_handler($message, $title, $args);
        };
    }

    /**
     * Block POST requests with blank User-Agent and Referer headers
     * Called on 'init' hook with priority -1 (very early)
     */
    public function block_bad_post_requests() {
        // Skip if feature is disabled
        if (!VMPFence_Config::get('block_post_requests', 0)) {
            return;
        }

        // Skip for CLI and WP-CLI requests (ISSUE-005 fix)
        if (PHP_SAPI === 'cli' || (defined('WP_CLI') && WP_CLI)) {
            return;
        }

        // Skip if not a POST request
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
            return;
        }

        // Skip in admin area for safety
        if (is_admin()) {
            return;
        }

        // Check if BOTH User-Agent AND Referer are missing/empty
        if (empty($_SERVER['HTTP_USER_AGENT']) && empty($_SERVER['HTTP_REFERER'])) {
            $ip = $this->get_real_ip();
            $reason = __('POST request with blank User-Agent and Referer headers', 'vmpfence-security');
            
            // Block the IP address permanently
            $this->create_ip_block($ip, $reason);
            
            // Get custom block text
            $custom_text = $this->get_custom_block_text();
            
            // Return 403 Forbidden with custom block page
            status_header(403);
            
            // Create a simple block page with custom text support
            $this->show_block_page($reason, $ip, $custom_text);
        }
    }

    /**
     * Get custom block text with proper formatting
     * 
     * @return string Formatted custom text or empty string
     */
    private function get_custom_block_text() {
        $text = VMPFence_Config::get('custom_block_text', '');
        
        if (empty($text)) {
            return '';
        }
        
        // Apply processing: strip HTML and auto-paragraph
        return wpautop(wp_strip_all_tags($text));
    }

    /**
     * Show block page for bad POST requests
     * 
     * @param string $reason Block reason
     * @param string $ip IP address
     * @param string $custom_text Custom block text
     */
    private function show_block_page($reason, $ip, $custom_text) {
        // Prepare data for the WAF block template
        $violations = array(
            array(
                'category' => 'Security',
                'description' => $reason,
                'score' => 100
            )
        );
        
        // Set template variables (same as bootstrap uses)
        // $request_id = uniqid('post_');
        $total_score = 100;
        $block_type = 'bad_post'; // Indicates bad POST block type
        
        // Load the existing WAF block template
        include VMPFENCE_PLUGIN_DIR . '/firewall/views/waf-403-blocked.php';
        exit;
    }

    /**
     * Get the real IP address (helper method)
     * 
     * @return string IP address
     */
    private function get_real_ip() {
        // Check for various proxy headers
        $ip_keys = array(
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_REAL_IP',
            'HTTP_CF_CONNECTING_IP',
            'HTTP_CLIENT_IP',
            'REMOTE_ADDR'
        );
        
        foreach ($ip_keys as $key) {
            if (isset($_SERVER[$key]) && !empty($_SERVER[$key])) {
                $ip = $_SERVER[$key];
                // Handle comma-separated IPs (from proxies)
                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }
                // Validate IP
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
        
        // Fallback to REMOTE_ADDR
        return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    }

    /**
     * Create IP block for bad POST requests
     * 
     * @param string $ip IP address to block
     * @param string $reason Reason for blocking
     */
    private function create_ip_block($ip, $reason) {
        // Log to security attempts table with proper event type using model
        $this->model->log_security_event($ip, 'bad_post_headers', $reason);
        
        // Use the brute force model's existing apply_lockout method (60 minutes = 1 hour)
        $this->model->apply_lockout($ip, 60, false, $reason); // 1 hour block
    }

    /**
     * Check password strength on profile update
     * 
     * @param int $user_id User ID
     * @param WP_User $old_user_data User data before update
     */
    public function check_password_strength_on_update($user_id, $old_user_data) {
        // Skip if feature is disabled
        if (!VMPFence_Config::get('check_password_strength', 1)) {
            return;
        }

        // Get new user data
        $new_user_data = get_userdata($user_id);
        if (!$new_user_data) {
            return;
        }

        // Check if password was actually changed
        if ($new_user_data->user_pass === $old_user_data->user_pass) {
            return; // Password not changed
        }

        // Analyze password strength
        $weakness_found = $this->analyze_password_strength($user_id, $new_user_data);
        
        // Send email alert if weak password detected
        if ($weakness_found) {
            $this->send_weak_password_alert($user_id, $new_user_data, $weakness_found);
        }
    }

    /**
     * Analyze password strength using WordPress's built-in password strength meter
     * 
     * @param int $user_id User ID
     * @param WP_User $user_data User data
     * @return array|false Weakness details or false if strong
     */
    private function analyze_password_strength($user_id, $user_data) {
        // Skip if we can't get the plain password (only works during password change)
        if (!isset($_POST['pass1']) || empty($_POST['pass1'])) {
            return false; // No plain password available for testing
        }
        
        $password = $_POST['pass1'];
        $username = $user_data->user_login;
        $email = $user_data->user_email;
        
        // Build user input list for password strength testing (like WordPress does)
        $user_inputs = array();
        $user_inputs[] = $username;
        $user_inputs[] = $email;
        
        if (!empty($user_data->first_name)) {
            $user_inputs[] = $user_data->first_name;
        }
        if (!empty($user_data->last_name)) {
            $user_inputs[] = $user_data->last_name;
        }
        if (!empty($user_data->display_name)) {
            $user_inputs[] = $user_data->display_name;
        }
        
        // Add site-specific inputs
        $user_inputs[] = get_bloginfo('name');
        $user_inputs[] = str_replace(array('http://', 'https://', 'www.'), '', home_url());
        
        // Use WordPress's password strength function (same as "Enforce Strong Passwords")
        if (!function_exists('wp_password_strength_meter')) {
            // Load WordPress password strength functionality
            wp_enqueue_script('password-strength-meter');
        }
        
        // Calculate password strength using the same method as WordPress
        $strength = $this->calculate_password_strength($password, $user_inputs);
        // Determine if password is weak based on WordPress standards
        $is_privileged_user = $this->is_privileged_user($user_data);
        
        // WordPress strength levels: 0 = very weak, 1 = weak, 2 = medium, 3 = strong
        $min_strength_required = $is_privileged_user ? 2 : 1; // Higher standard for privileged users
        
        if ($strength < $min_strength_required) {
            $strength_labels = array(
                0 => 'Very Weak',
                1 => 'Weak', 
                2 => 'Medium',
                3 => 'Strong'
            );
            
            return array(
                'strength_score' => $strength,
                'strength_label' => $strength_labels[$strength],
                'min_required' => $min_strength_required,
                'user_login' => $user_data->user_login,
                'user_email' => $user_data->user_email,
                'is_privileged' => $is_privileged_user,
                'severity' => $is_privileged_user ? 'critical' : 'high',
                'reason' => sprintf(
                    'Password strength is %s (score: %d), but %s users require minimum %s (score: %d)',
                    $strength_labels[$strength],
                    $strength,
                    $is_privileged_user ? 'privileged' : 'standard',
                    $strength_labels[$min_strength_required],
                    $min_strength_required
                )
            );
        }
        
        return false; // Password is strong enough
    }

    /**
     * Calculate password strength using WordPress's algorithm
     * This mimics the same calculation used by wp_password_strength_meter
     * 
     * @param string $password The password to test
     * @param array $user_inputs Array of user-related inputs to check against
     * @return int Strength score (0-3)
     */
    private function calculate_password_strength($password, $user_inputs = array()) {
        // Basic length check
        if (strlen($password) < 4) {
            return 0; // Very weak
        }
        
        if (strlen($password) < 6) {
            return 1; // Weak
        }
        
        // Check against user inputs (username, email, etc.)
        foreach ($user_inputs as $input) {
            if (!empty($input) && stripos($password, $input) !== false) {
                return 0; // Very weak - contains user data
            }
        }
        
        // Character diversity checks
        $score = 0;
        
        // Length bonus
        if (strlen($password) >= 8) $score++;
        if (strlen($password) >= 12) $score++;
        
        // Character type checks
        if (preg_match('/[a-z]/', $password)) $score++; // lowercase
        if (preg_match('/[A-Z]/', $password)) $score++; // uppercase  
        if (preg_match('/[0-9]/', $password)) $score++; // numbers
        if (preg_match('/[^a-zA-Z0-9]/', $password)) $score++; // symbols
        
        // Common pattern penalties
        if (preg_match('/(.)\1{2,}/', $password)) $score--; // Repeated characters
        if (preg_match('/123|abc|qwe|asd/i', $password)) $score--; // Common sequences
        
        // Check against most common passwords
        $very_common = array(
            'password', 'password1', '123456', 'qwerty', 'admin', 'login',
            'welcome', 'monkey', 'dragon', 'master', 'shadow', 'superman'
        );
        
        if (in_array(strtolower($password), $very_common)) {
            return 0; // Very weak
        }
        
        // Normalize score to 0-3 range
        if ($score <= 2) return 0; // Very weak
        if ($score <= 4) return 1; // Weak
        if ($score <= 6) return 2; // Medium
        return 3; // Strong
    }

    /**
     * Determine if user has privileged access
     * 
     * @param WP_User $user_data User data
     * @return bool True if user has elevated privileges
     */
    private function is_privileged_user($user_data) {
        // Check for editor-level capabilities
        $privileged_caps = array(
            'edit_posts',
            'publish_posts', 
            'edit_pages',
            'publish_pages',
            'edit_others_posts',
            'edit_others_pages',
            'manage_options',
            'install_plugins',
            'activate_plugins'
        );

        foreach ($privileged_caps as $cap) {
            if (user_can($user_data->ID, $cap)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Send email alert for weak password detection
     * 
     * @param int $user_id User ID
     * @param WP_User $user_data User data
     * @param array $weakness_details Details about the weakness
     */
    private function send_weak_password_alert($user_id, $user_data, $weakness_details) {
        // Get admin email addresses
        $admin_emails = $this->get_admin_emails();
        if (empty($admin_emails)) {
            return; // No admin emails to send to
        }

        $strength_labels = array(0 => 'Very Weak', 1 => 'Weak', 2 => 'Medium', 3 => 'Strong');
        $user_role = $this->get_highest_user_role($user_data);

        // Build human-readable messages for the template
        if ($weakness_details['is_privileged']) {
            $severity_text = 'CRITICAL';
            $short_message = sprintf(
                'User "%s" with "%s" access has a %s password.',
                $user_data->user_login,
                $user_role,
                strtolower($weakness_details['strength_label'])
            );
            $long_message = sprintf(
                "A user with the role of '%s' has set a password with %s strength. %s",
                $user_role,
                strtolower($weakness_details['strength_label']),
                $weakness_details['reason']
            );
        } else {
            $severity_text = 'HIGH';
            $short_message = sprintf(
                'User "%s" has set a %s password.',
                $user_data->user_login,
                strtolower($weakness_details['strength_label'])
            );
            $long_message = sprintf(
                "A user has set a password with %s strength. %s",
                strtolower($weakness_details['strength_label']),
                $weakness_details['reason']
            );
        }

        // Send via centralized Email Service (API → branded template)
        $context = array(
            'severity'           => $severity_text,
            'short_message'      => $short_message,
            'long_message'       => $long_message,
            'username'           => $user_data->user_login,
            'user_email'         => $user_data->user_email,
            'display_name'       => $user_data->display_name,
            'user_role'          => $user_role,
            'is_privileged'      => $weakness_details['is_privileged'],
            'strength_score'     => $weakness_details['strength_score'],
            'strength_label'     => $weakness_details['strength_label'],
            'min_required'       => $weakness_details['min_required'],
            'min_required_label' => isset($strength_labels[$weakness_details['min_required']]) ? $strength_labels[$weakness_details['min_required']] : 'Medium',
            'reason'             => $weakness_details['reason'],
            'edit_user_url'      => admin_url('user-edit.php?user_id=' . $user_id),
            'sent_at'            => current_time('Y-m-d H:i:s'),
        );

        $result = VMPFence_Email_Service::send_alert('weak_password_alert', $context, $admin_emails);
        $emails_sent = $result['success'] ? count($admin_emails) : 0;
        $email_errors = $result['success'] ? array() : $admin_emails;
        
        // DIRECT AUDIT LOG: Intentionally bypasses observer system.
        // Reason: Fires after wp_mail during weak password check, unique context.
        if ($emails_sent > 0) {
            VMPFence_Audit_Log::log_event('weak_password_detected', array(
                'action' => 'email_sent',
                'message' => sprintf(
                    'Weak password alert sent for user "%s" (strength: %s, score: %d/3) to %d administrator(s)',
                    $user_data->user_login,
                    $weakness_details['strength_label'],
                    $weakness_details['strength_score'],
                    $emails_sent
                ),
                'target_user_id' => $user_id,
                'target_username' => $user_data->user_login,
                'target_user_role' => $this->get_highest_user_role($user_data),
                'password_strength_score' => $weakness_details['strength_score'],
                'password_strength_label' => $weakness_details['strength_label'],
                'min_required_score' => $weakness_details['min_required'],
                'is_privileged_user' => $weakness_details['is_privileged'],
                'severity' => $weakness_details['severity'],
                'admin_emails_sent' => $emails_sent,
                'admin_emails_failed' => count($email_errors),
                'email_recipients' => array_diff($admin_emails, $email_errors), // Successfully sent emails
                'email_failures' => $email_errors, // Failed email addresses
                'alert_reason' => $weakness_details['reason']
            ));
        }
        
        // Log the alert to error log as well
        // if ($emails_sent > 0) {
        //     error_log(sprintf(
        //         'VMPFence: Weak password alert sent - User: %s, Strength: %s (%d/3), Admins notified: %d, Failed: %d',
        //         $user_data->user_login,
        //         $weakness_details['strength_label'],
        //         $weakness_details['strength_score'],
        //         $emails_sent,
        //         count($email_errors)
        //     ));
        // } else {
        //     error_log(sprintf(
        //         'VMPFence: Failed to send weak password alert - User: %s, Strength: %s (%d/3), All %d email attempts failed',
        //         $user_data->user_login,
        //         $weakness_details['strength_label'],
        //         $weakness_details['strength_score'],
        //         count($admin_emails)
        //     ));
        // }
    }

    /**
     * Get administrator email addresses
     * 
     * @return array Array of admin email addresses
     */
    private function get_admin_emails() {
        // Get admin email from settings
        $admin_email = get_option('admin_email');
        $emails = array($admin_email);
        
        // Get additional administrator users
        $admins = get_users(array(
            'role' => 'administrator',
            'fields' => array('user_email')
        ));
        
        foreach ($admins as $admin) {
            if (!empty($admin->user_email) && !in_array($admin->user_email, $emails)) {
                $emails[] = $admin->user_email;
            }
        }
        
        return array_filter($emails);
    }

    /**
     * Get the highest role for a user
     * 
     * @param WP_User $user_data User data
     * @return string Highest role name
     */
    private function get_highest_user_role($user_data) {
        $roles = $user_data->roles;
        
        // Role hierarchy (highest to lowest)
        $role_hierarchy = array(
            'administrator',
            'editor', 
            'author',
            'contributor',
            'subscriber'
        );
        
        foreach ($role_hierarchy as $role) {
            if (in_array($role, $roles)) {
                return $role;
            }
        }
        
        return 'subscriber'; // Fallback
    }

    /**
     * Build HTML email for weak password alert
     * 
     * @param string $site_name Site name
     * @param string $site_url Site URL  
     * @param string $short_message Short alert message
     * @param string $long_message Long description
     * @param WP_User $user_data User data
     * @param string $user_edit_url User edit URL
     * @param array $weakness_details Weakness analysis details
     * @return string HTML email content
     */
    private function build_weak_password_email($site_name, $site_url, $short_message, $long_message, $user_data, $user_edit_url, $weakness_details) {
        $strength_labels = array(
            0 => 'Very Weak',
            1 => 'Weak', 
            2 => 'Medium',
            3 => 'Strong'
        );
        
        ob_start();
        ?>
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title><?php echo esc_html($site_name); ?> Security Alert</title>
        </head>
        <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
            <div style="max-width: 600px; margin: 0 auto; padding: 20px;">
                <h2 style="color: #d63638; border-bottom: 2px solid #d63638; padding-bottom: 10px;">
                    🔒 VMPFence Security Alert
                </h2>
                
                <div style="background: #fff2f2; border-left: 4px solid #d63638; padding: 15px; margin: 20px 0;">
                    <h3 style="margin-top: 0; color: #d63638;">Weak Password Detected</h3>
                    <p><strong><?php echo esc_html($short_message); ?></strong></p>
                </div>
                
                <div style="background: #f9f9f9; padding: 15px; border-radius: 5px; margin: 20px 0;">
                    <h4>Password Strength Analysis:</h4>
                    <ul>
                        <li><strong>Strength Score:</strong> <?php echo $weakness_details['strength_score']; ?>/3</li>
                        <li><strong>Strength Level:</strong> <?php echo esc_html($weakness_details['strength_label']); ?></li>
                        <li><strong>Required Level:</strong> <?php echo esc_html($strength_labels[$weakness_details['min_required']]); ?> (<?php echo $weakness_details['min_required']; ?>/3)</li>
                    </ul>
                    <p><em><?php echo esc_html($weakness_details['reason']); ?></em></p>
                </div>
                
                <div style="background: #f9f9f9; padding: 15px; border-radius: 5px; margin: 20px 0;">
                    <h4>User Details:</h4>
                    <ul>
                        <li><strong>Username:</strong> <?php echo esc_html($user_data->user_login); ?></li>
                        <li><strong>Email:</strong> <?php echo esc_html($user_data->user_email); ?></li>
                        <li><strong>Display Name:</strong> <?php echo esc_html($user_data->display_name); ?></li>
                        <li><strong>Role:</strong> <?php echo esc_html($this->get_highest_user_role($user_data)); ?></li>
                        <li><strong>Privilege Level:</strong> <?php echo $weakness_details['is_privileged'] ? 'Privileged User' : 'Standard User'; ?></li>
                    </ul>
                </div>
                
                <div style="margin: 20px 0;">
                    <h4>What This Means:</h4>
                    <p><?php echo esc_html($long_message); ?></p>
                    
                    <p><strong>Important:</strong> This uses the same password strength algorithm as WordPress's "Enforce Strong Passwords" feature. The analysis is based on password complexity, length, and patterns - not dictionary matching.</p>
                </div>
                
                <div style="background: #e7f3ff; border-left: 4px solid #0073aa; padding: 15px; margin: 20px 0;">
                    <h4 style="margin-top: 0;">WordPress Password Strength Standards:</h4>
                    <ul>
                        <li><strong>Very Weak (0):</strong> Too short, common patterns, or contains user info</li>
                        <li><strong>Weak (1):</strong> Minimal character diversity</li>
                        <li><strong>Medium (2):</strong> Good length and character mix</li>
                        <li><strong>Strong (3):</strong> Excellent length, character diversity, and complexity</li>
                    </ul>
                </div>
                
                <div style="background: #e7f3ff; border-left: 4px solid #0073aa; padding: 15px; margin: 20px 0;">
                    <h4 style="margin-top: 0;">Recommended Actions:</h4>
                    <ol>
                        <li>Contact the user to change their password</li>
                        <li>Suggest using a password manager</li>
                        <li>Consider enabling "Enforce Strong Passwords" in VMPFence settings</li>
                        <li>Educate users about password best practices</li>
                    </ol>
                </div>
                
                <div style="text-align: center; margin: 30px 0;">
                    <a href="<?php echo esc_url($user_edit_url); ?>" 
                       style="background: #0073aa; color: white; padding: 12px 25px; text-decoration: none; border-radius: 5px; display: inline-block;">
                        Edit User Account
                    </a>
                </div>
                
                <hr style="border: 1px solid #eee; margin: 30px 0;">
                
                <div style="font-size: 12px; color: #666;">
                    <p><strong>Site:</strong> <a href="<?php echo esc_url($site_url); ?>"><?php echo esc_html($site_name); ?></a></p>
                    <p><strong>Generated by:</strong> VMPFence Security Plugin</p>
                    <p><strong>Algorithm:</strong> WordPress Password Strength Meter (same as "Enforce Strong Passwords")</p>
                    <p><strong>Time:</strong> <?php echo date('Y-m-d H:i:s'); ?></p>
                </div>
            </div>
        </body>
        </html>
        <?php
        return ob_get_clean();
    }
}