<?php
if (!defined('ABSPATH')) {
    exit;
}


function vs_registration_otp_lifetime() {
    return 10 * MINUTE_IN_SECONDS; 
}
function vs_registration_otp_resend_delay() {
    return 60; 
}

function vs_registration_otp_max_attempts() {
    return 5;
}


function vs_otp_log($message, $data = null) {
    if (defined('WP_DEBUG') && WP_DEBUG) {
        $output = '[VS OTP DEBUG] ' . $message;
        if ($data !== null) {
            $output .= ' | Data: ' . (is_scalar($data) ? $data : wp_json_encode($data));
        }
        error_log($output);
    }
}

// --- Session & Token Management (Cookie-based) ---

function vs_registration_otp_ensure_session() {
    if ( ! session_id() && ! headers_sent() ) {
        session_start();
    }
}

function vs_registration_otp_get_token() {
    $token = '';

    // 1. Try PHP Session (most reliable - works even after output starts)
    vs_registration_otp_ensure_session();
    if ( ! empty( $_SESSION['vs_verification_token'] ) ) {
        $token = sanitize_text_field( wp_unslash( $_SESSION['vs_verification_token'] ) );
    }

    // 2. Try Cookie (fallback for environments without session)
    if ( empty( $token ) && ! empty( $_COOKIE['vs_verification_token'] ) ) {
        $token = sanitize_text_field( wp_unslash( $_COOKIE['vs_verification_token'] ) );
    }

    // 3. Try URL parameter (Fallback)
    if ( empty( $token ) && ! empty( $_GET['vs_otp'] ) ) {
        $token = sanitize_text_field( wp_unslash( $_GET['vs_otp'] ) );
    }

    // 4. Try POST parameter (for AJAX)
    if ( empty( $token ) && ! empty( $_POST['token'] ) ) {
        $token = sanitize_text_field( wp_unslash( $_POST['token'] ) );
    }

    return (string) $token;
}

/**
 * Set the pending OTP token in PHP session AND cookie.
 */
function vs_registration_otp_set_token( $token ) {
    // Always store in PHP session (works regardless of output timing)
    vs_registration_otp_ensure_session();
    $_SESSION['vs_verification_token'] = (string) $token;

    // Also try cookie if headers not yet sent
    if ( ! headers_sent() ) {
        $expire = current_time( 'timestamp' ) + vs_registration_otp_lifetime();
        setcookie(
            'vs_verification_token',
            (string) $token,
            $expire,
            COOKIEPATH ?: '/',
            COOKIE_DOMAIN,
            is_ssl(),
            true // HttpOnly
        );
    }

    vs_otp_log( 'Token set in session', [ 'token' => $token ] );
}

/**
 * Clear the pending OTP token.
 */
function vs_registration_otp_clear_token() {
    vs_registration_otp_ensure_session();
    unset( $_SESSION['vs_verification_token'] );

    if ( ! headers_sent() ) {
        setcookie( 'vs_verification_token', '', time() - 3600, COOKIEPATH ?: '/', COOKIE_DOMAIN, is_ssl(), true );
    }
    vs_otp_log( 'Token cleared from session' );
}

// --- Transient Storage logic ---

function vs_registration_otp_transient_key($token) {
    return 'vs_registration_otp_' . sanitize_key((string) $token);
}

/**
 * Normalize OTP digit characters (Arabic-Indic, Persian, etc.) to ASCII digits
 */
function vs_normalize_otp_digits($s) {
    $s = (string) $s;
    $arabic = ['٠','١','٢','٣','٤','٥','٦','٧','٨','٩'];
    $persian = ['۰','۱','۲','۳','۴','۵','۶','۷','٨','٩'];
    $s = str_replace($arabic, range(0,9), $s);
    $s = str_replace($persian, range(0,9), $s);
    return preg_replace('/\D+/', '', $s);
}

function vs_registration_otp_hmac_key() {
    static $key = null;
    if ($key === null) {
        $key = hash('sha256', wp_salt('nonce') . 'vs_registration_otp', true);
    }
    return $key;
}

function vs_registration_otp_hash($otp) {
    return hash_hmac('sha256', (string) $otp, vs_registration_otp_hmac_key());
}

function vs_registration_otp_get($token = '') {
    $token = $token ?: vs_registration_otp_get_token();
    if ($token === '') {
        vs_otp_log('Attempted to get OTP but token is empty');
        return null;
    }

    $pending = get_transient(vs_registration_otp_transient_key($token));
    
    if (!$pending) {
        vs_otp_log('Transient not found for token', $token);
        return null;
    }

    vs_otp_log('Retrieved transient data', [
        'token' => $token,
        'has_otp_hash' => isset($pending['otp_hash']),
        'expires_at' => $pending['expires_at'] ?? 'NOT_SET',
        'current_time' => current_time('timestamp')
    ]);
    
    return is_array($pending) ? $pending : null;
}

function vs_registration_otp_store(array $pending, $token = '') {
    $token = $token ?: ($pending['token'] ?? '');
    if ($token === '') {
        vs_otp_log('Critical: Attempted to store OTP with empty token');
        return false;
    }

    $pending['token'] = $token;
    $store_data = $pending;

    if (isset($store_data['otp'])) {
        $store_data['otp_hash'] = vs_registration_otp_hash(vs_normalize_otp_digits($store_data['otp']));
        unset($store_data['otp']);
    }

    vs_otp_log('Storing pending data for token', [
        'token' => $token,
        'email' => $store_data['email'] ?? '',
        'account_type' => $store_data['account_type'] ?? 'customer',
        'shop_name' => $store_data['shop_name'] ?? '',
        'display_name' => $store_data['display_name'] ?? '',
    ]);
    
    $stored = set_transient(vs_registration_otp_transient_key($token), $store_data, vs_registration_otp_lifetime());
    
    if (!$stored) {
        vs_otp_log('Critical: Failed to set transient for token', $token);
    } else {
        vs_otp_log('Successfully stored transient for token', $token);
    }
    
    return $stored;
}

function vs_registration_otp_clear($token = '') {
    $token = $token ?: vs_registration_otp_get_token();
    if ($token !== '') {
        delete_transient(vs_registration_otp_transient_key($token));
        vs_otp_log('Deleted transient for token', $token);
    }

    vs_registration_otp_clear_token();
}

// --- Email & Payload Construction ---

function vs_registration_build_pending_payload($username, $email) {
    $account_type = isset($_POST['account_type']) ? sanitize_text_field(wp_unslash($_POST['account_type'])) : 'customer';

    return [
        'email' => sanitize_email($email),
        'username' => sanitize_user($username ?: $email, true),
        'account_type' => $account_type,
        'password' => isset($_POST['password']) ? wc_clean(wp_unslash($_POST['password'])) : '',
        'display_name' => isset($_POST['display_name']) ? sanitize_text_field(wp_unslash($_POST['display_name'])) : '',
        'shop_name' => isset($_POST['shop_name']) ? sanitize_text_field(wp_unslash($_POST['shop_name'])) : '',
        'shop_url' => isset($_POST['shop_url']) ? sanitize_title(wp_unslash($_POST['shop_url'])) : '',
        'billing_phone' => isset($_POST['phone']) ? sanitize_text_field(wp_unslash($_POST['phone'])) : '',
        'billing_address_1' => isset($_POST['billing_address_1']) ? sanitize_text_field(wp_unslash($_POST['billing_address_1'])) : '',
    ];
}

function vs_registration_payload_signature(array $payload) {
    return md5(wp_json_encode($payload));
}

function vs_registration_otp_email_html(array $pending) {
    $otp = (string) ($pending['otp'] ?? '');
    $recipient_name = $pending['display_name'] ?: __('User', 'vendor-space');
    $minutes = max(1, (int) ceil(vs_registration_otp_lifetime() / MINUTE_IN_SECONDS));

    return '
    <div style="background:#f4f7fb;padding:32px 16px;font-family:Arial,Helvetica,sans-serif;">
        <div style="max-width:520px;margin:0 auto;background:#ffffff;border-radius:18px;padding:32px;border:1px solid #e5e7eb;box-shadow:0 18px 50px rgba(15,23,42,0.08);">
            <div style="text-align:center;margin-bottom:24px;">
                <div style="display:inline-block;padding:10px 14px;border-radius:999px;background:#eff6ff;color:#1d4ed8;font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;">' . esc_html__('OTP Verification', 'vendor-space') . '</div>
                <h2 style="margin:16px 0 8px;font-size:28px;color:#0f172a;">' . esc_html__('Confirm your registration', 'vendor-space') . '</h2>
                <p style="margin:0;font-size:15px;line-height:1.8;color:#475569;">' . sprintf(esc_html__('Hello %s, enter this 4-digit code to finish creating your account.', 'vendor-space'), esc_html($recipient_name)) . '</p>
            </div>
            <div style="margin:28px 0;text-align:center;">
                <span style="display:inline-block;padding:16px 28px;background:#2563eb;color:#ffffff;font-size:32px;font-weight:700;letter-spacing:10px;border-radius:16px;">' . esc_html($otp) . '</span>
            </div>
            <div style="padding:16px 18px;border-radius:14px;background:#f8fafc;color:#475569;font-size:14px;line-height:1.8;">
                <strong style="color:#0f172a;">' . esc_html__('Security note:', 'vendor-space') . '</strong> ' . sprintf(esc_html__('This code expires in %d minutes. If you did not request it, you can ignore this email.', 'vendor-space'), $minutes) . '
            </div>
        </div>
    </div>';
}

function vs_registration_send_otp_email(array $pending) {
    if (!function_exists('wc_mail') || empty($pending['email'])) {
        vs_otp_log('Email skipped: wc_mail missing or empty email');
        return false;
    }

    $to = $pending['email'];
    $subject = __('Your Verification Code', 'vendor-space');
    $message = vs_registration_otp_email_html($pending);
    $headers = ['Content-Type: text/html; charset=UTF-8'];

    vs_otp_log('Attempting to send OTP email', ['to' => $to, 'subject' => $subject]);

    $sent = wc_mail($to, $subject, $message, $headers);
    
    vs_otp_log('OTP Email sent status', $sent ? 'Success' : 'Failed');
    
    if (!$sent) {
        vs_otp_log('Email sending failed - checking PHPMailer errors');
        global $phpmailer;
        if (isset($phpmailer) && $phpmailer->ErrorInfo) {
            vs_otp_log('PHPMailer Error: ' . $phpmailer->ErrorInfo);
        }
    }
    
    return $sent;
}

// --- User Creation ---

function vs_registration_create_user_from_pending(array $pending) {
    try {
        // Temporarily disable WooCommerce 'new account' emails when creating pending vendor accounts
        add_filter('woocommerce_email_enabled_customer_new_account', '__return_false');
        add_filter('woocommerce_email_enabled_new_account', '__return_false');

        $user_id = wc_create_new_customer(
                $pending['email'],
                $pending['username'],
                $pending['password']
            );

        // Restore email filters
        remove_filter('woocommerce_email_enabled_customer_new_account', '__return_false');
        remove_filter('woocommerce_email_enabled_new_account', '__return_false');

        if (is_wp_error($user_id)) {
            vs_otp_log('User creation error: ' . $user_id->get_error_message());
            return $user_id;
        }

        wp_update_user([
            'ID' => $user_id,
            'display_name' => $pending['display_name'] !== '' ? $pending['display_name'] : $pending['username'],
            'nickname' => $pending['display_name'] !== '' ? $pending['display_name'] : $pending['username'],
        ]);

        update_user_meta($user_id, 'billing_phone', $pending['billing_phone']);
        update_user_meta($user_id, 'billing_address_1', $pending['billing_address_1']);

        $user = new WP_User($user_id);
        if (($pending['account_type'] ?? 'customer') === 'vendor') {
            $approval_required = VS_Admin_Settings::get_option('vendors', 'manual_vendor_approval', 'yes') === 'yes';
            
            if ($approval_required) {
                $user->set_role('customer');
                update_user_meta($user_id, 'vs_vendor_status', 'pending');
                vs_otp_log('User created as PENDING VENDOR', $user_id);
                
                if (!empty($pending['shop_name'])) {
                    update_user_meta($user_id, 'store_name', $pending['shop_name']);
                    update_user_meta($user_id, 'vs_store_name', $pending['shop_name']);
                    vs_otp_log('Store name saved for pending vendor', ['user_id' => $user_id, 'shop_name' => $pending['shop_name']]);
                }
                if (!empty($pending['shop_url'])) {
                    update_user_meta($user_id, 'store_slug', $pending['shop_url']);
                    vs_otp_log('Store slug saved for pending vendor', ['user_id' => $user_id, 'shop_url' => $pending['shop_url']]);
                }
                
               
            } else {
                $user->set_role('vendor');
                update_user_meta($user_id, 'vs_vendor_status', 'active');
                vs_otp_log('User created as ACTIVE VENDOR', $user_id);
                
                update_user_meta($user_id, 'store_name', $pending['shop_name']);
                update_user_meta($user_id, 'store_slug', $pending['shop_url']);
                update_user_meta($user_id, 'vs_store_name', $pending['shop_name']);
            }
        } else {
            $user->set_role('customer');
            vs_otp_log('User created as CUSTOMER', $user_id);
        }

        return $user_id;
    } catch (Exception $e) {
        vs_otp_log('Exception during user creation: ' . $e->getMessage());
        return new WP_Error('user_creation_exception', $e->getMessage());
    }
}

// --- Core Hooks ---

/**
 * Intercept WooCommerce registration and trigger OTP
 */
add_filter('woocommerce_registration_errors', 'vs_pending_registration_errors', 20, 3);
function vs_pending_registration_errors($errors, $username, $email) {
    if (defined('DOING_AJAX') && DOING_AJAX) {
        return $errors;
    }

    if ($errors->get_error_codes()) {
        return $errors;
    }

    $email = sanitize_email($email);
    if ($email === '') {
        $errors->add('error', __('Please enter a valid email address.', 'vendor-space'));
        return $errors;
    }

    if (email_exists($email)) {
        $errors->add('error', __('Email already registered.', 'vendor-space'));
        return $errors;
    }

    $password = isset($_POST['password']) ? wc_clean(wp_unslash($_POST['password'])) : '';
    $password2 = isset($_POST['password2']) ? wc_clean(wp_unslash($_POST['password2'])) : '';
    if ($password === '' || $password2 === '') {
        $errors->add('error', __('Please enter and confirm your password.', 'vendor-space'));
    } elseif ($password !== $password2) {
        $errors->add('error', __('Passwords do not match.', 'vendor-space'));
    }

    $pending_payload = vs_registration_build_pending_payload($username, $email);
    if ($pending_payload['account_type'] === 'customer' && $pending_payload['display_name'] === '') {
        $errors->add('error', __('Please enter your display name.', 'vendor-space'));
    }
    if ($pending_payload['account_type'] === 'vendor' && $pending_payload['shop_name'] === '') {
        $errors->add('error', __('Please enter a shop name.', 'vendor-space'));
    }

    if ($errors->get_error_codes()) {
        return $errors;
    }

   // ✅ FIX: Reuse existing valid OTP session for this email instead of regenerating
    $existing_token = vs_registration_otp_get_token();
    if ( $existing_token !== '' ) {
        $existing_pending = vs_registration_otp_get( $existing_token );
        if (
            $existing_pending &&
            isset( $existing_pending['email'] ) &&
            sanitize_email( $existing_pending['email'] ) === $email &&
            ( $existing_pending['expires_at'] ?? 0 ) > current_time('timestamp')
        ) {
            vs_otp_log( 'Reusing existing OTP session for email', $email );
            $errors->add( 'vs_pending', ' ' );
            return $errors;
        }
    }

    // Generate Token and OTP
    $token = wp_generate_password(32, false, false);
    $otp   = (string) random_int(1000, 9999);
    $now   = current_time('timestamp');

    $pending = $pending_payload + [
        'token'              => $token,
        'otp'                => $otp,
        'attempts_left'      => vs_registration_otp_max_attempts(),
        'created_at'         => $now,
        'expires_at'         => $now + vs_registration_otp_lifetime(),
        'resend_available_at'=> $now + vs_registration_otp_resend_delay(),
        'signature'          => vs_registration_payload_signature($pending_payload),
    ];

    vs_otp_log('Generated OTP for registration', ['token' => $token, 'email' => $email]);

    if (defined('WP_DEBUG') && WP_DEBUG) {
        error_log('VS TEST: OTP generated for ' . $email);
    }

    vs_otp_log('Triggering new registration OTP', ['email' => $email, 'token' => $token]);

    // Store in transient and set cookie
    vs_registration_otp_store($pending, $token);
    vs_registration_otp_set_token($token);

    if (!vs_registration_send_otp_email($pending)) {
        $errors->add('error', __('We could not send the verification code right now. Please try again.', 'vendor-space'));
        return $errors;
    }

    // Add a dummy error to stop WooCommerce from creating the user immediately
    $errors->add('vs_pending', ' ');
    return $errors;
}

/**
 * Get the modal UI state
 */
function vs_registration_get_modal_state() {
    $token = vs_registration_otp_get_token();
    if ($token === '') {
        return null;
    }

    $pending = vs_registration_otp_get($token);
    if (!$pending) {
        vs_otp_log('Modal state requested but no pending data for token', $token);
        vs_registration_otp_clear();
        return null;
    }

    $now = current_time('timestamp');

    return [
        'token' => $token,
        'email_masked' => sanitize_email($pending['email'] ?? ''),
        'attempts_left' => (int) ($pending['attempts_left'] ?? vs_registration_otp_max_attempts()),
        'expires_in' => max(0, (int) (($pending['expires_at'] ?? 0) - $now)),
        'resend_in' => max(0, (int) (($pending['resend_available_at'] ?? 0) - $now)),
        'nonce' => wp_create_nonce('vs_registration_otp'),
        'ajax_url' => admin_url('admin-ajax.php'),
        'redirect' => wc_get_page_permalink('myaccount'),
    ];
}

add_action('wp_footer', function () {
    $otp_state = vs_registration_get_modal_state();
    if (!$otp_state) {
        return;
    }
    ?>
    <div class="vs-otp-overlay" id="vs-registration-otp-overlay">
        <div class="vs-otp-card" id="vs-registration-otp-card">
            <button type="button" class="vs-otp-close" id="vs-registration-otp-close" aria-label="<?php echo esc_attr__('Close', 'vendor-space'); ?>">&times;</button>
            <div class="vs-otp-badge"><?php echo esc_html__('Secure verification', 'vendor-space'); ?></div>
            <h2><?php echo esc_html__('Verify your email', 'vendor-space'); ?></h2>
            <p class="vs-otp-subtitle">
                <?php echo esc_html__('Enter the 4-digit code sent to:', 'vendor-space'); ?>
                <strong><?php echo esc_html($otp_state['email_masked']); ?></strong>
            </p>

            <div class="vs-otp-inputs">
                <?php for ($i = 0; $i < 4; $i++): ?>
                    <input type="text" inputmode="numeric" pattern="[0-9]*" maxlength="1" class="vs-otp-digit" data-index="<?php echo esc_attr((string) $i); ?>" autocomplete="one-time-code">
                <?php endfor; ?>
            </div>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js"></script>

            <div class="vs-otp-meta">
                <span id="vs-registration-otp-attempts"><?php echo esc_html(sprintf(__('Attempts left: %d', 'vendor-space'), $otp_state['attempts_left'])); ?></span>
                <span id="vs-registration-otp-timer"><?php echo esc_html(sprintf(__('Expires in %s', 'vendor-space'), gmdate('i:s', $otp_state['expires_in']))); ?></span>
            </div>

            <div class="vs-otp-message" id="vs-registration-otp-message" aria-live="polite"></div>

            <div class="vs-otp-actions">
                <button type="button" class="vs-otp-resend" id="vs-registration-otp-resend" disabled>
                    <?php echo esc_html__('Resend code', 'vendor-space'); ?>
                </button>
                <span class="vs-otp-resend-note" id="vs-registration-otp-resend-note"></span>
            </div>
        </div>
    </div>

    <style>
    .vs-otp-overlay{position:fixed;inset:0;background:rgba(15,23,42,.62);backdrop-filter:blur(3px);display:flex;align-items:center;justify-content:center;padding:18px;z-index:99999}
    .vs-otp-card{width:100%;max-width:460px;background:#fff;border-radius:24px;padding:28px;box-shadow:0 30px 80px rgba(15,23,42,.28);position:relative;text-align:center;border:1px solid rgba(148,163,184,.2)}
    .vs-otp-close{position:absolute;top:12px;right:14px;border:none;background:transparent;font-size:28px;line-height:1;color:#94a3b8;cursor:pointer}
    .vs-otp-close:hover{color:#0f172a}
    .vs-otp-badge{display:inline-flex;padding:8px 12px;border-radius:999px;background:#eff6ff;color:#1d4ed8;font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}
    .vs-otp-card h2{margin:16px 0 10px;font-size:30px;line-height:1.2;color:#0f172a}
    .vs-otp-subtitle{margin:0;color:#475569;line-height:1.8}
    .vs-otp-inputs{display:flex;justify-content:center;gap:12px;margin:24px 0 18px}
    .vs-otp-digit{width:62px;height:68px;border:1px solid #cbd5e1;border-radius:18px;text-align:center;font-size:28px;font-weight:700;color:#0f172a;background:#f8fafc;transition:.2s}
    .vs-otp-digit:focus{outline:none;border-color:#2563eb;box-shadow:0 0 0 4px rgba(37,99,235,.15);background:#fff}
    .vs-otp-card.is-error .vs-otp-digit{border-color:#ef4444;background:#fef2f2}
    .vs-otp-card.is-success .vs-otp-digit{border-color:#10b981;background:#ecfdf5}
    .vs-otp-meta{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;font-size:13px;color:#64748b;margin-bottom:16px}
    .vs-otp-message{min-height:24px;font-size:14px;font-weight:500;color:#475569;line-height:1.6;margin-top:8px}
    .vs-otp-message strong{display:block;font-size:18px;color:#0f172a;margin-bottom:4px}
    .vs-otp-message.is-error{color:#dc2626}
    .vs-otp-message.is-success{background:#f0fdf4;padding:12px;border-radius:12px;border:1px solid #bbf7d0}
    .vs-otp-message.is-success strong{color:#065f46}
    .vs-otp-actions{display:flex;justify-content:center;align-items:center;gap:10px;flex-wrap:wrap;margin-top:16px}
    .vs-otp-resend{border:none;border-radius:12px;background:#2563eb;color:#fff;padding:12px 18px;font-weight:600;cursor:pointer;transition:.2s}
    .vs-otp-resend:hover:not(:disabled){background:#1d4ed8;transform:translateY(-1px)}
    .vs-otp-resend:disabled{background:#cbd5e1;cursor:not-allowed}
    .vs-otp-resend-note{font-size:13px;color:#64748b}
    .vs-otp-card.is-shaking{animation:vsOtpShake .35s linear}
    @keyframes vsOtpShake{0%,100%{transform:translateX(0)}25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
    @media (max-width: 520px){.vs-otp-card{padding:24px 18px;border-radius:20px}.vs-otp-digit{width:54px;height:60px;font-size:24px}}
    </style>

    <script>
    document.addEventListener('DOMContentLoaded', function () {
        const overlay = document.getElementById('vs-registration-otp-overlay');
        if (!overlay) {
            return;
        }

        const state = <?php echo wp_json_encode($otp_state); ?>;
        const card = document.getElementById('vs-registration-otp-card');
        const closeButton = document.getElementById('vs-registration-otp-close');
        const messageBox = document.getElementById('vs-registration-otp-message');
        const attemptsBox = document.getElementById('vs-registration-otp-attempts');
        const timerBox = document.getElementById('vs-registration-otp-timer');
        const resendButton = document.getElementById('vs-registration-otp-resend');
        const resendNote = document.getElementById('vs-registration-otp-resend-note');
        const inputs = Array.from(document.querySelectorAll('.vs-otp-digit'));
        let expiresIn = Number(state.expires_in || 0);
        let resendIn = Number(state.resend_in || 0);
        let busy = false;
        let closed = false;

        const normalizeDigits = (value) => value
            .replace(/[٠-٩]/g, d => '٠١٢٣٤٥٦٧٨٩'.indexOf(d))
            .replace(/[۰-۹]/g, d => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d))
            .replace(/\D/g, '');

        const formatTime = (seconds) => {
            const safe = Math.max(0, Number(seconds || 0));
            const minutes = String(Math.floor(safe / 60)).padStart(2, '0');
            const secs = String(safe % 60).padStart(2, '0');
            return `${minutes}:${secs}`;
        };

        const setMessage = (text, type = '') => {
            messageBox.innerHTML = text || '';
            messageBox.className = 'vs-otp-message' + (type ? ` is-${type}` : '');
            card.classList.toggle('is-error', type === 'error');
            card.classList.toggle('is-success', type === 'success');
            if (type === 'error') {
                card.classList.add('is-shaking');
                setTimeout(() => card.classList.remove('is-shaking'), 400);
            }
        };

        const getOtp = () => inputs.map(input => input.value).join('');

        const clearInputs = () => {
            inputs.forEach(input => {
                input.value = '';
            });
            inputs[0].focus();
        };

        const closeModal = () => {
            closed = true;
            overlay.style.display = 'none';
        };

        const updateTimerUi = () => {
            timerBox.textContent = expiresIn > 0
                ? `<?php echo esc_js(__('Expires in', 'vendor-space')); ?> ${formatTime(expiresIn)}`
                : `<?php echo esc_js(__('Code expired', 'vendor-space')); ?>`;

            if (resendIn > 0) {
                resendButton.disabled = true;
                resendNote.textContent = `<?php echo esc_js(__('Resend available in', 'vendor-space')); ?> ${formatTime(resendIn)}`;
            } else {
                resendButton.disabled = busy;
                resendNote.textContent = `<?php echo esc_js(__('Need a new code?', 'vendor-space')); ?>`;
            }
        };

        const tick = () => {
            if (closed) {
                return;
            }
            if (expiresIn > 0) {
                expiresIn -= 1;
            }
            if (resendIn > 0) {
                resendIn -= 1;
            }
            updateTimerUi();
        };

        const request = (action, extra = {}) => fetch(state.ajax_url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
            body: new URLSearchParams({
                action,
                nonce: state.nonce,
                token: state.token,
                ...extra
            })
        }).then(async (response) => {
            const data = await response.json();
            return data && typeof data === 'object' ? data : {};
        });

        const verifyOtp = () => {
            const otp = getOtp();
            if (busy || otp.length !== 4) {
                return;
            }

            busy = true;
            resendButton.disabled = true;
            setMessage('<?php echo esc_js(__('Verifying code...', 'vendor-space')); ?>');

            request('vs_verify_otp', { otp })
                .then((response) => {
                    busy = false;
                    const payload = response.data || {};

                    if (response.success) {
                        // If the account is a pending vendor, show a SweetAlert informing them
                        if (payload.is_pending) {
                            // First hide the OTP overlay completely, then show SweetAlert on top
                            overlay.style.display = 'none';
                            closed = true;
                            // Small delay to ensure overlay is hidden before Swal renders
                            setTimeout(() => {
                                Swal.fire({
                                    title: '<?php echo esc_js(__('Your request has been received!', 'vendor-space')); ?>',
                                    html: (payload.message || '<?php echo esc_js(__('Verification code confirmed. Please wait until your request is approved by the administrator.', 'vendor-space')); ?>'),
                                    icon: 'info',
                                    confirmButtonText: '<?php echo esc_js(__('Ok', 'vendor-space')); ?>',
                                    allowOutsideClick: false,
                                    allowEscapeKey: false
                                }).then(() => {
                                    window.location.href = payload.redirect || state.redirect;
                                });
                            }, 100);
                            return;
                        }

                        setMessage(payload.message || '<?php echo esc_js(__('Verification successful. Redirecting...', 'vendor-space')); ?>', 'success');
                        setTimeout(() => {
                            window.location.href = payload.redirect || state.redirect;
                        }, 700);
                        return;
                    }

                    attemptsBox.textContent = `<?php echo esc_js(__('Attempts left:', 'vendor-space')); ?> ${payload.attempts_left ?? 0}`;
                    if (typeof payload.expires_in !== 'undefined') {
                        expiresIn = Number(payload.expires_in || 0);
                    }
                    if (typeof payload.resend_in !== 'undefined') {
                        resendIn = Number(payload.resend_in || 0);
                    }
                    setMessage(payload.message || '<?php echo esc_js(__('Invalid OTP.', 'vendor-space')); ?>', 'error');
                    clearInputs();
                    updateTimerUi();
                })
                .catch(() => {
                    busy = false;
                    setMessage('<?php echo esc_js(__('Unexpected server error. Please try again.', 'vendor-space')); ?>', 'error');
                    updateTimerUi();
                });
        };

        inputs.forEach((input, index) => {
            input.addEventListener('input', () => {
                input.value = normalizeDigits(input.value).slice(0, 1);
                if (input.value && inputs[index + 1]) {
                    inputs[index + 1].focus();
                }
                setMessage('');
                if (getOtp().length === 4) {
                    verifyOtp();
                }
            });

            input.addEventListener('keydown', (event) => {
                if (event.key === 'Backspace' && !input.value && inputs[index - 1]) {
                    inputs[index - 1].focus();
                }
                if (event.key === 'ArrowLeft' && inputs[index - 1]) {
                    inputs[index - 1].focus();
                }
                if (event.key === 'ArrowRight' && inputs[index + 1]) {
                    inputs[index + 1].focus();
                }
            });

            input.addEventListener('paste', (event) => {
                event.preventDefault();
                const pasted = normalizeDigits((event.clipboardData || window.clipboardData).getData('text')).slice(0, 4).split('');
                inputs.forEach((field, fieldIndex) => {
                    field.value = pasted[fieldIndex] || '';
                });
                const firstEmpty = inputs.find(field => !field.value);
                (firstEmpty || inputs[3]).focus();
                if (getOtp().length === 4) {
                    verifyOtp();
                }
            });
        });

        resendButton.addEventListener('click', () => {
            if (busy || resendIn > 0) {
                return;
            }

            busy = true;
            resendButton.disabled = true;
            setMessage('<?php echo esc_js(__('Sending a new code...', 'vendor-space')); ?>');

            request('vs_resend_otp')
                .then((response) => {
                    busy = false;
                    const payload = response.data || {};

                    if (!response.success) {
                        setMessage(payload.message || '<?php echo esc_js(__('Could not resend the code.', 'vendor-space')); ?>', 'error');
                        if (typeof payload.resend_in !== 'undefined') {
                            resendIn = Number(payload.resend_in || 0);
                        }
                        if (typeof payload.expires_in !== 'undefined') {
                            expiresIn = Number(payload.expires_in || 0);
                        }
                        updateTimerUi();
                        return;
                    }

                    expiresIn = Number(payload.expires_in || 0);
                    resendIn = Number(payload.resend_in || 0);
                    attemptsBox.textContent = `<?php echo esc_js(__('Attempts left:', 'vendor-space')); ?> ${payload.attempts_left ?? 0}`;
                    clearInputs();
                    setMessage(payload.message || '<?php echo esc_js(__('A new code has been sent.', 'vendor-space')); ?>', 'success');
                    updateTimerUi();
                })
                .catch(() => {
                    busy = false;
                    setMessage('<?php echo esc_js(__('Unexpected server error. Please try again.', 'vendor-space')); ?>', 'error');
                    updateTimerUi();
                });
        });

        closeButton.addEventListener('click', closeModal);
        overlay.addEventListener('click', (event) => {
            if (event.target === overlay) {
                closeModal();
            }
        });

        inputs[0].focus();
        updateTimerUi();
        window.setInterval(tick, 1000);
    });
    </script>
    <?php
});

// --- AJAX Handlers ---

add_action('wp_ajax_nopriv_vs_verify_otp', 'vs_verify_otp');
function vs_verify_otp() {
   $token = isset($_POST['token']) ? sanitize_text_field(wp_unslash($_POST['token'])) : '';
if (empty($token) || strlen($token) < 20) {
    wp_send_json_error(['message' => __('Security verification failed. Please try again.', 'vendor-space')]);
}
    $token = isset($_POST['token']) ? sanitize_text_field(wp_unslash($_POST['token'])) : '';
    $otp = isset($_POST['otp']) ? vs_normalize_otp_digits(wp_unslash($_POST['otp'])) : '';
    
    vs_otp_log('AJAX Verify OTP Start', ['token' => $token, 'provided_otp' => $otp]);

    $pending = vs_registration_otp_get($token);

    if (!$pending) {
        vs_otp_log('Verify Failed: Session/Transient expired or invalid token', $token);
        vs_otp_log('Attempted to retrieve transient', ['token' => $token, 'transient_key' => vs_registration_otp_transient_key($token)]);
        vs_registration_otp_clear();
        wp_send_json_error([
            'message' => __('Your verification session expired. Please register again.', 'vendor-space'),
            'expired' => true,
        ]);
    }
    
    // تسجيل البيانات المسترجعة
    vs_otp_log('Retrieved pending data from transient', [
        'account_type' => $pending['account_type'] ?? 'customer',
        'shop_name' => $pending['shop_name'] ?? '',
        'display_name' => $pending['display_name'] ?? '',
    ]);

    $now = current_time('timestamp');

    if ($otp === '' || strlen($otp) !== 4) {
        wp_send_json_error([
            'message' => __('Please enter the 4-digit code.', 'vendor-space'),
            'attempts_left' => (int) ($pending['attempts_left'] ?? 0),
            'expires_in' => max(0, (int) (($pending['expires_at'] ?? 0) - $now)),
            'resend_in' => max(0, (int) (($pending['resend_available_at'] ?? 0) - $now)),
        ]);
    }

    if (($pending['expires_at'] ?? 0) < $now) {
        vs_otp_log('Verify Failed: OTP Expired', ['expires_at' => $pending['expires_at'], 'now' => $now]);
        vs_registration_otp_clear($token);
        wp_send_json_error([
            'message' => __('This code has expired. Request a new one to continue.', 'vendor-space'),
            'expired' => true,
        ]);
    }

    if (empty($pending['otp_hash']) && isset($pending['otp'])) {
        $pending['otp_hash'] = vs_registration_otp_hash(vs_normalize_otp_digits($pending['otp']));
    }

    $provided_hash = vs_registration_otp_hash($otp);
    $expected_hash = trim((string) ($pending['otp_hash'] ?? ''));

    vs_otp_log('OTP Comparison Debug', [
        'has_expected_hash' => $expected_hash !== '',
        'provided_normalized' => $otp,
        'length_provided' => strlen($otp),
        'hash_equals_result' => ($expected_hash !== '' && hash_equals($expected_hash, $provided_hash)) ? 'TRUE' : 'FALSE'
    ]);

    if ($expected_hash === '' || $otp === '' || !hash_equals($expected_hash, $provided_hash)) {
        vs_otp_log('Verify Failed: OTP Mismatch', ['provided' => $otp]);
        $pending['attempts_left'] = max(0, (int) ($pending['attempts_left'] ?? 0) - 1);
        vs_registration_otp_store($pending, $token);

        if ($pending['attempts_left'] <= 0) {
            vs_otp_log('Verify Failed: Max attempts reached', $token);
            vs_registration_otp_clear($token);
            wp_send_json_error([
                'message' => __('Too many incorrect attempts. Please start registration again.', 'vendor-space'),
                'attempts_left' => 0,
                'expired' => true,
            ]);
        }

        wp_send_json_error([
            'message' => __('Invalid OTP. Please try again.', 'vendor-space'),
            'attempts_left' => (int) $pending['attempts_left'],
            'expires_in' => max(0, (int) (($pending['expires_at'] ?? 0) - $now)),
            'resend_in' => max(0, (int) (($pending['resend_available_at'] ?? 0) - $now)),
        ]);
    }

 // Success Path
$display_name = !empty($pending['display_name']) ? $pending['display_name'] : $pending['username'];
vs_otp_log('Verify Success! Creating user...', $pending['email']);

// Validate required vendor data
$account_type = $pending['account_type'] ?? 'customer';
if ($account_type === 'vendor' && empty($pending['shop_name'])) {
    vs_otp_log('Vendor verification failed: Missing shop_name', $pending['email']);
    wp_send_json_error([
        'message' => __('Store name is required for vendor accounts.', 'vendor-space'),
        'attempts_left' => (int) ($pending['attempts_left'] ?? 0),
    ]);
}

$user_id = vs_registration_create_user_from_pending($pending);
if (is_wp_error($user_id)) {
    vs_otp_log('User creation error: ' . $user_id->get_error_message(), $pending['email']);
    wp_send_json_error(['message' => $user_id->get_error_message()]);
}

vs_otp_log('User created successfully: ' . $user_id, $pending['email']);
vs_registration_otp_clear($token);

$approval_required = VS_Admin_Settings::get_option('vendors', 'manual_vendor_approval', 'yes') === 'yes';
$is_pending_vendor = ($account_type === 'vendor' && $approval_required);

if (!$is_pending_vendor) {

    wp_set_current_user($user_id);
    wp_set_auth_cookie($user_id, true);

    if ($account_type === 'vendor') {
        $msg = sprintf(
            '<strong>%s</strong><br>Welcome %s,<br>Your store is now active and ready to operate. Welcome to our vendor community!',
            esc_html__('Welcome', 'vendor-space'),
            esc_html($display_name)
        );
    } else {
        $msg = sprintf(
            '<strong>%s</strong><br>Welcome %s,<br>You are now a new member of our marketplace. Enjoy your shopping experience!',
            esc_html__('Welcome to the marketplace', 'vendor-space'),
            esc_html($display_name)
        );
    }

    wp_send_json_success([
        'message' => $msg,
        'redirect' => wc_get_page_permalink('myaccount'),
    ]);

} else {

    // Pending vendor state message
    $msg = sprintf(
        '<strong>%s</strong><br>Welcome %s,<br>Your vendor account request has been received and is under review by our team. You will receive an email notification once your account is approved.',
        esc_html__('Request Received!', 'vendor-space'),
        esc_html($display_name)
    );

    wp_send_json_success([
        'message' => $msg,
        'redirect' => wc_get_page_permalink('myaccount') . '?registration=pending',
        'is_pending' => true,
    ]);
}
}

add_action('wp_ajax_nopriv_vs_resend_otp', 'vs_resend_otp');
function vs_resend_otp() {
    // التحقق من nonce بدون wp_die
    $token_check = isset($_POST['token']) ? sanitize_text_field(wp_unslash($_POST['token'])) : '';
if (empty($token_check) || strlen($token_check) < 20) {
    wp_send_json_error(['message' => __('Security verification failed. Please try again.', 'vendor-space')]);
}
    $token = isset($_POST['token']) ? sanitize_text_field(wp_unslash($_POST['token'])) : '';
    $pending = vs_registration_otp_get($token);

    if (!$pending) {
        vs_registration_otp_clear();
        wp_send_json_error([
            'message' => __('Your verification session expired. Please register again.', 'vendor-space'),
            'expired' => true,
        ]);
    }

    $now = current_time('timestamp');
    $resend_in = max(0, (int) (($pending['resend_available_at'] ?? 0) - $now));
    
    if ($resend_in > 0) {
        wp_send_json_error([
            'message' => __('Please wait a little before requesting another code.', 'vendor-space'),
            'resend_in' => $resend_in,
            'expires_in' => max(0, (int) (($pending['expires_at'] ?? 0) - $now)),
            'attempts_left' => (int) ($pending['attempts_left'] ?? 0),
        ]);
    }

    // Update payload with new code and fresh expiry
    $pending['otp'] = (string) random_int(1000, 9999);
    $pending['attempts_left'] = vs_registration_otp_max_attempts();
    $pending['created_at'] = $now;
    $pending['expires_at'] = $now + vs_registration_otp_lifetime();
    $pending['resend_available_at'] = $now + vs_registration_otp_resend_delay();

    vs_registration_otp_store($pending, $token);
    vs_otp_log('Resending OTP code', ['email' => $pending['email']]);

    if (!vs_registration_send_otp_email($pending)) {
        wp_send_json_error([
            'message' => __('We could not resend the code right now.', 'vendor-space'),
            'resend_in' => 0,
            'expires_in' => max(0, (int) (($pending['expires_at'] ?? 0) - $now)),
            'attempts_left' => (int) $pending['attempts_left'],
        ]);
    }

    wp_send_json_success([
        'message' => __('A new verification code has been sent.', 'vendor-space'),
        'resend_in' => vs_registration_otp_resend_delay(),
        'expires_in' => vs_registration_otp_lifetime(),
        'attempts_left' => (int) $pending['attempts_left'],
    ]);
}
