/**
 * SiteStaffr Setup Wizard JavaScript
 *
 * Handles wizard navigation, validation, plan selection,
 * website scan / description generation, and AJAX form submission.
 *
 * All PHP-injected values come from window.sitestaffrWizardData
 * (set via wp_localize_script in class-sitestaffr-admin.php).
 *
 * @package    SiteStaffr
 * @subpackage SiteStaffr/admin/js
 * @since      1.0.0
 */

(function() {
    'use strict';

    var d = window.sitestaffrWizardData;
    if (!d) {
        return;
    }

    document.addEventListener('DOMContentLoaded', function() {

        try {

        // Wizard state
        var currentStep  = 1;
        var totalSteps   = 3;
        var selectedPlan = null;

        /**
         * Ensure the site is registered with the middleware before proceeding.
         * On failure, still invokes the callback so the user can advance
         * (description gen will show its own error).
         */
        function ensureSiteRegistered(callback) {
            var formData = new FormData();
            formData.append('action', 'sitestaffr_wizard_register_site');
            formData.append('nonce', document.getElementById('sitestaffr_wizard_nonce').value);

            var xhr = new XMLHttpRequest();
            xhr.open('POST', d.ajaxUrl, true);
            xhr.onload = function() {
                if (xhr.status === 200) {
                    try {
                        var response = JSON.parse(xhr.responseText);
                        if (response.success) {
                            callback();
                            return;
                        }
                    } catch (e) {}
                }
                // Registration failed — still advance but description gen may fail with a clear error
                console.warn('SiteStaffr: Site registration failed, advancing anyway');
                callback();
            };
            xhr.onerror = function() {
                console.warn('SiteStaffr: Site registration request failed');
                callback();
            };
            xhr.send(formData);
        }

        // DOM elements
        var btnNext       = document.getElementById('btn-next');
        var wizardNav     = document.getElementById('wizard-nav');
        var backToStep1Btn = document.getElementById('back-to-step-1');
        var backToStep2Btn = document.getElementById('back-to-step-2');
        var loadingOverlay = document.getElementById('loading-overlay');

        // ===================================================================
        // Init
        // ===================================================================

        initializeWizard();

        // If returning from Stripe Checkout, auto-advance to Step 3.
        if (d.checkoutComplete === '1') {
            selectedPlan = 'paid';
            ensureSiteRegistered(function() { goToStep(3); });
        }

        function initializeWizard() {
            for (var i = 1; i <= totalSteps; i++) {
                var step = document.getElementById('wizard-step-' + i);
                if (step) {
                    step.style.display = 'none';
                    step.classList.remove('active');
                }
            }

            var step1 = document.getElementById('wizard-step-1');
            if (step1) {
                step1.style.display = 'block';
                step1.classList.add('active');
            }

            updateProgressBar();
            updateNavButtons();

            var firstInput = document.getElementById('business_name');
            if (firstInput) {
                firstInput.focus();
            }
        }

        // ===================================================================
        // Navigation
        // ===================================================================

        function goToStep(step) {
            for (var i = 1; i <= totalSteps; i++) {
                var stepEl = document.getElementById('wizard-step-' + i);
                if (stepEl) {
                    stepEl.style.display = 'none';
                    stepEl.classList.remove('active');
                }
            }

            var targetStep = document.getElementById('wizard-step-' + step);
            if (targetStep) {
                targetStep.style.display = 'block';
                targetStep.classList.add('active');
            }

            currentStep = step;
            updateProgressBar();
            updateNavButtons();

            // Step 2: hide nav (plan cards are the action)
            if (step === 2) {
                if (wizardNav) wizardNav.style.display = 'none';
            }

            // Step 3: hide nav (custom buttons handle completion)
            if (step === 3) {
                if (wizardNav) wizardNav.style.display = 'none';
            }

            // Scroll wizard container into view
            var container = document.querySelector('.sitestaffr-wizard-container');
            if (container) {
                container.scrollIntoView({ behavior: 'smooth', block: 'start' });
            }
        }

        function updateProgressBar() {
            var progress = (currentStep / totalSteps) * 100;
            var progressFill = document.getElementById('progress-fill');
            if (progressFill) {
                progressFill.style.width = progress + '%';
            }

            var currentStepText = document.getElementById('current-step');
            if (currentStepText) {
                currentStepText.textContent = currentStep;
            }

            for (var i = 1; i <= totalSteps; i++) {
                var indicator = document.getElementById('step-indicator-' + i);
                if (indicator) {
                    indicator.classList.remove('active', 'completed');
                    if (i < currentStep) {
                        indicator.classList.add('completed');
                    } else if (i === currentStep) {
                        indicator.classList.add('active');
                    }
                }
            }
        }

        function updateNavButtons() {
            if (currentStep === 1) {
                if (btnNext) {
                    btnNext.innerHTML = d.i18n.next + ' <span class="dashicons dashicons-arrow-right-alt"></span>';
                    btnNext.disabled = false;
                }
                if (wizardNav) wizardNav.style.display = 'flex';
            } else {
                // Steps 2 and 3 hide the default nav
                if (wizardNav) wizardNav.style.display = 'none';
            }
        }

        // ===================================================================
        // Step 1: Validation & Next
        // ===================================================================

        function validateStep1() {
            clearErrors();

            var businessName  = document.getElementById('business_name').value.trim();
            var businessPhone = document.getElementById('business-phone-step1').value.trim();

            if (!businessName) {
                showError('business_name', d.i18n.businessNameRequired);
                return false;
            }

            // Phone is optional and format-flexible (international-friendly):
            // when provided, just sanity-check it has enough digits.
            if (businessPhone) {
                var phoneDigits = businessPhone.replace(/\D/g, '');
                if (phoneDigits.length < 7) {
                    showError('business-phone-step1', d.i18n.invalidPhone);
                    return false;
                }
            }

            var businessEmail = document.getElementById('business-email-step1').value.trim();
            if (!businessEmail) {
                showError('business-email-step1', 'Business email is required.');
                return false;
            }
            if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(businessEmail)) {
                showError('business-email-step1', 'Please enter a valid email address.');
                return false;
            }

            return true;
        }

        function showError(fieldId, message) {
            var field = document.getElementById(fieldId);
            if (field) {
                field.classList.add('sitestaffr-error');
                var errorEl = document.createElement('span');
                errorEl.className = 'sitestaffr-error-msg';
                errorEl.textContent = message;
                field.parentNode.appendChild(errorEl);
            }
        }

        function clearErrors() {
            var errorFields = document.querySelectorAll('.sitestaffr-error');
            errorFields.forEach(function(field) {
                field.classList.remove('sitestaffr-error');
            });
            var errorMsgs = document.querySelectorAll('.sitestaffr-error-msg');
            errorMsgs.forEach(function(msg) {
                msg.remove();
            });
        }

        // Save Step 1 data via AJAX, then advance to Step 2
        function saveStep1Data() {
            var businessName       = document.getElementById('business_name').value.trim();
            var businessPhoneField = document.getElementById('business-phone-step1');
            var businessPhone      = businessPhoneField ? businessPhoneField.value.trim() : '';

            var formData = new FormData();
            formData.append('action', 'sitestaffr_save_wizard');
            formData.append('nonce', document.getElementById('sitestaffr_wizard_nonce').value);
            formData.append('wizard_complete', '0');
            formData.append('business_name', businessName);
            if (businessPhone) {
                formData.append('business_phone_step1', businessPhone);
            }

            var businessEmail = document.getElementById('business-email-step1').value.trim();
            if (businessEmail) {
                formData.append('business_email', businessEmail);
            }

            var xhr = new XMLHttpRequest();
            xhr.open('POST', d.ajaxUrl, true);

            xhr.onload = function() {
                if (xhr.status === 200 || xhr.status === 304) {
                    try {
                        var response = JSON.parse(xhr.responseText);
                        if (response.success) {
                            ensureSiteRegistered(function() {
                                goToStep(2);
                                maybeStartBackgroundScan();
                            });
                        } else {
                            alert(d.i18n.saveError);
                        }
                    } catch (e) {
                        // Still advance if response parsing fails
                        ensureSiteRegistered(function() {
                            goToStep(2);
                            maybeStartBackgroundScan();
                        });
                    }
                } else {
                    alert(d.i18n.saveError);
                }
            };

            xhr.onerror = function() {
                alert(d.i18n.connectionError);
            };

            xhr.send(formData);
        }

        // Next button — only active on Step 1
        if (btnNext) {
            btnNext.addEventListener('click', function(e) {
                e.preventDefault();
                if (currentStep === 1 && validateStep1()) {
                    saveStep1Data();
                }
            });
        }

        // Back navigation is unified on the per-step back links (the old
        // global Previous button was a duplicate and is gone from the markup).

        // ===================================================================
        // Step 2: Plan Selection
        // ===================================================================

        function startHostedCheckout(plan) {
            var formData = new FormData();
            formData.append('action', 'sitestaffr_create_wizard_checkout');
            formData.append('nonce', document.getElementById('sitestaffr_wizard_nonce').value);
            formData.append('plan_name', plan);

            loadingOverlay.style.display = 'flex';

            var xhr = new XMLHttpRequest();
            xhr.open('POST', d.ajaxUrl, true);

            xhr.onload = function() {
                loadingOverlay.style.display = 'none';

                if (xhr.status !== 200) {
                    alert(d.i18n.checkoutFailed);
                    return;
                }

                var response = null;
                try {
                    response = JSON.parse(xhr.responseText);
                } catch (e) {
                    alert(d.i18n.checkoutUnexpected);
                    return;
                }

                if (response && response.success && response.data && response.data.checkoutUrl) {
                    window.location.href = response.data.checkoutUrl;
                    return;
                }

                var msg = (response && response.data && response.data.message)
                    ? response.data.message
                    : d.i18n.checkoutSessionFailed;
                alert(msg);
            };

            xhr.onerror = function() {
                loadingOverlay.style.display = 'none';
                alert(d.i18n.checkoutConnectionError);
            };

            xhr.send(formData);
        }

        // The four plan cards share one handler: the free trial just advances,
        // the paid plans go to hosted checkout.
        var planButtons = document.querySelectorAll('.sitestaffr-plan-select-btn');
        planButtons.forEach(function(btn) {
            btn.addEventListener('click', function(e) {
                e.preventDefault();
                selectedPlan = this.getAttribute('data-plan');
                if (selectedPlan === 'free') {
                    goToStep(3);
                    return;
                }
                startHostedCheckout(selectedPlan);
            });
        });

        if (backToStep1Btn) {
            backToStep1Btn.addEventListener('click', function(e) {
                e.preventDefault();
                goToStep(1);
            });
        }

        if (backToStep2Btn) {
            backToStep2Btn.addEventListener('click', function(e) {
                e.preventDefault();
                goToStep(2);
            });
        }

        // ===================================================================
        // Step 3: Completion
        // ===================================================================

        function completeWizard() {
            loadingOverlay.style.display = 'flex';

            var formData = new FormData();
            formData.append('action', 'sitestaffr_save_wizard');
            formData.append('nonce', document.getElementById('sitestaffr_wizard_nonce').value);
            formData.append('wizard_complete', '1');
            formData.append('business_name', document.getElementById('business_name').value.trim());

            var businessPhone = document.getElementById('business-phone-step1');
            if (businessPhone && businessPhone.value.trim()) {
                formData.append('business_phone_step1', businessPhone.value.trim());
            }

            var businessEmail = document.getElementById('business-email-step1');
            if (businessEmail && businessEmail.value.trim()) {
                formData.append('business_email', businessEmail.value.trim());
            }

            if (selectedPlan) {
                formData.append('selected_plan', selectedPlan);
            }

            var xhr = new XMLHttpRequest();
            xhr.open('POST', d.ajaxUrl, true);

            xhr.onload = function() {
                loadingOverlay.style.display = 'none';

                if (xhr.status === 200 || xhr.status === 304) {
                    showWizardComplete();
                } else {
                    alert(d.i18n.saveError);
                }
            };

            xhr.onerror = function() {
                loadingOverlay.style.display = 'none';
                alert(d.i18n.connectionError);
            };

            xhr.send(formData);
        }

        function showWizardComplete() {
            var stepEl = document.getElementById('wizard-step-3');
            if (stepEl) {
                // "Meet your agent" — skippable live test. The tokenized link
                // flags the session is_test_call so it stays out of stats,
                // leads, and notification emails.
                var meetAgentHtml = '';
                if (d.testWidgetUrl) {
                    meetAgentHtml =
                        '<a href="' + d.testWidgetUrl + '" target="_blank" rel="noopener" class="sitestaffr-btn-dashboard">' +
                        '<span class="dashicons dashicons-microphone"></span> ' + d.i18n.meetYourAgent +
                        '</a>' +
                        '<p class="sitestaffr-meet-agent-note">' + d.i18n.meetYourAgentNote + '</p>';
                }

                stepEl.innerHTML =
                    '<div class="sitestaffr-step-content sitestaffr-completion">' +
                    '<div class="sitestaffr-success-icon"><span class="dashicons dashicons-yes-alt"></span></div>' +
                    '<h2>' + d.i18n.allSet + '</h2>' +
                    '<p class="sitestaffr-step-description">' + d.i18n.allSetDesc + '</p>' +
                    meetAgentHtml +
                    '<a href="' + d.dashboardUrl + '" class="sitestaffr-btn-dashboard-secondary">' +
                    '<span class="sitestaffr-dashboard-link-text">' + d.i18n.skipToDashboard + '</span> <span class="dashicons dashicons-arrow-right-alt2"></span>' +
                    '</a>' +
                    '</div>';
            }
            if (wizardNav) wizardNav.style.display = 'none';

            // Update progress bar to 100%
            var progressFill = document.getElementById('progress-fill');
            if (progressFill) progressFill.style.width = '100%';

            for (var i = 1; i <= totalSteps; i++) {
                var indicator = document.getElementById('step-indicator-' + i);
                if (indicator) {
                    indicator.classList.remove('active');
                    indicator.classList.add('completed');
                }
            }
        }

        // Step-3 validation speaks inline; no native dialogs on the last step.
        var step3Error = document.getElementById('wizard-step3-error');

        function showStep3Error(message) {
            step3Error.textContent = message;
            step3Error.style.display = 'block';
            step3Error.scrollIntoView({ block: 'nearest' });
        }

        function clearStep3Error() {
            if (step3Error) step3Error.style.display = 'none';
        }

        // Save & Finish button — save enhancement data, then complete
        var saveEnhancementBtn = document.getElementById('save-enhancement');
        if (saveEnhancementBtn) {
            saveEnhancementBtn.addEventListener('click', function() {
                clearStep3Error();

                var hoursValue = '';
                var selectedHoursRadio = document.querySelector('input[name="business_hours_option"]:checked');
                if (!selectedHoursRadio) {
                    showStep3Error(d.i18n.selectHours);
                    return;
                }
                if (selectedHoursRadio.value === 'custom') {
                    hoursValue = collectScheduleData();
                } else {
                    hoursValue = selectedHoursRadio.value;
                }

                var description = '';
                var manualContainer = document.getElementById('manual-entry-option');
                var manualTextarea  = document.getElementById('business_description');
                var generatedText   = document.getElementById('generated-text');

                if (manualContainer && manualContainer.style.display !== 'none' && manualTextarea && manualTextarea.value.trim()) {
                    description = manualTextarea.value.trim();
                } else if (generatedText && generatedText.textContent.trim()) {
                    description = generatedText.textContent.trim();
                }

                // A scan still in flight must not block setup: finish with no
                // description, and the owner generates or writes one later from
                // Settings (the note under the scan says exactly that).
                if (!description && scanState !== 'running') {
                    if (manualContainer && manualContainer.style.display !== 'none') {
                        showStep3Error(d.i18n.addDescription);
                    } else {
                        showStep3Error(d.i18n.generateDescription);
                    }
                    return;
                }

                saveEnhancementBtn.disabled = true;
                loadingOverlay.style.display = 'flex';

                var xhr = new XMLHttpRequest();
                xhr.open('POST', d.ajaxUrl, true);
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

                xhr.onload = function() {
                    loadingOverlay.style.display = 'none';
                    saveEnhancementBtn.disabled = false;

                    if (xhr.status === 200) {
                        try {
                            var response = JSON.parse(xhr.responseText);
                            if (response.success) {
                                completeWizard();
                            } else {
                                alert(d.i18n.saveError);
                            }
                        } catch (e) {
                            alert(d.i18n.saveEnhancementError);
                        }
                    } else {
                        alert(d.i18n.saveEnhancementError);
                    }
                };

                xhr.onerror = function() {
                    loadingOverlay.style.display = 'none';
                    saveEnhancementBtn.disabled = false;
                    alert(d.i18n.connectionError);
                };

                var formBody = 'action=sitestaffr_save_enhancement';
                formBody += '&nonce=' + encodeURIComponent(document.getElementById('sitestaffr_wizard_nonce').value);
                formBody += '&business_hours=' + encodeURIComponent(hoursValue);
                formBody += '&business_description=' + encodeURIComponent(description);

                xhr.send(formBody);
            });
        }

        // ===================================================================
        // Phone Number Formatting
        // ===================================================================

        // Phone stays free-form (no US-only input mask — international numbers
        // are welcome). Blur just sanity-checks the digit count when non-empty.
        var phoneFieldStep1 = document.getElementById('business-phone-step1');
        if (phoneFieldStep1) {
            phoneFieldStep1.addEventListener('blur', function() {
                var phone   = this.value.replace(/\D/g, '');
                var errorEl = document.getElementById('business-phone-error');

                if (phone.length > 0 && phone.length < 7) {
                    if (errorEl) errorEl.style.display = 'block';
                    this.style.borderColor = '#d63638';
                } else {
                    if (errorEl) errorEl.style.display = 'none';
                    this.style.borderColor = '';
                }
            });
        }

        // ===================================================================
        // Schedule Builder (Step 3)
        // ===================================================================

        function generateTimeOptions() {
            var times = [];
            for (var hour = 0; hour < 24; hour++) {
                for (var min = 0; min < 60; min += 30) {
                    var displayHour = hour === 0 ? 12 : (hour > 12 ? hour - 12 : hour);
                    var ampm        = hour < 12 ? 'AM' : 'PM';
                    var displayMin  = min < 10 ? '0' + min : '' + min;
                    times.push(displayHour + ':' + displayMin + ' ' + ampm);
                }
            }
            return times;
        }

        function initScheduleBuilder() {
            var days  = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
            var times = generateTimeOptions();

            days.forEach(function(day, index) {
                var startSelect = document.querySelector('.start-time[data-day="' + day + '"]');
                var endSelect   = document.querySelector('.end-time[data-day="' + day + '"]');

                if (startSelect && endSelect) {
                    times.forEach(function(time) {
                        var opt1 = document.createElement('option');
                        opt1.value = time;
                        opt1.textContent = time;
                        startSelect.appendChild(opt1);

                        var opt2 = document.createElement('option');
                        opt2.value = time;
                        opt2.textContent = time;
                        endSelect.appendChild(opt2);
                    });

                    if (index < 5) {
                        startSelect.value = '9:00 AM';
                        endSelect.value   = '5:00 PM';
                    }
                }
            });
        }

        function toggleDayInputs(day, isOpen) {
            var timeInputs  = document.querySelector('.sitestaffr-time-inputs[data-day="' + day + '"]');
            var toggleLabel = document.querySelector('.day-open-toggle[data-day="' + day + '"] + .toggle-label');

            if (timeInputs) timeInputs.style.display = isOpen ? 'flex' : 'none';
            if (toggleLabel) toggleLabel.textContent = isOpen ? d.i18n.open : d.i18n.closed;
        }

        function attachScheduleEventListeners() {
            var toggles = document.querySelectorAll('.day-open-toggle');
            toggles.forEach(function(toggle) {
                toggle.addEventListener('change', function() {
                    toggleDayInputs(this.getAttribute('data-day'), this.checked);
                });
            });
        }

        var customHoursRadio = document.getElementById('hours_custom');
        var scheduleBuilder  = document.getElementById('schedule-builder');

        if (customHoursRadio && scheduleBuilder) {
            initScheduleBuilder();
            attachScheduleEventListeners();

            customHoursRadio.addEventListener('change', function() {
                if (this.checked) scheduleBuilder.style.display = 'block';
            });

            var otherHoursRadios = document.querySelectorAll('input[name="business_hours_option"]:not(#hours_custom)');
            otherHoursRadios.forEach(function(radio) {
                radio.addEventListener('change', function() {
                    if (this.checked) scheduleBuilder.style.display = 'none';
                });
            });
        }

        function collectScheduleData() {
            var schedule  = [];
            var days      = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
            var dayNames  = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];

            days.forEach(function(day, index) {
                var toggle = document.querySelector('.day-open-toggle[data-day="' + day + '"]');
                if (toggle && toggle.checked) {
                    var start = document.querySelector('.start-time[data-day="' + day + '"]').value;
                    var end   = document.querySelector('.end-time[data-day="' + day + '"]').value;
                    schedule.push(dayNames[index] + ': ' + start + '-' + end);
                } else {
                    schedule.push(dayNames[index] + ': Closed');
                }
            });

            return schedule.join(', ');
        }

        // ===================================================================
        // Website Scan & Manual Description Toggle
        // ===================================================================

        var manualEntry = document.getElementById('manual-entry-option');
        var generatedContainer = document.getElementById('generated-description');
        var generatedTextEl = document.getElementById('generated-text');

        // Where the identity scan stands: 'idle' | 'running' | 'done' | 'manual'.
        // While it is running the owner can still finish — see the Save & Finish
        // handler — so a slow scan never dead-ends setup.
        var scanState = 'idle';
        var syncedPageCount = 0;

        function showManualDescription(prefillFromGenerated) {
            var manualTextarea = document.getElementById('business_description');
            scanState = 'manual';
            if (generatedContainer) generatedContainer.style.display = 'none';
            if (manualEntry) manualEntry.style.display = 'block';

            if (prefillFromGenerated && generatedTextEl && manualTextarea) {
                manualTextarea.value = generatedTextEl.textContent;
            }
            if (manualTextarea) {
                manualTextarea.focus();
                updateCharCount();
            }
        }

        function showGeneratedDescription(text) {
            scanState = 'done';
            if (generatedTextEl && typeof text === 'string') {
                generatedTextEl.textContent = text;
            }
            if (manualEntry) manualEntry.style.display = 'none';
            if (generatedContainer) generatedContainer.style.display = 'block';

            // Lead with the pages, not the paragraph: owners read the paragraph as
            // "everything the AI knows" when the page count is only a caption.
            var title = document.getElementById('generated-title');
            if (title && syncedPageCount > 0) {
                title.textContent = (d.i18n.readPagesTitle || 'Your agent read %d pages of your site')
                    .replace('%d', syncedPageCount);
            }
            var source = document.getElementById('generated-source');
            if (source && syncedPageCount > 0) {
                source.textContent = (d.i18n.learnedFromPages || '')
                    .replace('%d', syncedPageCount);
            }

            // The description is clamped; only offer to expand it when there is
            // actually more to read.
            var wrap = document.getElementById('generated-text-wrap');
            var toggle = document.getElementById('btn-toggle-generated');
            if (wrap && toggle) {
                wrap.classList.add('is-clamped');
                toggle.style.display = (wrap.scrollHeight > wrap.clientHeight + 1) ? '' : 'none';
                toggle.textContent = d.i18n.readFullDescription || 'Read full description';
            }
        }

        var toggleGeneratedBtn = document.getElementById('btn-toggle-generated');
        if (toggleGeneratedBtn) {
            toggleGeneratedBtn.addEventListener('click', function() {
                var wrap = document.getElementById('generated-text-wrap');
                if (!wrap) return;
                var clamped = wrap.classList.toggle('is-clamped');
                this.textContent = clamped
                    ? (d.i18n.readFullDescription || 'Read full description')
                    : (d.i18n.showLessDescription || 'Show less');
            });
        }

        var scanBtn = document.getElementById('btn-scan-website');
        var scanHero = document.getElementById('scan-hero');
        var scanPollTimer = null;

        /**
         * The identity job runs on the SERVER (cron), so the site keeps being learned
         * even if the owner reloads, closes the tab, or quits the browser. The wizard
         * only starts it and reports its progress.
         */
        function maybeStartBackgroundScan() {
            if (scanState !== 'idle') {
                return;
            }
            triggerScan();
        }

        function identityAjax(action) {
            return new Promise(function(resolve, reject) {
                var xhr = new XMLHttpRequest();
                xhr.open('POST', d.ajaxUrl, true);
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                xhr.timeout = 30000;
                xhr.onload = function() {
                    try {
                        resolve(JSON.parse(xhr.responseText));
                    } catch (e) {
                        reject(new Error('Invalid response'));
                    }
                };
                xhr.onerror = function() { reject(new Error('Request failed')); };
                xhr.ontimeout = function() { reject(new Error('Request timed out')); };
                xhr.send('action=' + encodeURIComponent(action) + '&nonce=' + encodeURIComponent(d.identityJobNonce));
            });
        }

        function showScanProgress() {
            var showcase = document.getElementById('scan-showcase');
            if (scanHero) scanHero.style.display = 'none';
            if (showcase) showcase.style.display = 'block';
            if (scanBtn) scanBtn.disabled = true;
        }

        function renderJobProgress(job) {
            var statusText = document.getElementById('scan-status-text');
            var statusDetail = document.getElementById('scan-status-detail');
            var progressBar = document.getElementById('scan-progress-bar');

            if (progressBar) progressBar.style.width = (job.percent || 5) + '%';

            if (statusText) {
                if (job.status === 'generating') {
                    statusText.textContent = d.i18n.scanWriting || 'Writing your business description...';
                } else if (job.total > 0) {
                    statusText.textContent = (d.i18n.scanLearning || 'Learning your website: page %1 of %2...')
                        .replace('%1', Math.min(job.done + 1, job.total))
                        .replace('%2', job.total);
                } else {
                    statusText.textContent = d.i18n.scanPreparing || 'Finding your best pages...';
                }
            }
            if (statusDetail) statusDetail.textContent = job.current || '';
        }

        function handleJobFailure(job) {
            scanState = 'idle';
            var showcase = document.getElementById('scan-showcase');
            if (showcase) showcase.style.display = 'none';
            if (scanBtn) scanBtn.disabled = false;

            if (job && job.error_code === 'scan_rate_limited') {
                if (scanHero) scanHero.style.display = '';
                showStep3Error(job.error || d.i18n.scanRateLimited || 'Generation limit reached.');
                return;
            }

            // Anything else: fall back to writing it by hand, with the reason shown.
            showManualDescription(false);
            showStep3Error((job && job.error) || d.i18n.scanFailed || 'We could not learn your website automatically. Please write a short description below.');
        }

        function applyJobState(job) {
            if (!job || !job.status) return;

            if (job.status === 'done') {
                scanState = 'done';
                syncedPageCount = job.synced || 0;
                if (scanPollTimer) { clearTimeout(scanPollTimer); scanPollTimer = null; }
                if (scanBtn) scanBtn.disabled = false;
                var showcase = document.getElementById('scan-showcase');
                if (showcase) showcase.style.display = 'none';
                if (job.description) {
                    showGeneratedDescription(job.description);
                } else {
                    showManualDescription(false);
                }
                return;
            }

            if (job.status === 'failed') {
                if (scanPollTimer) { clearTimeout(scanPollTimer); scanPollTimer = null; }
                handleJobFailure(job);
                return;
            }

            // queued | syncing | generating: still working.
            scanState = 'running';
            showScanProgress();
            renderJobProgress(job);
            scheduleJobPoll();
        }

        function scheduleJobPoll() {
            if (scanPollTimer) clearTimeout(scanPollTimer);
            scanPollTimer = setTimeout(pollJob, 2500);
        }

        function pollJob() {
            identityAjax('sitestaffr_identity_job_status')
                .then(function(resp) {
                    if (resp && resp.success) {
                        applyJobState(resp.data);
                    } else {
                        scheduleJobPoll();
                    }
                })
                .catch(function() { scheduleJobPoll(); });
        }

        function triggerScan() {
            scanState = 'running';
            showScanProgress();
            renderJobProgress({ percent: 5, total: 0, done: 0, status: 'queued' });

            identityAjax('sitestaffr_start_identity_job')
                .then(function(resp) {
                    if (resp && resp.success) {
                        applyJobState(resp.data);
                    } else {
                        handleJobFailure(resp && resp.data);
                    }
                })
                .catch(function() {
                    handleJobFailure({ error: d.i18n.connectionError });
                });
        }

        // Returning to the wizard mid-job (reload, new tab, tomorrow): pick the job up
        // wherever the server has got to.
        function resumeIdentityJob() {
            identityAjax('sitestaffr_identity_job_status')
                .then(function(resp) {
                    if (!resp || !resp.success || !resp.data) return;
                    var job = resp.data;
                    if (job.status === 'idle') return;
                    if (job.status === 'done' && !job.description) return;
                    applyJobState(job);
                })
                .catch(function() {});
        }

        resumeIdentityJob();

        if (scanBtn) {
            scanBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                triggerScan();
            });
        }
        if (scanHero) {
            scanHero.addEventListener('click', function() {
                if (scanBtn && !scanBtn.disabled) triggerScan();
            });
        }


        var editBtn = document.getElementById('btn-edit-generated');
        if (editBtn) {
            editBtn.addEventListener('click', function() {
                showManualDescription(true);
            });
        }

        // ===================================================================
        // Character Counter
        // ===================================================================

        var manualDescField = document.getElementById('business_description');
        if (manualDescField) {
            manualDescField.addEventListener('input', updateCharCount);
            updateCharCount();
        }

        function updateCharCount() {
            var field          = document.getElementById('business_description');
            var charCountEl    = document.getElementById('char-count');
            var charCountWrapper = document.getElementById('char-count-wrapper');
            var maxLength      = 5000;

            if (field && charCountEl) {
                var length = field.value.length;
                charCountEl.textContent = length;

                if (charCountWrapper) {
                    if (length > maxLength) {
                        charCountWrapper.style.color = '#d63638';
                    } else if (length >= 50) {
                        charCountWrapper.style.color = '#10b981';
                    } else {
                        charCountWrapper.style.color = '#646970';
                    }
                }
            }
        }

        } catch (err) {
            console.error('SiteStaffr Setup Wizard error:', err);
        }

    }); // DOMContentLoaded

})();
