<?php
/**
 * Two-Factor Authentication REST Controller
 *
 * Provides REST API endpoints for 2FA setup, verification, and management.
 *
 * @package     WPUltimateSecurity\UltimateSecurity\Presentation\API\Controllers
 * @since       2.0.0
 */

declare(strict_types=1);

namespace WPUltimateSecurity\UltimateSecurity\Presentation\API\Controllers;

use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WPUltimateSecurity\UltimateSecurity\Presentation\API\AbstractRestController;
use WPUltimateSecurity\UltimateSecurity\Modules\Authentication\TwoFactor\Providers\EmailProvider;
use WPUltimateSecurity\UltimateSecurity\Modules\Authentication\TwoFactor\Providers\TOTPProvider;
use WPUltimateSecurity\UltimateSecurity\Modules\Authentication\TwoFactor\Providers\HOTPProvider;
use WPUltimateSecurity\UltimateSecurity\Modules\Authentication\TwoFactor\Services\SimpleBackupCodeService;
use WPUltimateSecurity\UltimateSecurity\Modules\Authentication\TwoFactor\Http\AjaxHandlers;
use WPUltimateSecurity\UltimateSecurity\Support\Helpers\Utils;

/**
 * REST API controller for Two-Factor Authentication.
 *
 * Provides endpoints for:
 * - Email 2FA setup and verification
 * - TOTP (Authenticator App) setup and verification
 * - HOTP (Counter-based) setup and verification
 * - Provider selection and status
 * - Backup codes status
 *
 * @since 2.0.0
 */
class TwoFactorController extends AbstractRestController
{
    /**
     * The resource name for this controller.
     *
     * @var string
     */
    protected string $resource = '2fa';

    /**
     * Register the controller's routes.
     *
     * @since 2.0.0
     * @return void
     */
    public function registerRoutes(): void
    {
        // Email 2FA routes
        $this->registerEmailRoutes();

        // TOTP routes
        $this->registerTOTPRoutes();

        // HOTP routes
        $this->registerHOTPRoutes();

        // Provider management routes
        $this->registerProviderRoutes();

        // Backup codes status route
        $this->registerBackupCodesRoutes();
    }

    /**
     * Register Email 2FA routes.
     *
     * @return void
     */
    private function registerEmailRoutes(): void
    {
        // Send verification code
        $this->registerRoute('email/send-code', [
            'methods' => 'POST',
            'callback' => [$this, 'sendEmailCode'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);

        // Verify code and enable
        $this->registerRoute('email/verify', [
            'methods' => 'POST',
            'callback' => [$this, 'verifyEmailCode'],
            'permission_callback' => [$this, 'checkUserPermission'],
            'args' => [
                'code' => [
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                ],
            ],
        ]);

        // Disable email 2FA
        $this->registerRoute('email/disable', [
            'methods' => 'POST',
            'callback' => [$this, 'disableEmail'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);

        // Get email 2FA status
        $this->registerRoute('email/status', [
            'methods' => 'GET',
            'callback' => [$this, 'getEmailStatus'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);
    }

    /**
     * Register TOTP routes.
     *
     * @return void
     */
    private function registerTOTPRoutes(): void
    {
        // Setup TOTP (generate secret and QR code)
        $this->registerRoute('totp/setup', [
            'methods' => 'POST',
            'callback' => [$this, 'setupTOTP'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);

        // Verify TOTP code and enable
        $this->registerRoute('totp/verify', [
            'methods' => 'POST',
            'callback' => [$this, 'verifyTOTP'],
            'permission_callback' => [$this, 'checkUserPermission'],
            'args' => [
                'code' => [
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                ],
            ],
        ]);

        // Disable TOTP
        $this->registerRoute('totp/disable', [
            'methods' => 'POST',
            'callback' => [$this, 'disableTOTP'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);

        // Get TOTP status
        $this->registerRoute('totp/status', [
            'methods' => 'GET',
            'callback' => [$this, 'getTOTPStatus'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);
    }

    /**
     * Register HOTP routes.
     *
     * @return void
     */
    private function registerHOTPRoutes(): void
    {
        // Setup HOTP
        $this->registerRoute('hotp/setup', [
            'methods' => 'POST',
            'callback' => [$this, 'setupHOTP'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);

        // Verify HOTP code and enable
        $this->registerRoute('hotp/verify', [
            'methods' => 'POST',
            'callback' => [$this, 'verifyHOTP'],
            'permission_callback' => [$this, 'checkUserPermission'],
            'args' => [
                'code' => [
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                ],
            ],
        ]);

        // Disable HOTP
        $this->registerRoute('hotp/disable', [
            'methods' => 'POST',
            'callback' => [$this, 'disableHOTP'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);

        // Get HOTP status
        $this->registerRoute('hotp/status', [
            'methods' => 'GET',
            'callback' => [$this, 'getHOTPStatus'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);
    }

    /**
     * Register provider management routes.
     *
     * @return void
     */
    private function registerProviderRoutes(): void
    {
        // Set active provider
        $this->registerRoute('provider', [
            'methods' => 'POST',
            'callback' => [$this, 'setProvider'],
            'permission_callback' => [$this, 'checkUserPermission'],
            'args' => [
                'provider' => [
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field',
                    'enum' => ['email', 'totp', 'hotp', 'sms', 'webauthn', 'none'],
                ],
            ],
        ]);

        // Get current provider and available methods
        $this->registerRoute('provider', [
            'methods' => 'GET',
            'callback' => [$this, 'getProvider'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);

        // Get overall 2FA status for current user
        $this->registerRoute('status', [
            'methods' => 'GET',
            'callback' => [$this, 'getOverallStatus'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);
    }

    /**
     * Register backup codes routes.
     *
     * @return void
     */
    private function registerBackupCodesRoutes(): void
    {
        // Get backup codes status (not the codes themselves)
        $this->registerRoute('backup-codes/status', [
            'methods' => 'GET',
            'callback' => [$this, 'getBackupCodesStatus'],
            'permission_callback' => [$this, 'checkUserPermission'],
        ]);
    }

    // =========================================================================
    // Permission Callbacks
    // =========================================================================

    /**
     * Check if user can access their own 2FA settings.
     *
     * @param WP_REST_Request $request The request object.
     * @return bool|WP_Error True if permitted, WP_Error otherwise.
     */
    public function checkUserPermission(WP_REST_Request $request): bool|WP_Error
    {
        if (!is_user_logged_in()) {
            return $this->permissionDenied(__('You must be logged in to manage 2FA settings.', 'ultimate-security'));
        }

        // Users can only manage their own 2FA unless they're an admin
        $requested_user_id = $this->getInt($request, 'user_id', 0);
        if ($requested_user_id > 0 && $requested_user_id !== get_current_user_id()) {
            if (!current_user_can('manage_options')) {
                return $this->permissionDenied(__('You can only manage your own 2FA settings.', 'ultimate-security'));
            }
        }

        return true;
    }

    /**
     * Get the user ID from request or current user.
     *
     * @param WP_REST_Request $request The request object.
     * @return int User ID.
     */
    private function getUserId(WP_REST_Request $request): int
    {
        $user_id = $this->getInt($request, 'user_id', 0);
        return $user_id > 0 ? $user_id : get_current_user_id();
    }

    // =========================================================================
    // Email 2FA Endpoints
    // =========================================================================

    /**
     * Send email verification code.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function sendEmailCode(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        // Check if email 2FA is enabled globally
        $options = Utils::ultimate_security_get_option();
        if (empty($options['security']['2fa_authentication']['email_authentication']['2fa_email_verification_enable'])) {
            return $this->error(
                'email_2fa_disabled',
                __('Email 2FA is not enabled for this site.', 'ultimate-security'),
                400
            );
        }

        // Check if user role is allowed
        $user = get_user_by('id', $user_id);
        if (!$user) {
            return $this->notFound(__('User not found.', 'ultimate-security'));
        }

        $allowed_roles = $options['security']['2fa_authentication']['email_authentication']['2fa_email_verification_enable_for'] ?? [];
        if (!$this->isUserRoleAllowed($user, $allowed_roles)) {
            return $this->error(
                'role_not_allowed',
                __('Your user role is not allowed to use email 2FA.', 'ultimate-security'),
                403
            );
        }

        // Check if already enabled
        if (EmailProvider::is_enabled_for_user($user_id)) {
            return $this->error(
                'already_enabled',
                __('Email 2FA is already enabled for this user.', 'ultimate-security'),
                400
            );
        }

        // Send verification code
        $result = EmailProvider::send_verification_code($user_id);
        if (!$result) {
            return $this->error(
                'send_failed',
                __('Failed to send verification code. Please try again.', 'ultimate-security'),
                500
            );
        }

        return $this->success(
            ['sent' => true],
            __('Verification code sent to your email.', 'ultimate-security')
        );
    }

    /**
     * Verify email code and enable 2FA.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function verifyEmailCode(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);
        $code = $this->getString($request, 'code');

        if (empty($code)) {
            return $this->validationError(__('Verification code is required.', 'ultimate-security'));
        }

        // Verify the code
        if (!EmailProvider::verify_code($user_id, $code)) {
            return $this->error(
                'invalid_code',
                __('Invalid or expired verification code.', 'ultimate-security'),
                400
            );
        }

        // Enable email 2FA for user
        EmailProvider::enable_for_user($user_id);

        // Log the event
        $this->logTwoFactorEnabled($user_id, 'email');

        return $this->success(
            ['enabled' => true],
            __('Email 2FA has been enabled.', 'ultimate-security')
        );
    }

    /**
     * Disable email 2FA.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function disableEmail(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        EmailProvider::disable_for_user($user_id);

        // Clear provider if it was email
        $current_provider = get_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER, true);
        if ($current_provider === 'Email Authentication' || $current_provider === 'email') {
            delete_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER);
        }

        $this->logTwoFactorDisabled($user_id, 'email');

        return $this->success(
            ['enabled' => false],
            __('Email 2FA has been disabled.', 'ultimate-security')
        );
    }

    /**
     * Get email 2FA status.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function getEmailStatus(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);
        $user = get_user_by('id', $user_id);

        $enabled = EmailProvider::is_enabled_for_user($user_id);

        // Mask email for display
        $email = $user ? $user->user_email : '';
        $masked_email = $this->maskEmail($email);

        return $this->success([
            'enabled' => $enabled,
            'email' => $masked_email,
            'configured' => $enabled,
        ]);
    }

    // =========================================================================
    // TOTP Endpoints
    // =========================================================================

    /**
     * Setup TOTP - generate secret and QR code.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function setupTOTP(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        // Check if TOTP is enabled globally
        $options = Utils::ultimate_security_get_option();
        if (empty($options['security']['2fa_authentication']['application_authentication']['2fa_application_authentication_enable'])) {
            return $this->error(
                'totp_disabled',
                __('Authenticator app 2FA is not enabled for this site.', 'ultimate-security'),
                400
            );
        }

        // Generate new secret (or get existing)
        $otp_data = TOTPProvider::get_otp_data($user_id);
        if (!$otp_data) {
            return $this->error(
                'setup_failed',
                __('Failed to generate TOTP secret.', 'ultimate-security'),
                500
            );
        }

        return $this->success([
            'secret' => $otp_data['totp_secret'],
            'qr_code' => $otp_data['totp_qr_code'],
            'current_code' => $otp_data['totp_code'], // For testing/verification
        ]);
    }

    /**
     * Verify TOTP code and enable.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function verifyTOTP(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);
        $code = $this->getString($request, 'code');

        if (empty($code)) {
            return $this->validationError(__('Verification code is required.', 'ultimate-security'));
        }

        // Verify the code
        if (!TOTPProvider::verify_code($user_id, $code)) {
            return $this->error(
                'invalid_code',
                __('Invalid verification code. Please check and try again.', 'ultimate-security'),
                400
            );
        }

        // Mark TOTP as verified/configured
        update_user_meta($user_id, 'ultimate_security_2fa_totp_verified', true);
        update_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER, 'Authenticator Application');
        update_user_meta($user_id, AjaxHandlers::META_2FA_UPDATED_AT, current_time('mysql'));

        $this->logTwoFactorEnabled($user_id, 'totp');

        return $this->success(
            ['enabled' => true, 'verified' => true],
            __('Authenticator app 2FA has been enabled.', 'ultimate-security')
        );
    }

    /**
     * Disable TOTP.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function disableTOTP(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        TOTPProvider::disable_for_user($user_id);
        delete_user_meta($user_id, 'ultimate_security_2fa_totp_verified');

        // Clear provider if it was TOTP
        $current_provider = get_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER, true);
        if ($current_provider === 'Authenticator Application' || $current_provider === 'totp') {
            delete_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER);
        }

        $this->logTwoFactorDisabled($user_id, 'totp');

        return $this->success(
            ['enabled' => false],
            __('Authenticator app 2FA has been disabled.', 'ultimate-security')
        );
    }

    /**
     * Get TOTP status.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function getTOTPStatus(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        $configured = TOTPProvider::is_configured($user_id);
        $verified = (bool) get_user_meta($user_id, 'ultimate_security_2fa_totp_verified', true);

        return $this->success([
            'enabled' => $configured && $verified,
            'configured' => $configured,
            'verified' => $verified,
        ]);
    }

    // =========================================================================
    // HOTP Endpoints
    // =========================================================================

    /**
     * Setup HOTP.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function setupHOTP(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        // Check if HOTP is enabled globally
        $options = Utils::ultimate_security_get_option();
        if (empty($options['security']['2fa_authentication']['application_authentication']['2fa_application_authentication_enable'])) {
            return $this->error(
                'hotp_disabled',
                __('Authenticator app 2FA is not enabled for this site.', 'ultimate-security'),
                400
            );
        }

        $otp_data = HOTPProvider::get_otp_data($user_id);
        if (!$otp_data) {
            return $this->error(
                'setup_failed',
                __('Failed to generate HOTP secret.', 'ultimate-security'),
                500
            );
        }

        return $this->success([
            'secret' => $otp_data['hotp_secret'],
            'qr_code' => $otp_data['hotp_qr_code'],
            'counter' => $otp_data['hotp_counter'],
        ]);
    }

    /**
     * Verify HOTP code and enable.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function verifyHOTP(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);
        $code = $this->getString($request, 'code');

        if (empty($code)) {
            return $this->validationError(__('Verification code is required.', 'ultimate-security'));
        }

        if (!HOTPProvider::verify_code($user_id, $code)) {
            return $this->error(
                'invalid_code',
                __('Invalid verification code.', 'ultimate-security'),
                400
            );
        }

        update_user_meta($user_id, 'ultimate_security_2fa_hotp_verified', true);
        update_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER, 'HOTP');
        update_user_meta($user_id, AjaxHandlers::META_2FA_UPDATED_AT, current_time('mysql'));

        $this->logTwoFactorEnabled($user_id, 'hotp');

        return $this->success(
            ['enabled' => true, 'verified' => true],
            __('HOTP 2FA has been enabled.', 'ultimate-security')
        );
    }

    /**
     * Disable HOTP.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function disableHOTP(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        HOTPProvider::disable_for_user($user_id);
        delete_user_meta($user_id, 'ultimate_security_2fa_hotp_verified');

        $current_provider = get_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER, true);
        if ($current_provider === 'HOTP' || $current_provider === 'hotp') {
            delete_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER);
        }

        $this->logTwoFactorDisabled($user_id, 'hotp');

        return $this->success(
            ['enabled' => false],
            __('HOTP 2FA has been disabled.', 'ultimate-security')
        );
    }

    /**
     * Get HOTP status.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function getHOTPStatus(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        $configured = HOTPProvider::is_configured($user_id);
        $verified = (bool) get_user_meta($user_id, 'ultimate_security_2fa_hotp_verified', true);

        return $this->success([
            'enabled' => $configured && $verified,
            'configured' => $configured,
            'verified' => $verified,
        ]);
    }

    // =========================================================================
    // Provider Management Endpoints
    // =========================================================================

    /**
     * Set active 2FA provider.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function setProvider(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);
        $provider = $this->getString($request, 'provider');

        // Validate provider is configured
        if ($provider !== 'none' && !$this->isProviderConfigured($user_id, $provider)) {
            return $this->error(
                'provider_not_configured',
                __('The selected 2FA method is not configured. Please set it up first.', 'ultimate-security'),
                400
            );
        }

        // Map provider slug to stored value
        $provider_map = [
            'email' => 'Email Authentication',
            'totp' => 'Authenticator Application',
            'hotp' => 'HOTP',
            'sms' => 'SMS',
            'webauthn' => 'WebAuthn',
            'none' => '',
        ];

        $stored_value = $provider_map[$provider] ?? '';

        if ($provider === 'none') {
            delete_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER);
        } else {
            update_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER, $stored_value);
            update_user_meta($user_id, AjaxHandlers::META_2FA_UPDATED_AT, current_time('mysql'));
        }

        return $this->success(
            ['provider' => $provider],
            __('2FA provider updated.', 'ultimate-security')
        );
    }

    /**
     * Get current provider and available methods.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function getProvider(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        $stored_provider = get_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER, true);

        // Map stored value to slug
        $provider_map = [
            'Email Authentication' => 'email',
            'Authenticator Application' => 'totp',
            'HOTP' => 'hotp',
            'SMS' => 'sms',
            'WebAuthn' => 'webauthn',
        ];

        $current = $provider_map[$stored_provider] ?? null;

        // Get available (configured) methods
        $available = [];
        if (EmailProvider::is_enabled_for_user($user_id)) {
            $available[] = 'email';
        }
        if (TOTPProvider::is_configured($user_id) && get_user_meta($user_id, 'ultimate_security_2fa_totp_verified', true)) {
            $available[] = 'totp';
        }
        if (HOTPProvider::is_configured($user_id) && get_user_meta($user_id, 'ultimate_security_2fa_hotp_verified', true)) {
            $available[] = 'hotp';
        }

        // Check for Pro providers
        if (class_exists('\WPUltimateSecurity\UltimateSecurityPro\Modules\Authentication\Authentication2FASMS')) {
            if (get_user_meta($user_id, 'ultimate_security_sms_verified', true)) {
                $available[] = 'sms';
            }
        }

        return $this->success([
            'provider' => $current,
            'available' => $available,
        ]);
    }

    /**
     * Get overall 2FA status.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function getOverallStatus(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        $provider = get_user_meta($user_id, AjaxHandlers::META_2FA_PROVIDER, true);
        $has_2fa = !empty($provider);

        return $this->success([
            'enabled' => $has_2fa,
            'provider' => $provider ?: null,
            'methods' => [
                'email' => EmailProvider::is_enabled_for_user($user_id),
                'totp' => TOTPProvider::is_configured($user_id),
                'hotp' => HOTPProvider::is_configured($user_id),
            ],
        ]);
    }

    // =========================================================================
    // Backup Codes Endpoints
    // =========================================================================

    /**
     * Get backup codes status.
     *
     * @param WP_REST_Request $request The request object.
     * @return WP_REST_Response|WP_Error
     */
    public function getBackupCodesStatus(WP_REST_Request $request): WP_REST_Response|WP_Error
    {
        $user_id = $this->getUserId($request);

        // Check if Pro backup code service exists
        if (class_exists('\WPUltimateSecurity\UltimateSecurityPro\Modules\Authentication\TwoFactor\Services\BackupCodeService')) {
            $remaining = \WPUltimateSecurity\UltimateSecurityPro\Modules\Authentication\TwoFactor\Services\BackupCodeService::get_remaining_count($user_id);
        } else {
            $status = SimpleBackupCodeService::get_status($user_id);
            $remaining = $status['remaining'] ?? 0;
        }

        return $this->success([
            'has_codes' => $remaining > 0,
            'remaining' => $remaining,
            'is_low' => $remaining > 0 && $remaining <= 3,
        ]);
    }

    // =========================================================================
    // Helper Methods
    // =========================================================================

    /**
     * Check if user role is allowed for a 2FA method.
     *
     * @param \WP_User $user          The user object.
     * @param array    $allowed_roles Array of allowed role configs.
     * @return bool
     */
    private function isUserRoleAllowed(\WP_User $user, array $allowed_roles): bool
    {
        if (empty($allowed_roles)) {
            return true; // No restriction
        }

        $allowed_codes = [];
        foreach ($allowed_roles as $role) {
            if (!empty($role)) {
                $allowed_codes[] = $role;
            }
        }

        if (empty($allowed_codes)) {
            return true;
        }

        return !empty(array_intersect($allowed_codes, $user->roles));
    }

    /**
     * Check if a provider is configured for user.
     *
     * @param int    $user_id  User ID.
     * @param string $provider Provider slug.
     * @return bool
     */
    private function isProviderConfigured(int $user_id, string $provider): bool
    {
        return match ($provider) {
            'email' => EmailProvider::is_enabled_for_user($user_id),
            'totp' => TOTPProvider::is_configured($user_id) && get_user_meta($user_id, 'ultimate_security_2fa_totp_verified', true),
            'hotp' => HOTPProvider::is_configured($user_id) && get_user_meta($user_id, 'ultimate_security_2fa_hotp_verified', true),
            'sms' => (bool) get_user_meta($user_id, 'ultimate_security_sms_verified', true),
            'webauthn' => false, // TODO: Implement when WebAuthn 2FA is added
            default => false,
        };
    }

    /**
     * Mask an email address for display.
     *
     * @param string $email Email address.
     * @return string Masked email.
     */
    private function maskEmail(string $email): string
    {
        if (empty($email) || !str_contains($email, '@')) {
            return '';
        }

        [$local, $domain] = explode('@', $email);

        if (strlen($local) <= 2) {
            $masked_local = str_repeat('*', strlen($local));
        } else {
            $masked_local = substr($local, 0, 1) . str_repeat('*', strlen($local) - 2) . substr($local, -1);
        }

        return $masked_local . '@' . $domain;
    }

    /**
     * Log 2FA enabled event.
     *
     * @param int    $user_id User ID.
     * @param string $method  2FA method.
     */
    private function logTwoFactorEnabled(int $user_id, string $method): void
    {
        if (class_exists('\WPUltimateSecurity\UltimateSecurityPro\Modules\Authentication\TwoFactor\Storage\LogRepository')) {
            \WPUltimateSecurity\UltimateSecurityPro\Modules\Authentication\TwoFactor\Storage\LogRepository::log_2fa_enabled($user_id, $method);
        }

        $user = get_user_by('id', $user_id);
        do_action('ultimate_security_2fa_method_enabled', $user_id, $method, $user);
    }

    /**
     * Log 2FA disabled event.
     *
     * @param int    $user_id User ID.
     * @param string $method  2FA method.
     */
    private function logTwoFactorDisabled(int $user_id, string $method): void
    {
        if (class_exists('\WPUltimateSecurity\UltimateSecurityPro\Modules\Authentication\TwoFactor\Storage\LogRepository')) {
            \WPUltimateSecurity\UltimateSecurityPro\Modules\Authentication\TwoFactor\Storage\LogRepository::log_2fa_disabled($user_id, $method);
        }

        $user = get_user_by('id', $user_id);
        do_action('ultimate_security_2fa_method_disabled', $user_id, $method, $user);
    }
}
