/**
 * Sign-up Form JavaScript
 * Handles multi-step form navigation and AJAX submissions
 */

(function($) {
    'use strict';

    class SignupForm {
        constructor() {
            // Get current step from PHP
            this.currentStep = parseInt($('.step-counter-text').text().match(/\d+/)[0]);
            this.totalSteps = 3;
            this.form = $('#signup-form');
            this.map = null;
            this.selectedLocation = null;
            this.countdownTimer = null;
            this.countdownStarted = false;
            this.popupShown = false; // Track if permission popup has been shown
            this.init();
        }

        init() {
            this.bindEvents();
            this.updateProgress();
            this.showCurrentStep();
            this.updateNavigationButtons();
            this.handleUserTypeChange();
            this.initializeFieldStates();
            this.initializeMap();
            this.initializeAddressSearch();
            
            // If already on completion step, start countdown
            if (this.currentStep === 4) {
                this.startCountdown();
            }
        }

        bindEvents() {
            // Form submission
            this.form.on('submit', (e) => {
                e.preventDefault();
                this.submitCurrentStep();
            });

            // Restrict Persian-only fields
            this.form.on('input', '#first_name, #last_name, #organization_name', (e) => {
                this.filterPersianInput($(e.target));
            });

            this.form.on('blur', '#first_name, #last_name, #organization_name', (e) => {
                this.validateField($(e.target));
            });

            // User type change
            $('input[name="user_type"]').on('change', () => {
                this.handleUserTypeChange();
            });

            // Input event - only update field state (no validation while typing)
            // EXCEPTION: Clear error if Persian field is now valid
            this.form.on('input', 'input, textarea', (e) => {
                const $field = $(e.target);
                this.updateFieldState($field);
                
                const fieldId = $field.attr('id');
                const value = $field.val().trim();
                
                // For Persian-only fields, clear error if field is now valid
                // (Error for non-Persian characters is shown by filterPersianInput)
                if (['first_name', 'last_name', 'organization_name'].includes(fieldId)) {
                    // Check if field is now valid (at least 3 Persian characters, no non-Persian)
                    const hasNonPersian = /[^\u0600-\u06FF\s\u200c]/g.test(value);
                    const hasNumbers = /[\u0660-\u0669\u06F0-\u06F9]/g.test(value);
                    
                    if (!hasNonPersian && !hasNumbers && value.length >= 3 && this.isPersianText(value)) {
                        // Clear error if field is valid
                        this.clearFieldError($field);
                        $field.removeClass('is-invalid');
                    }
                } else {
                    // For other fields, only clear error if field was invalid and now appears valid
                    if ($field.hasClass('is-invalid')) {
                        const isRequired = $field.attr('data-required') === 'true';
                        
                        // Clear error if not empty (for required) or if optional
                        if (!isRequired || value.length > 0) {
                            this.clearFieldError($field);
                            $field.removeClass('is-invalid');
                        }
                    }
                }
            });

            // Field state on focus/blur
            this.form.on('focus blur', 'input, textarea', (e) => {
                const $field = $(e.target);
                this.updateFieldState($field);
                
                // Validate field on blur to show errors
                if (e.type === 'blur') {
                    this.validateField($field);
                }
            });
        }

        handleUserTypeChange() {
            const userType = $('input[name="user_type"]:checked').val();
            const organizationField = $('#organization_field');
            
            if (userType === 'Lab') {
                organizationField.slideDown(300);
                $('#organization_name').attr('data-required', 'true');
            } else {
                organizationField.slideUp(300);
                $('#organization_name').removeAttr('data-required');
            }
            
            // Update step 2 content based on user type
            this.updateStep2Content();
        }

        updateStep2Content() {
            const userType = $('input[name="user_type"]:checked').val();
            const step2Element = $('.form-step[data-step="2"]');
            
            if (!step2Element.length) {
                return; // Step 2 doesn't exist yet
            }
            
            const stepTitle = step2Element.find('.step-title');
            const stepDescription = step2Element.find('.step-description');
            
            if (userType === 'Clinic') {
                stepTitle.text('اطلاعات مطب');
                stepDescription.text('لطفا نام و نام خانوادگی دنداپزشک وارد شود');
            } else if (userType === 'Lab') {
                stepTitle.text('اطلاعات لابراتوار');
                stepDescription.text('لطفا نام و نام خانوادگی مدیریت لابراتوار و نام لابراتوار وارد شود');
            } else {
                // Default text if no user type selected yet
                stepTitle.text('اطلاعات شخصی');
                stepDescription.text('نام و نام خانوادگی خود را وارد کنید');
            }
        }

        validateField($field) {
            const value = $field.val().trim();
            const isRequired = $field.attr('data-required') === 'true';
            const fieldId = $field.attr('id');
            let isValid = true;
            let errorMessage = '';

            // Check if required field is empty
            if (isRequired && value.length === 0) {
                isValid = false;
                // Get field label for better error message
                const fieldLabel = $field.closest('.form-field').find('.floating-label .label-text').text() || 
                                  $field.attr('name') || 
                                  fieldId;
                errorMessage = `فیلد ${fieldLabel} اجباری است.`;
            }

            // Validate Persian-only fields
            if (['first_name', 'last_name', 'organization_name'].includes(fieldId)) {
                if (value.length === 0) {
                    isValid = !isRequired;
                    if (isRequired && !errorMessage) {
                        const fieldLabel = $field.closest('.form-field').find('.floating-label .label-text').text() || 
                                          $field.attr('name') || 
                                          fieldId;
                        errorMessage = `فیلد ${fieldLabel} اجباری است.`;
                    }
                } else {
                    // Check minimum character length (at least 3 characters)
                    if (value.length < 3) {
                        isValid = false;
                        errorMessage = 'حداقل 3 حرف باید وارد شود.';
                    } else if (!this.isPersianText(value)) {
                        isValid = false;
                        errorMessage = 'فقط حروف فارسی مجاز است.';
                    }
                }
            }

            // Special handling for address field
            if (fieldId === 'user_address' && isRequired) {
                isValid = this.isValidAddress(value);
                if (!isValid && !errorMessage) {
                    errorMessage = 'لطفاً موقعیت خود را روی نقشه انتخاب کنید.';
                }
            }

            const wasInvalid = $field.hasClass('is-invalid');
            $field.toggleClass('is-invalid', !isValid);

            // Show or clear error message
            if (!isValid && errorMessage) {
                this.showFieldError($field, errorMessage);
            } else if (wasInvalid && isValid) {
                this.clearFieldError($field);
            }

            return isValid;
        }

        updateFieldState($field) {
            const value = $field.val().trim();
            $field.toggleClass('has-value', value.length > 0);
        }

        initializeFieldStates() {
            // Initialize field states for pre-filled values
            this.form.find('input, textarea').each((index, field) => {
                this.updateFieldState($(field));
            });
        }

        showStepSuccessMessage(completedStep) {
            // Don't show success message for completion step (step 4)
            if (completedStep === 4) {
                return;
            }

            const stepMessages = {
                1: 'نوع کاربری شما با موفقیت ذخیره شد.',
                2: 'اطلاعات شخصی شما با موفقیت ذخیره شد.',
                3: 'آدرس شما با موفقیت ذخیره شد.'
            };

            const message = stepMessages[completedStep];
            if (message) {
                this.showMessage(message, 'success');
            }
        }

        validateCurrentStep() {
            const currentStepElement = $(`.form-step[data-step="${this.currentStep}"]`);
            const requiredFields = currentStepElement.find('input[data-required="true"], textarea[data-required="true"]');
            let isValid = true;

            // Clear any previous validation states
            this.form.find('input, textarea').removeClass('is-invalid');
            // Clear all field error messages for current step only
            currentStepElement.find('.field-error-message').remove();

            requiredFields.each((index, field) => {
                const $field = $(field);
                // Skip validation for disabled fields
                if ($field.prop('disabled')) {
                    return; // continue to next field
                }
                // validateField will show errors automatically
                if (!this.validateField($field)) {
                    isValid = false;
                }
            });

            // Validate phone field if it has a value
            const phoneField = $('#address_phone');
            const phoneValue = phoneField.val().trim();
            if (phoneValue && !this.isValidPhone(phoneValue)) {
                phoneField.addClass('is-invalid');
                this.showFieldError(phoneField, 'شماره تلفن باید 11 رقم باشد و با 09 شروع شود.');
                isValid = false;
            }

            // Validate address field for step 3 (only if field is enabled)
            if (this.currentStep === 3) {
                const addressField = $('#user_address');
                if (!addressField.prop('disabled')) {
                    const addressValue = addressField.val().trim();
                    if (!this.isValidAddress(addressValue)) {
                        addressField.addClass('is-invalid');
                        this.showFieldError(addressField, 'لطفاً موقعیت خود را روی نقشه انتخاب کنید تا آدرس دریافت شود.');
                        isValid = false;
                    }
                }
            }

            return isValid;
        }

        submitCurrentStep() {
            // For step 1, only check if user type is selected
            if (this.currentStep === 1) {
                const userType = $('input[name="user_type"]:checked').val();
                if (!userType) {
                    this.showMessage('لطفاً نوع کاربری خود را انتخاب کنید.', 'error');
                    return;
                }
            } else {
                // For other steps, validate required fields
                // validateCurrentStep will show field-specific errors automatically
                if (!this.validateCurrentStep()) {
                    // Check for address-specific errors (map location not selected)
                    const addressField = $('#user_address');
                    if (this.currentStep === 3) {
                        if (addressField.prop('disabled')) {
                            this.showMessage('لطفاً ابتدا موقعیت خود را روی نقشه انتخاب کنید.', 'error');
                            return;
                        }
                    }
                    
                    // Don't show general error message - field-specific errors are already shown
                    // Just return to prevent submission
                    return;
                }
            }

            this.setLoading(true);

            const formData = this.getCurrentStepData();
            const action = this.getActionForStep(this.currentStep);

            $.ajax({
                url: signupLocalization.ajaxUrl,
                type: 'POST',
                data: {
                    action: action,
                    ...formData,
                    nonce: this.getNonceForStep(this.currentStep)
                },
                success: (response) => {
                    this.setLoading(false);
                    
                    if (response.success) {
                        // Move to next step immediately and show success message for the completed step
                        const completedStep = this.currentStep;
                        this.nextStep();
                        
                        // Show success message for the completed step on the new step with a small delay
                        setTimeout(() => {
                            this.showStepSuccessMessage(completedStep);
                        }, 100);
                    } else {
                        this.showMessage(response.data.message || 'خطایی رخ داد. لطفاً دوباره تلاش کنید.', 'error');
                    }
                },
                error: () => {
                    this.setLoading(false);
                    this.showMessage('خطا در ارتباط با سرور. لطفاً دوباره تلاش کنید.', 'error');
                }
            });
        }

        getCurrentStepData() {
            const data = {
                user_id: $('input[name="user_id"]').val()
            };

            switch (this.currentStep) {
                case 1:
                    data.user_type = $('input[name="user_type"]:checked').val();
                    break;
                case 2:
                    // Trim text fields to remove leading/trailing whitespace
                    data.first_name = $('#first_name').val().trim();
                    data.last_name = $('#last_name').val().trim();
                    if ($('#organization_name').is(':visible')) {
                        data.organization_name = $('#organization_name').val().trim();
                    }
                    break;
                case 3:
                    // Save address data as JSON array using helper function
                    data.user_address = JSON.stringify(this.getCurrentAddressData());
                    // Also update user role to Client when address is saved
                    data.update_role = true;
                    break;
            }

            return data;
        }

        getActionForStep(step) {
            const actions = {
                1: 'save_user_type',
                2: 'save_user_info',
                3: 'save_user_address'
            };
            return actions[step];
        }

        getNonceForStep(step) {
            const nonces = {
                1: signupLocalization.nonces.save_user_type,
                2: signupLocalization.nonces.save_user_info,
                3: signupLocalization.nonces.save_user_address
            };
            return nonces[step];
        }

        nextStep() {
            // Clear any existing message timeout
            if (this.messageTimeout) {
                clearTimeout(this.messageTimeout);
                this.messageTimeout = null;
            }
            
            if (this.currentStep < this.totalSteps) {
                this.currentStep++;
                this.updateProgress();
                this.showCurrentStep();
                this.updateNavigationButtons();
                // Initialize field states for the new step
                this.initializeFieldStates();
            } else {
                // All steps completed - go to completion step
                this.currentStep = 4;
                this.updateProgress();
                this.showCurrentStep();
                this.updateNavigationButtons();
            }
        }


        prevStep() {
            if (this.currentStep > 1) {
                this.currentStep--;
                this.updateProgress();
                this.showCurrentStep();
                this.updateNavigationButtons();
            }
        }

        showCurrentStep() {
            $('.form-step').removeClass('active');
            $(`.form-step[data-step="${this.currentStep}"]`).addClass('active');
            
            // Update step 2 content based on user type when showing step 2
            if (this.currentStep === 2) {
                this.updateStep2Content();
            }
            
            // Clear any existing location detected messages when switching steps
            $('.location-detected-message').remove();
            
            // Clear all field errors when switching steps
            $('.field-error-message').remove();
            
            // Initialize map when step 3 is shown
            if (this.currentStep === 3 && !this.map) {
                this.initializeMap();
            }
            
            // Handle completion step
            if (this.currentStep === 4) {
                this.startCountdown();
            }
        }

        updateProgress() {
            if (this.currentStep <= 3) {
                $('.step-counter-text').text(`مرحله ${this.currentStep} از 3`);
                $('#step-counter').removeClass('hidden');
            } else {
                // Hide step counter on completion step
                $('#step-counter').addClass('hidden');
            }
        }

        updateNavigationButtons() {
            const $prevBtn = $('#prev_step');
            const $submitBtn = $('#submit_step');
            const $btnText = $('.btn-text');

            // Show/hide previous button
            if (this.currentStep > 1 && this.currentStep <= this.totalSteps) {
                $prevBtn.show();
            } else {
                $prevBtn.hide();
            }

            // Update submit button
            if (this.currentStep <= this.totalSteps) {
                $submitBtn.show();
                $btnText.text(this.currentStep === this.totalSteps ? 'ثبت آدرس' : 'ادامه');
            } else {
                $submitBtn.hide();
            }

            // Bind previous button click
            $prevBtn.off('click').on('click', () => {
                this.prevStep();
            });
        }

        setLoading(loading) {
            const $btn = $('#submit_step');
            const $btnText = $('.btn-text');
            const $btnLoader = $('.btn-loader');

            if (loading) {
                $btn.addClass('loading').prop('disabled', true);
                $btnText.hide();
                $btnLoader.show();
            } else {
                $btn.removeClass('loading').prop('disabled', false);
                $btnText.show();
                $btnLoader.hide();
            }
        }

        initializeMap() {
            // Check if we're on step 3 and map container exists
            if (this.currentStep !== 3 || !$('#location-map').length || this.map) {
                return;
            }

            // Check if Leaflet and Neshan SDK are loaded
            if (typeof L === 'undefined') {
                console.error('Leaflet not loaded');
                return;
            }

            try {
                // Initialize the Neshan map using Leaflet
                this.map = new L.Map('location-map', {
                    key: 'web.45357b6bfe19452ebd955f31fc0e82e6',
                    maptype: 'neshan',
                    poi: false,
                    traffic: false,
                    center: [35.6892, 51.3890], // Tehran coordinates [lat, lng]
                    zoom: 14
                });

                // Hide loading indicator
                $('#map-loading').hide();

                // Add click event listener to the map
                this.map.on('click', (e) => {
                    this.handleMapClick(e);
                });

                // Load existing location if available
                const existingLocation = $('#user_geo_location').val();
                if (existingLocation) {
                    try {
                        const coords = JSON.parse(existingLocation);
                        this.setMapLocation(coords.lat, coords.lng);
                        // If location exists, auto-confirm it
                        this.handleConfirmLocation();
                    } catch (e) {
                        console.warn('Invalid existing location data');
                    }
                } else {
                    // If no existing location, ensure fields are disabled and overlay is shown
                    $('#user_address, #address_details, #address_notes, #address_phone').prop('disabled', true);
                    $('#address-fields-overlay').removeClass('hidden');
                }

                // Check geolocation support and disable button if not supported
                if (!navigator.geolocation) {
                    $('#my-location-btn').prop('disabled', true).attr('title', 'موقعیت‌یابی پشتیبانی نمی‌شود');
                } else {
                    // Try to get user's location automatically when map loads
                    this.autoDetectLocation();
                }

            } catch (error) {
                console.error('Error initializing map:', error);
                $('#map-loading').html('<p>خطا در بارگذاری نقشه</p>');
            }
        }

        handleMapClick(e) {
            const lat = e.latlng.lat;
            const lng = e.latlng.lng;
            
            // Store selected location
            this.selectedLocation = { lat: lat, lng: lng };
            
            // Update hidden input
            $('#user_geo_location').val(JSON.stringify(this.selectedLocation));
            
            // Enable the confirm location button only if location is valid
            if (this.isValidLocation(lat, lng)) {
                $('#confirm-location-btn').prop('disabled', false);
            }
            
            // Add marker to map (remove existing first)
            if (this.marker) {
                this.map.removeLayer(this.marker);
            }
            
            this.marker = L.marker([lat, lng], {
                icon: L.divIcon({
                    className: 'custom-marker',
                    html: '<div style="background-color: #007bff; width: 20px; height: 20px; border-radius: 50%; border: 3px solid white; box-shadow: 0 2px 4px rgba(0,0,0,0.3);"></div>',
                    iconSize: [20, 20],
                    iconAnchor: [10, 10]
                })
            }).addTo(this.map);
        }

        setMapLocation(lat, lng) {
            if (!this.map) return;
            
            // Set map center
            this.map.setView([lat, lng], this.map.getZoom());
            
            // Add marker
            if (this.marker) {
                this.map.removeLayer(this.marker);
            }
            
            this.marker = L.marker([lat, lng], {
                icon: L.divIcon({
                    className: 'custom-marker',
                    html: '<div style="background-color: #007bff; width: 20px; height: 20px; border-radius: 50%; border: 3px solid white; box-shadow: 0 2px 4px rgba(0,0,0,0.3);"></div>',
                    iconSize: [20, 20],
                    iconAnchor: [10, 10]
                })
            }).addTo(this.map);
            
            // Update UI and enable button only if location is valid
            this.selectedLocation = { lat: lat, lng: lng };
            $('#user_geo_location').val(JSON.stringify(this.selectedLocation));
            
            if (this.isValidLocation(lat, lng)) {
                $('#confirm-location-btn').prop('disabled', false);
            }
        }

        // Check if location is within Iran bounds
        isValidLocation(lat, lng) {
            return lat >= 25 && lat <= 40 && lng >= 44 && lng <= 64;
        }

        // Convert Persian/Farsi digits to English digits
        convertPersianToEnglishDigits(str) {
            const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
            const englishDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
            
            let result = str;
            for (let i = 0; i < persianDigits.length; i++) {
                result = result.replace(new RegExp(persianDigits[i], 'g'), englishDigits[i]);
            }
            return result;
        }

        // Validate phone number
        isValidPhone(phone) {
            // Convert Persian digits first
            phone = this.convertPersianToEnglishDigits(phone);
            
            // Check if phone has 11 digits and starts with 09
            const phoneRegex = /^09\d{9}$/;
            return phoneRegex.test(phone);
        }

        // Validate phone field in real-time
        validatePhoneField($field) {
            const value = $field.val().trim();
            
            if (value === '') {
                // Empty phone is valid (optional field)
                $field.removeClass('is-invalid');
                this.clearFieldError($field);
                return true;
            }
            
            if (this.isValidPhone(value)) {
                $field.removeClass('is-invalid');
                this.clearFieldError($field);
                return true;
            } else {
                $field.addClass('is-invalid');
                return false;
            }
        }

        // Check if address is valid (not loading/error messages)
        isValidAddress(address) {
            if (!address || address.trim() === '') {
                return false;
            }
            
            const invalidMessages = [
                'در حال دریافت آدرس...',
                'آدرس یافت نشد',
                'خطا در دریافت آدرس'
            ];
            
            // Check if address is a loading/error message
            if (invalidMessages.includes(address.trim())) {
                return false;
            }
            
            // Check if address field is disabled (user hasn't confirmed location yet)
            const $addressField = $('#user_address');
            if ($addressField.prop('disabled')) {
                return false;
            }
            
            return true;
        }

        // Filter input to allow only Persian letters, spaces, and zero-width non-joiner
        // Shows error immediately if non-Persian characters are detected
        filterPersianInput($field) {
            const value = $field.val();
            const hasNonPersian = /[^\u0600-\u06FF\s\u200c]/g.test(value);
            const hasNumbers = /[\u0660-\u0669\u06F0-\u06F9]/g.test(value);
            
            // Show error immediately if non-Persian characters are detected
            if (hasNonPersian || hasNumbers) {
                this.showFieldError($field, 'فقط حروف فارسی مجاز است.');
                $field.addClass('is-invalid');
            }
            
            // Filter out non-Persian characters
            let filteredValue = value.replace(/[^\u0600-\u06FF\s\u200c]/g, '');
            filteredValue = filteredValue.replace(/[\u0660-\u0669\u06F0-\u06F9]/g, '');
            if (value !== filteredValue) {
                $field.val(filteredValue);
            }
        }

        // Validate Persian-only fields
        isPersianText(text) {
            if (!text) {
                return false;
            }

            const normalized = text.replace(/\s+/g, '').replace(/\u200c/g, '');
            if (!normalized.length) {
                return false;
            }

            try {
                const chars = Array.from(normalized);
                return chars.every((char) => /\p{Script=Arabic}/u.test(char) && /\p{Letter}/u.test(char));
            } catch (error) {
                const fallbackRegex = /^[\u0621-\u0629\u062A-\u063A\u0641-\u064A\u067E\u0686\u0698\u06A9\u06AF\u06BE\u06C0\u06CC]+$/;
                return fallbackRegex.test(normalized);
            }
        }

        // Return the first Persian-only field that fails validation
        getInvalidPersianField() {
            const selectors = ['#first_name', '#last_name', '#organization_name'];
            for (const selector of selectors) {
                const $field = $(selector);
                if (!$field.length) {
                    continue;
                }

                const value = $field.val().trim();
                const isRequired = $field.attr('data-required') === 'true';

                if (!value) {
                    if (isRequired) {
                        $field.addClass('is-invalid');
                        return $field;
                    }
                    $field.removeClass('is-invalid');
                    continue;
                }

                if (!this.isPersianText(value)) {
                    $field.addClass('is-invalid');
                    return $field;
                }

                $field.removeClass('is-invalid');
            }

            return null;
        }

        initializeAddressSearch() {
            this.searchTimeout = null;
            this.searchResults = [];
            
            // Make search field writable and bind events
            $('#address-search').prop('readonly', false);
            
            // Prevent clicks on search field from propagating to map
            $('.map-search-overlay').on('click', (e) => {
                e.stopPropagation();
            });
            
            // Bind search input events
            $('#address-search').on('input', (e) => {
                this.handleSearchInput(e.target.value);
            });
            
            // Bind confirm location button click
            $('#confirm-location-btn').on('click', () => {
                this.handleConfirmLocation();
            });
            
            // Bind my location button click
            $('#my-location-btn').on('click', () => {
                this.getCurrentLocation();
            });
            
            // Bind popup close event (X button)
            $('#popup-close').on('click', () => {
                this.hideLocationPermissionPopup();
            });
            
            // Bind popup continue button (ادامه) - requests location and closes popup
            $('#popup-dismiss').on('click', () => {
                this.hideLocationPermissionPopup();
                // Request location permission
                this.getCurrentLocation();
            });
            
            // Bind popup close button (بستن) - closes without requesting access
            $('#popup-close-btn').on('click', () => {
                this.hideLocationPermissionPopup();
            });
            
            // Hide popup when clicking outside
            $(document).on('click', (e) => {
                if ($(e.target).hasClass('location-permission-popup')) {
                    this.hideLocationPermissionPopup();
                }
            });
            
            // Hide results when clicking outside
            $(document).on('click', (e) => {
                if (!$(e.target).closest('.map-search-overlay').length) {
                    this.hideSearchResults();
                }
            });

            // Listen for page visibility changes to retry location when user returns
            document.addEventListener('visibilitychange', () => {
                if (!document.hidden && !$('#user_geo_location').val()) {
                    // Page became visible and no location is set, retry auto-detection
                    setTimeout(() => {
                        this.autoDetectLocation();
                    }, 1000);
                }
            });

            // Listen for window focus to retry location detection
            window.addEventListener('focus', () => {
                if (!$('#user_geo_location').val()) {
                    // Window focused and no location is set, retry auto-detection
                    setTimeout(() => {
                        this.autoDetectLocation();
                    }, 500);
                }
            });
        }

        handleSearchInput(query) {
            if (this.searchTimeout) {
                clearTimeout(this.searchTimeout);
            }
            
            if (query.length < 3) {
                this.hideSearchResults();
                return;
            }
            
            this.searchTimeout = setTimeout(() => {
                this.searchAddress(query);
            }, 500);
        }

        searchAddress(query) {
            this.showSearchLoading();
            
            // Use OpenStreetMap Nominatim for geocoding (free service)
            $.ajax({
                url: 'https://nominatim.openstreetmap.org/search',
                type: 'GET',
                data: {
                    format: 'json',
                    q: query,
                    limit: 5,
                    addressdetails: 1,
                    'accept-language': 'fa,en',
                    countrycodes: 'ir', // Limit to Iran
                    bounded: 1,
                    viewbox: '44.0,25.0,63.5,39.8' // Iran bounding box
                },
                success: (response) => {
                    this.handleSearchResults(response);
                },
                error: (xhr, status, error) => {
                    console.error('Search error:', error);
                    this.showSearchError();
                }
            });
        }

        handleSearchResults(results) {
            this.searchResults = results || [];
            this.displaySearchResults();
        }

        displaySearchResults() {
            const $results = $('#search-results');
            $results.empty();
            
            if (this.searchResults.length === 0) {
                $results.html('<div class="search-no-results">هیچ نتیجه‌ای یافت نشد</div>');
            } else {
                this.searchResults.forEach((result, index) => {
                    const $item = $(`
                        <div class="search-result-item" data-index="${index}">
                            <div class="search-result-title">${result.display_name}</div>
                        </div>
                    `);
                    
                    $item.on('click', () => {
                        this.selectSearchResult(result);
                    });
                    
                    $results.append($item);
                });
            }
            
            $results.show();
        }

        selectSearchResult(result) {
            // Set map location
            const lat = parseFloat(result.lat);
            const lng = parseFloat(result.lon);
            this.setMapLocation(lat, lng);
            
            // Hide search results and clear search input
            this.hideSearchResults();
            $('#address-search').val('');
        }

        showSearchLoading() {
            $('#search-results').html('<div class="search-loading">در حال جستجو...</div>').show();
        }

        showSearchError() {
            $('#search-results').html('<div class="search-no-results">خطا در جستجو</div>').show();
        }

        hideSearchResults() {
            $('#search-results').hide();
        }

        getAddressFromCoordinates(lat, lng) {
            // Show loading in address field
            $('#user_address').val('در حال دریافت آدرس...').addClass('has-value').removeClass('is-invalid');
            
            // Try using a free reverse geocoding service as fallback
            // Since Neshan Search API requires separate key, we'll use OpenStreetMap Nominatim
            $.ajax({
                url: 'https://nominatim.openstreetmap.org/reverse',
                type: 'GET',
                data: {
                    format: 'json',
                    lat: lat,
                    lon: lng,
                    zoom: 18,
                    addressdetails: 1,
                    'accept-language': 'fa,en'
                },
                success: (response) => {
                    if (response && response.display_name) {
                        // Format the address for Persian users
                        let address = this.formatAddress(response);
                        $('#user_address').val(address).addClass('has-value').removeClass('is-invalid');
                    } else {
                        $('#user_address').val('آدرس یافت نشد').addClass('has-value').addClass('is-invalid');
                    }
                },
                error: (xhr, status, error) => {
                    console.error('Reverse geocoding error:', error);
                    $('#user_address').val('خطا در دریافت آدرس').addClass('has-value').addClass('is-invalid');
                }
            });
        }

        // Helper function to get current address data as object
        getCurrentAddressData() {
            let phone = ($('#address_phone').val() || '').trim();
            
            // Convert Persian digits to English and store with 0 format
            phone = this.convertPersianToEnglishDigits(phone);
            
            // Trim text fields to remove leading/trailing whitespace
            return {
                geo_coordinates: $('#user_geo_location').val() || '',
                address: ($('#user_address').val() || '').trim(),
                details: ($('#address_details').val() || '').trim(),
                notes: ($('#address_notes').val() || '').trim(),
                phone: phone // Already trimmed, store with 0 format, not 98
            };
        }

        // Enable address fields when location is confirmed
        enableAddressFields() {
            $('#user_address, #address_details, #address_notes, #address_phone').prop('disabled', false);
            
            // Hide the address fields overlay and notice
            $('#address-fields-overlay').addClass('hidden');
            $('.address-fields-notice').addClass('hidden');
        }

        // Handle confirm location button click
        handleConfirmLocation() {
            if (!this.selectedLocation) return;
            
            // Enable address fields
            this.enableAddressFields();
            
            // Get address from coordinates and auto-fill
            this.getAddressFromCoordinates(this.selectedLocation.lat, this.selectedLocation.lng);
            
            // Disable the button after confirmation
            $('#confirm-location-btn').prop('disabled', true);
            
            // Scroll to the address field with 40px offset
            this.scrollToAddressField();
        }

        // Get user's current location using browser geolocation
        getCurrentLocation() {
            const $btn = $('#my-location-btn');
            
            // Check if geolocation is supported
            if (!navigator.geolocation) {
                this.showMessage('مرورگر شما از موقعیت‌یابی پشتیبانی نمی‌کند.', 'error');
                return;
            }

            // Show loading state
            $btn.addClass('loading').prop('disabled', true);

            const options = {
                enableHighAccuracy: true,
                timeout: 10000,
                maximumAge: 0 // Don't use cache for manual requests
            };

            navigator.geolocation.getCurrentPosition(
                (position) => {
                    // Success callback
                    $btn.removeClass('loading').prop('disabled', false);
                    
                    const lat = position.coords.latitude;
                    const lng = position.coords.longitude;
                    
                    // Check if location is within Iran and set on map
                    if (this.isValidLocation(lat, lng)) {
                        this.setMapLocation(lat, lng);
                        // Show success message for manual location detection
                        this.showMessage('موقعیت شما یافت شد', 'success');
                    } else {
                        this.showMessage('موقعیت شما خارج از ایران است. لطفاً موقعیت را دستی انتخاب کنید.', 'error');
                    }
                },
                (error) => {
                    // Error callback
                    $btn.removeClass('loading').prop('disabled', false);
                    
                    switch (error.code) {
                        case error.PERMISSION_DENIED:
                            // Only show popup if it hasn't been shown before
                            // Don't show popup again if user already dismissed it
                            if (!this.popupShown) {
                                this.showLocationPermissionPopup();
                            }
                            break;
                        case error.POSITION_UNAVAILABLE:
                            this.showMessage('اطلاعات موقعیت در دسترس نیست.', 'error');
                            break;
                        case error.TIMEOUT:
                            this.showMessage('درخواست موقعیت‌یابی منقضی شد. لطفاً دوباره تلاش کنید.', 'error');
                            break;
                        default:
                            this.showMessage('خطای ناشناخته در موقعیت‌یابی.', 'error');
                            break;
                    }
                },
                options
            );
        }

        // Show location permission popup (only once per page load)
        showLocationPermissionPopup() {
            // Only show popup once per page load
            if (this.popupShown) {
                return;
            }
            this.popupShown = true;
            $('#location-permission-popup').fadeIn(300);
        }

        // Hide location permission popup
        hideLocationPermissionPopup() {
            $('#location-permission-popup').fadeOut(300);
        }

        // Scroll to address field with smooth animation
        scrollToAddressField() {
            const addressField = document.getElementById('user_address');
            if (addressField) {
                const elementPosition = addressField.getBoundingClientRect().top;
                const offsetPosition = elementPosition + window.pageYOffset - 40; // 40px offset

                window.scrollTo({
                    top: offsetPosition,
                    behavior: 'smooth'
                });
            }
        }

        // Auto-detect user's location when map loads
        autoDetectLocation() {
            // Only auto-detect if no existing location is set and we're on step 3
            if ($('#user_geo_location').val() || this.currentStep !== 3) {
                return;
            }

            const options = {
                enableHighAccuracy: false, // Use cached location for auto-detection
                timeout: 5000, // Shorter timeout for auto-detection
                maximumAge: 300000 // 5 minutes cache
            };

            navigator.geolocation.getCurrentPosition(
                (position) => {
                    // Success callback
                    const lat = position.coords.latitude;
                    const lng = position.coords.longitude;
                    
                    // Check if location is within Iran and set on map
                    if (this.isValidLocation(lat, lng)) {
                        this.setMapLocation(lat, lng);
                        // Show location detected message only on address step (step 3), auto-hide after 3 seconds
                        this.showLocationDetectedMessage();
                    }
                },
                (error) => {
                    // Error callback - silently handle errors for auto-detection
                    // Only show popup for permission denied, and only once
                    if (error.code === error.PERMISSION_DENIED && !this.popupShown) {
                        this.showLocationPermissionPopup();
                    }
                    // Other errors are silently ignored for auto-detection
                },
                options
            );
        }

        formatAddress(response) {
            // Extract relevant address components
            const address = response.address || {};
            const parts = [];
            
            // Add street/road
            if (address.road) parts.push(address.road);
            if (address.house_number) parts.push(address.house_number);
            
            // Add neighborhood/suburb
            if (address.neighbourhood) parts.push(address.neighbourhood);
            if (address.suburb) parts.push(address.suburb);
            
            // Add city
            if (address.city) parts.push(address.city);
            if (address.town) parts.push(address.town);
            if (address.village) parts.push(address.village);
            
            // Add state/province
            if (address.state) parts.push(address.state);
            
            return parts.length > 0 ? parts.join('، ') : response.display_name || 'آدرس یافت نشد';
        }

        startCountdown() {
            // Prevent multiple countdown initializations
            if (this.countdownTimer || this.countdownStarted) {
                return;
            }
            
            this.countdownStarted = true;
            let countdown = 3;
            const countdownElement = $('#countdown');
            const dashboardUrl = $('#dashboard-btn').attr('href');
            
            // Update countdown display
            const updateCountdown = () => {
                countdownElement.text(countdown);
                countdown--;
                
                if (countdown < 0) {
                    // Clear timer and redirect
                    clearInterval(this.countdownTimer);
                    this.countdownTimer = null;
                    
                    // Use window.location.replace to prevent back button issues
                    window.location.replace(dashboardUrl);
                }
            };
            
            // Start countdown
            updateCountdown(); // Show initial value
            this.countdownTimer = setInterval(updateCountdown, 1000);
            
            // Clear countdown when user clicks dashboard button
            $('#dashboard-btn').off('click.countdown').on('click.countdown', (e) => {
                e.preventDefault();
                if (this.countdownTimer) {
                    clearInterval(this.countdownTimer);
                    this.countdownTimer = null;
                }
                // Use window.location.replace to prevent back button issues
                window.location.replace(dashboardUrl);
            });
        }

        showMessage(message, type = 'info', $field = null) {
            // If field is provided and it's an error, show below the field
            if ($field && type === 'error' && $field.length) {
                this.showFieldError($field, message);
                return;
            }

            // Otherwise show at top (for success messages or general errors without a field)
            $('.signup-message').remove();

            const messageClass = type === 'error' ? 'alert-danger' : 
                               type === 'success' ? 'alert-success' : 'alert-info';

            const $message = $(`
                <div class="signup-message alert ${messageClass} alert-dismissible fade show" role="alert">
                    <i class="bi bi-${type === 'error' ? 'exclamation-triangle' : 
                                      type === 'success' ? 'check-circle' : 'info-circle'}"></i>
                    ${message}
                    <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                </div>
            `);

            $('.step-content').prepend($message);
        }

        showFieldError($field, message) {
            // Find the parent form-field container
            const $formField = $field.closest('.form-field');
            if (!$formField.length) {
                // For radio buttons or special fields, try different approach
                const $container = $field.closest('.radio-option, .form-field, .organization-field');
                if ($container.length) {
                    $container.find('.field-error-message').remove();
                    const $errorMsg = $(`
                        <div class="field-error-message">
                            <i class="bi bi-exclamation-triangle"></i>
                            <span>${message}</span>
                        </div>
                    `);
                    $container.append($errorMsg);
                    return;
                }
                return;
            }

            // Remove existing error message for this field
            $formField.find('.field-error-message').remove();

            // Create error message element
            const $errorMsg = $(`
                <div class="field-error-message">
                    <i class="bi bi-exclamation-triangle"></i>
                    <span>${message}</span>
                </div>
            `);

            // Insert error message after the floating-field container
            const $floatingField = $formField.find('.floating-field');
            if ($floatingField.length) {
                $floatingField.after($errorMsg);
            } else {
                // Fallback: append to form-field
                $formField.append($errorMsg);
            }

            // Scroll to field if needed
            const fieldTop = $field.offset().top;
            const windowHeight = $(window).height();
            if (fieldTop < $(window).scrollTop() || fieldTop > $(window).scrollTop() + windowHeight) {
                $('html, body').animate({
                    scrollTop: fieldTop - 100
                }, 300);
            }
        }

        clearFieldError($field) {
            // Find the parent form-field container
            const $formField = $field.closest('.form-field');
            if ($formField.length) {
                $formField.find('.field-error-message').remove();
            } else {
                // Try to find in parent containers
                const $container = $field.closest('.radio-option, .form-field, .organization-field');
                if ($container.length) {
                    $container.find('.field-error-message').remove();
                }
            }
        }

        showLocationDetectedMessage() {
            // Only show on address step (step 3)
            if (this.currentStep !== 3) {
                return;
            }

            // Remove existing location messages
            $('.location-detected-message').remove();

            const $message = $(`
                <div class="location-detected-message alert alert-success alert-dismissible fade show" role="alert">
                    <i class="bi bi-check-circle"></i>
                    موقعیت شما به صورت خودکار یافت شد
                    <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                </div>
            `);

            // Insert message before the map
            $('.geo-location-field .geo-label').after($message);

            // Auto-hide after 3 seconds
            setTimeout(() => {
                $message.fadeOut(300, () => $message.remove());
            }, 3000);
        }
    }

    // Initialize when document is ready
    $(document).ready(function() {
        new SignupForm();
    });

})(jQuery);
