/**
 * Simply.IN Payment Method Renderer
 */
define([
    'Magento_Checkout/js/view/payment/default',
    'jquery',
    'mage/url',
    'Magento_Checkout/js/model/quote',
    'Magento_Checkout/js/model/full-screen-loader',
    'Simplyin_Payment/js/model/session-storage-manager',
    'Simplyin_Payment/js/model/country-data',
    'Simplyin_Payment/js/model/ajax-client'
], function (Component, $, urlBuilder, quote, fullScreenLoader, sessionStorageManager, countryData, ajaxClient) {
    'use strict';

    return Component.extend({
        defaults: {
            template: 'Simplyin_Payment/payment/simplyin-payment',
            paymentIframeUrl: null,
            showNewAccountCheckbox: false,
            createSimplyInAccount: true,
            availablePaymentMethods: [],
            methodsLoaded: false,
            selectedPaymentMethod: null,
            saveCard: false,
            cardName: '',
            savedCardCvv: '',
            blikCode: '',
            simplyInOrderId: null,
            paymentInfo: null,
            phoneNumber: '',
            selectedCountryCode: '+48',
            selectedCountryIso: 'PL',
            phoneNumberError: '',
            countryCodes: [],
            countryDropdownOpen: false,
            countrySearchQuery: '',
            filteredCountryCodes: []
        },

        /**
         * Get default value for create account checkbox from admin config
         * @returns {boolean}
         */
        getDefaultCreateAccountChecked: function () {
            if (window.checkoutConfig && 
                window.checkoutConfig.payment && 
                window.checkoutConfig.payment.simplyin_payment &&
                typeof window.checkoutConfig.payment.simplyin_payment.defaultCreateAccountChecked !== 'undefined') {
                return window.checkoutConfig.payment.simplyin_payment.defaultCreateAccountChecked;
            }
            return true; // fallback to checked if config not available
        },

        /**
         * Get payment method code
         */
        getCode: function () {
            return 'simplyin_payment';
        },

        /**
         * Get SimplyIN logo URL for checkout display
         */
        getLogoUrl: function () {
            return window.checkoutConfig.payment.simplyin_payment.logoUrl || '';
        },

        /**
         * Get P24 logo URL for checkout display
         * Falls back to dynamic provider logo if available
         */
        getP24LogoUrl: function () {
            // First check if we have a dynamic provider logo from API
            if (this.paymentProviderLogoUrl && this.paymentProviderLogoUrl()) {
                return this.paymentProviderLogoUrl();
            }
            return window.checkoutConfig.payment.simplyin_payment.p24LogoUrl || '';
        },

        /**
         * Get payment provider name for display
         */
        getPaymentProviderName: function () {
            if (this.paymentProviderName && this.paymentProviderName()) {
                return this.paymentProviderName();
            }
            return 'Przelewy24';
        },

        /**
         * Initialize observables
         */
        initObservable: function () {
            this._super()
                .observe([
                    'showNewAccountCheckbox',
                    'createSimplyInAccount',
                    'availablePaymentMethods',
                    'methodsLoaded',
                    'selectedPaymentMethod',
                    'saveCard',
                    'cardName',
                    'savedCardCvv',
                    'blikCode',
                    'blikDigit1',
                    'blikDigit2',
                    'blikDigit3',
                    'blikDigit4',
                    'blikDigit5',
                    'blikDigit6',
                    'phoneNumber',
                    'selectedCountryCode',
                    'selectedCountryIso',
                    'phoneNumberError',
                    'countryCodes',
                    'countryDropdownOpen',
                    'countrySearchQuery',
                    'filteredCountryCodes',
                    'paymentProviderName',
                    'paymentProviderLogoUrl',
                    'paymentProviderRegulationsUrl',
                    'paymentProviderGdprUrl'
                ]);

            var self = this;

            // Set default value for createSimplyInAccount from admin config
            this.createSimplyInAccount(this.getDefaultCreateAccountChecked());

            // Load country data from country-data module
            this.countryCodes(countryData.getCountriesArray());

            // Initialize filtered countries with all countries
            this.filteredCountryCodes(this.countryCodes());

            // Set default country (Poland)
            this.selectedCountryIso('PL');
            this.selectedCountryCode('+48');

            // Watch for country search query changes
            this.countrySearchQuery.subscribe(function (query) {
                self.filterCountries(query);
            });

            // Watch for country ISO changes to update phone code
            this.selectedCountryIso.subscribe(function (isoCode) {
                if (isoCode) {
                    var phoneCode = countryData.getPhoneCode(isoCode);
                    if (phoneCode) {
                        self.selectedCountryCode(phoneCode);
                    }
                }
            });

            // Initialize country dropdown with flags after render
            setTimeout(function () {
                self.initCountryDropdownFlags();
                self.setupDropdownClickOutside();
            }, 500);

            // Initialize session storage manager
            sessionStorageManager.initialize();

            // Listen for email change event
            $(document).on('simplyin:email_changed', function (event, newEmail) {
                self.availablePaymentMethods([]);
                self.methodsLoaded(false);
                self.selectedPaymentMethod(null);
                self.showNewAccountCheckbox(false);
            });

            // Listen for new account option event
            $(document).on('simplyin:showNewAccountOption', function (event, email) {
                self.showNewAccountCheckbox(true);

                // Force load payment methods for new users
                // Use setTimeout to ensure session storage is updated
                setTimeout(function() {
                    self.loadPaymentMethods();
                }, 100);
            });

            // Listen for auth success
            $(document).on('simplyin:auth_successful', function (event, token, userData) {
                self.loadPaymentMethods();
            });

            // Check if user is already authenticated and load methods
            // This handles the case where user returns to payment step with existing session
            var existingToken = sessionStorageManager.getAuthToken();
            var isNewUser = sessionStorageManager.isNewUser();
            var isRecognized = sessionStorageManager.isUserRecognized();

            if (existingToken && existingToken.trim() !== '') {
                this.loadPaymentMethods();
            } else if (isNewUser) {
                this.showNewAccountCheckbox(true);
                this.loadPaymentMethods();
            } else if (isRecognized) {
                // User was recognized (checkEmail returned userExists=true) but didn't verify OTP
                // Still load payment methods so they can use SimplyIN payment
                this.loadPaymentMethods();
            }

            // Check if returning from 3D Secure redirect
            this.handle3DSReturn();

            return this;
        },

        /**
         * Check if user is authenticated with SimplyIN
         * Used to determine whether to show card save options
         */
        isSimplyInAuthenticated: function () {
            var authToken = sessionStorageManager.getAuthToken();
            return authToken !== null && authToken !== '' && authToken.trim() !== '';
        },

        /**
         * Check if BLIK is available for current currency
         * BLIK only works with PLN currency (matching PrestaShop behavior)
         *
         * @return {boolean}
         */
        isBlikAvailableForCurrency: function () {
            // Check from checkout config
            if (window.checkoutConfig && 
                window.checkoutConfig.payment && 
                window.checkoutConfig.payment.simplyin_payment) {
                
                // Use pre-calculated value from backend if available
                if (typeof window.checkoutConfig.payment.simplyin_payment.isBlikAvailable !== 'undefined') {
                    return window.checkoutConfig.payment.simplyin_payment.isBlikAvailable;
                }
                
                // Fallback: check currency code
                var currencyCode = window.checkoutConfig.payment.simplyin_payment.currencyCode;
                if (currencyCode) {
                    return currencyCode.toUpperCase() === 'PLN';
                }
            }
            
            // Fallback: check quote currency
            if (quote && quote.totals()) {
                var quoteCurrency = quote.totals().quote_currency_code;
                if (quoteCurrency) {
                    return quoteCurrency.toUpperCase() === 'PLN';
                }
            }
            
            // Default to true if we can't determine currency
            return true;
        },

        /**
         * Get terms & conditions URL for the paywall footer.
         * Operator (payment provider) value only; no Simply.IN fallback.
         */
        getFooterTermsUrl: function () {
            return this.paymentProviderRegulationsUrl() || '';
        },

        /**
         * Get privacy policy URL for the paywall footer.
         * Operator (payment provider) value only; no Simply.IN fallback.
         */
        getFooterPrivacyUrl: function () {
            return this.paymentProviderGdprUrl() || '';
        },

        /**
         * Check if payment method is available
         */
        isAvailable: function () {
            // Available if user is authenticated OR if new user wants to create account
            // OR if user was recognized by SimplyIN (checkEmail returned userExists=true)
            var authToken = sessionStorageManager.getAuthToken();
            var isNewUser = sessionStorageManager.isNewUser();
            var isRecognized = sessionStorageManager.isUserRecognized();

            var available = (authToken !== null && authToken !== '') || isNewUser || isRecognized;

            return available;
        },

        /**
         * Check if should show new account checkbox
         */
        shouldShowNewAccountCheckbox: function () {
            var authToken = sessionStorageManager.getAuthToken();
            var isNewUser = sessionStorageManager.isNewUser();
            var showCheckbox = this.showNewAccountCheckbox();

            return !authToken && isNewUser && showCheckbox;
        },

        /**
         * Load Simply.IN payment methods
         */
        loadPaymentMethods: function () {
            var self = this;
            var authToken = sessionStorageManager.getAuthToken();
            var isNewUser = sessionStorageManager.isNewUser();
            var isRecognized = sessionStorageManager.isUserRecognized();

            // Allow loading payment methods for:
            // - Authenticated users (has auth token)
            // - New users (creating account)
            // - Recognized users (checkEmail returned userExists=true, even without OTP)
            if (!authToken && !isNewUser && !isRecognized) {
                console.warn('SimplyIn: No auth token, not a new user, and not recognized. Waiting for authentication.');
                return;
            }

            ajaxClient.post('simplyin/api/getPaymentMethods', {
                authToken: authToken || null,
                isNewUser: isNewUser,
                isRecognized: isRecognized
            }).done(function (response) {
                    self.methodsLoaded(true);
                    if (response.success && response.paymentMethods) {
                        var methods = response.paymentMethods.map(function (method) {
                            method.code = method.type; // Assign code for selection logic
                            if (method.addCard && method.addCard.iframeUrl) {
                                method.iframeUrl = method.addCard.iframeUrl;
                            }
                            return method;
                        });

                        // ---------------------------------------------------------
                        // CURRENCY FILTERING: Remove BLIK for non-PLN currencies
                        // Matches PrestaShop plugin behavior
                        // ---------------------------------------------------------
                        var isBlikAvailable = self.isBlikAvailableForCurrency();
                        if (!isBlikAvailable) {
                            methods = methods.filter(function (method) {
                                var isBlik = method.type === 'blik' || 
                                            method.code === 'blik' || 
                                            (method.typeName && method.typeName.toUpperCase() === 'BLIK');
                                if (isBlik) {
                                    console.log('SimplyIn: BLIK payment method filtered out - not available for non-PLN currency');
                                }
                                return !isBlik;
                            });
                        }

                        // Extract payment provider info from the first method that has it
                        var providerInfo = null;
                        for (var i = 0; i < methods.length; i++) {
                            if (methods[i].paymentProvider) {
                                providerInfo = methods[i].paymentProvider;
                                break;
                            }
                        }
                        
                        // Update provider observables if we found provider info
                        if (providerInfo) {
                            if (providerInfo.name) {
                                self.paymentProviderName(providerInfo.name);
                            }
                            if (providerInfo.logoUrl) {
                                self.paymentProviderLogoUrl(providerInfo.logoUrl);
                            }
                            if (providerInfo.regulationsUrl) {
                                self.paymentProviderRegulationsUrl(providerInfo.regulationsUrl);
                            }
                            if (providerInfo.gdprUrl) {
                                self.paymentProviderGdprUrl(providerInfo.gdprUrl);
                            }
                        }

                        // ---------------------------------------------------------
                        // MERGE SAVED CARDS FROM FRONTEND SESSION DATA (only for authenticated users)
                        // ---------------------------------------------------------
                        if (authToken) {
                            var userData = sessionStorageManager.getUserData();

                            // Find add_card settings to reuse iframeUrl
                            var addCardMethod = methods.find(function (m) { return m.type === 'add_card'; });

                            if (userData) {
                                if (userData.paymentDetails && Array.isArray(userData.paymentDetails)) {
                                    userData.paymentDetails.forEach(function (card) {
                                        var brand = card.cardProvider || 'card';
                                        var last4 = card.cardNumberLastDigits || '****';
                                        
                                        // Use card name from API if available, fallback to brand name
                                        var cardName = card.name || card.cardName || self.capitalizeFirstLetter(brand);
                                        // Display format: "Card Name (**1234)" like WooCommerce
                                        var displayName = cardName + ' (**' + last4 + ')';

                                        // Use logoThumbnailUrl from API if available, otherwise use SimplyIN hosted URL
                                        var logoUrl = card.logoThumbnailUrl || card.logoUrl || self.getSimplyInCardLogo(brand);

                                        var savedCardMethod = {
                                            type: 'saved_card',
                                            name: displayName,
                                            code: 'saved_card_' + (card._id || Math.random().toString(36)),
                                            isSavedCard: true,
                                            cardToken: card.cardToken,
                                            last4: last4,
                                            brand: brand,
                                            cardName: cardName,
                                            cardId: card._id,
                                            logoThumbnailUrl: logoUrl,
                                            iframeUrl: addCardMethod ? addCardMethod.iframeUrl : null,
                                            addCard: addCardMethod ? addCardMethod.addCard : null // Propagate integratorId
                                        };

                                        methods.push(savedCardMethod);
                                    });
                                }
                            }
                        }
                        // ---------------------------------------------------------

                        self.availablePaymentMethods(methods);
                    } else {
                        // Refresh returned unauthenticated / no methods: clear any previously loaded
                        // list so a stale (or un-scoped) set is never left on screen. Fail closed.
                        self.availablePaymentMethods([]);
                        self.selectedPaymentMethod(null);
                        console.warn('SimplyIn: API success but no methods or failure flag', response);
                    }
            }).fail(function (xhr, status, error) {
                    self.methodsLoaded(true);
                    console.error('Failed to load Simply.IN payment methods', error, xhr.responseText);
            });
        },

        /**
         * Select a payment method
         */
        selectSimplyInPaymentMethod: function (method) {
            var self = this;
            
            if (this.selectedPaymentMethod() === method) {
                return true;
            }

            this.selectedPaymentMethod(method);

            // Initialize Iframe for BOTH New Card and Saved Card
            if (method.iframeUrl && (method.type === 'card' || method.type === 'add_card' || method.isSavedCard)) {
                // Short delay to allow DOM to update with if containers
                setTimeout(function () {
                    self.initCardIframe(method);
                }, 200);
            } else if (method.type === 'card' || method.type === 'add_card') {
                console.warn('SimplyIn: Missing iframeUrl for card method', method);
            }

            return true;
        },

        /**
         * Initialize Card Iframe
         */
        initCardIframe: function (method) {
            var self = this;
            var scriptId = 'simplyin-card-script';

            // If the card iframe library is already available, just render the fields.
            if (window.CCIframe) {
                self.renderCardFields();
                return;
            }

            // A previous attempt may have left a <script> tag that never defined
            // window.CCIframe (failed/aborted load). Trusting that dead tag makes every
            // subsequent method switch fall into the renderCardFields timeout banner.
            // Drop it so we always reload the script from scratch (matches Hyva loadCC).
            var existing = document.getElementById(scriptId);
            if (existing) {
                existing.remove();
            }

            fullScreenLoader.startLoader();

            var script = document.createElement('script');
            script.id = scriptId;
            script.src = method.iframeUrl;
            script.onload = function () {
                fullScreenLoader.stopLoader();
                $('.loading-mask').hide();
                self.renderCardFields();
            };
            script.onerror = function () {
                console.error('SimplyIn: Failed to load payment iframe script');
                fullScreenLoader.stopLoader();
                $('.loading-mask').hide();
                // Remove the dead tag so the next attempt can reload the script.
                var dead = document.getElementById(scriptId);
                if (dead) {
                    dead.remove();
                }
                self.messageContainer.addErrorMessage({
                    message: $.mage.__('Failed to load card payment. Please try again or refresh the page.')
                });
            };
            document.head.appendChild(script);
        },

        /**
         * Render Card Fields
         */
        renderCardFields: function () {
            var self = this;

            // Poll for CCIframe availability (max 2 seconds)
            var attempts = 0;
            var maxAttempts = 20;

            var checkInterval = setInterval(function () {
                attempts++;
                if (window.CCIframe) {
                    clearInterval(checkInterval);
                    self.initializeCCIframe();
                } else if (attempts >= maxAttempts) {
                    clearInterval(checkInterval);
                    console.error('SimplyIn: CCIframe not found in window object after timeout!');
                    // Drop the dead script tag so a retry / refresh can reload it.
                    var deadScript = document.getElementById('simplyin-card-script');
                    if (deadScript) {
                        deadScript.remove();
                    }
                    self.messageContainer.addErrorMessage({
                        message: $.mage.__('Failed to load card payment. Please try again or refresh the page.')
                    });
                }
            }, 100);
        },

        initializeCCIframe: function () {
            var method = this.selectedPaymentMethod();
            var integratorId = (method.addCard && method.addCard.integratorId) ? method.addCard.integratorId : 'SimplyIn';

            try {
                this.ccInstance = window.CCIframe({
                    integratorId: integratorId
                });

                var options = {
                    fonts: [{
                        family: "Inter",
                        src: "url(https://fonts.gstatic.com/s/inter/v18/UcCo3FwrK3iLTcviYwYZ8UA3.woff2) format('woff2')",
                        style: "normal",
                        weight: "100 900",
                    }],
                    styles: {
                        base: {
                            color: "rgba(0, 0, 0, 0.8)",
                            fontFamily: "Inter",
                            fontSize: "14px",
                        }
                    }
                };

                if (method.isSavedCard) {
                    // For Saved Card: No UI components needed for One Click (CVV optional/removed)
                } else {
                    // For New Card: Render All
                    this.ccInstance.createComponent("cardNumber", "#simplyin-card-number", options);
                    this.ccInstance.createComponent("cardExp", "#simplyin-card-expiry", options);
                    this.ccInstance.createComponent("cardCvv", "#simplyin-card-cvv", options);
                }

            } catch (e) {
                console.error('SimplyIn: Failed to init CCIframe', e);
            }
        },

        /**
         * Check if a method is selected
         */
        isMethodSelected: function (method) {
            var selected = this.selectedPaymentMethod();
            return selected && (selected.code === method.code); // Use unique code
        },

        /**
         * Validate phone number for new account creation
         * Uses the global simplyinAccountSection component for validation
         */
        validatePhoneNumber: function () {
            // Get the global SimplyIN account section component
            var simplyinSection = window.simplyinAccountSection;
            
            // If no section component or section is not visible, skip validation
            if (!simplyinSection || 
                typeof simplyinSection.shouldShowNewAccountSection !== 'function' ||
                !simplyinSection.shouldShowNewAccountSection()) {

                return true;
            }
            
            // If user unchecked the "create account" checkbox, skip validation
            if (!simplyinSection.createSimplyInAccount()) {
                return true;
            }
            
            // Validate phone number using the section component
            var phone = simplyinSection.phoneNumber();
            
            if (!phone || phone.trim() === '') {
                simplyinSection.phoneNumberError($.mage.__('The phone number is required.'));
                // Scroll to the phone field
                var phoneInput = document.querySelector('.simplyin-phone-number-input');
                if (phoneInput) {
                    phoneInput.focus();
                    phoneInput.scrollIntoView({ behavior: 'smooth', block: 'center' });
                }
                return false;
            }
            
            var phoneRegex = /^\d{6,15}$/;
            if (!phoneRegex.test(phone.replace(/[\s\-\(\)]/g, ''))) {
                simplyinSection.phoneNumberError($.mage.__('Please enter a valid phone number.'));
                var phoneInput = document.querySelector('.simplyin-phone-number-input');
                if (phoneInput) {
                    phoneInput.focus();
                }
                return false;
            }
            
            // Clear error
            simplyinSection.phoneNumberError('');
            return true;
        },

        /**
         * Initialize country dropdown with flag images
         */
        initCountryDropdownFlags: function () {
            var dropdown = document.getElementById('simplyin-country-code');
            if (!dropdown) {
                return;
            }

            // Add flag images to dropdown options using CSS background
            var options = dropdown.querySelectorAll('option');
            options.forEach(function (option) {
                var flagPath = option.getAttribute('data-flag');
                if (flagPath) {
                    // Store flag path for potential custom rendering
                    option.style.backgroundImage = 'url(' + flagPath + ')';
                    option.style.backgroundRepeat = 'no-repeat';
                    option.style.backgroundPosition = '8px center';
                    option.style.backgroundSize = '20px 15px';
                    option.style.paddingLeft = '36px';
                }
            });
        },

        /**
         * Toggle country dropdown
         */
        toggleCountryDropdown: function () {
            var isOpen = !this.countryDropdownOpen();
            this.countryDropdownOpen(isOpen);

            // Reset search when opening
            if (isOpen) {
                this.countrySearchQuery('');
                this.filteredCountryCodes(this.countryCodes());

                // Focus search input after dropdown opens
                var self = this;
                setTimeout(function () {
                    var searchInput = document.querySelector('.simplyin-country-search-input');
                    if (searchInput) {
                        searchInput.focus();
                    }
                }, 100);
            }
        },

        /**
         * Filter countries based on search query
         */
        filterCountries: function (query) {
            if (!query || query.trim() === '') {
                this.filteredCountryCodes(this.countryCodes());
                return;
            }

            var searchTerm = query.toLowerCase().trim();
            var filtered = this.countryCodes().filter(function (country) {
                var countryName = country.name.toLowerCase();
                var countryCode = country.code.toLowerCase();
                var countryIso = country.iso.toLowerCase();

                // Match by name, code, or ISO
                return countryName.indexOf(searchTerm) === 0 ||
                    countryName.indexOf(' ' + searchTerm) !== -1 ||
                    countryCode.indexOf(searchTerm) !== -1 ||
                    countryIso.indexOf(searchTerm) !== -1;
            });

            this.filteredCountryCodes(filtered);
        },

        /**
         * Handle keyboard navigation in country search
         */
        handleCountrySearchKeydown: function (data, event) {
            // Prevent dropdown from closing on keydown
            event.stopPropagation();

            // Handle Enter key - select first filtered country
            if (event.keyCode === 13) { // Enter
                event.preventDefault();
                var filtered = this.filteredCountryCodes();
                if (filtered.length > 0) {
                    this.selectCountry(filtered[0]);
                }
                return false;
            }

            // Handle Escape key - close dropdown
            if (event.keyCode === 27) { // Escape
                event.preventDefault();
                this.countryDropdownOpen(false);
                return false;
            }

            return true;
        },

        /**
         * Select a country from dropdown
         */
        selectCountry: function (country) {
            this.selectedCountryIso(country.iso);
            this.selectedCountryCode(country.code);
            this.countryDropdownOpen(false);
            this.countrySearchQuery('');
        },

        /**
         * Get selected country flag path
         */
        getSelectedCountryFlag: function () {
            var countries = this.countryCodes();
            var selectedIso = this.selectedCountryIso();
            var country = countries.find(function (c) {
                return c.iso === selectedIso;
            });
            return country ? country.flagPath : '';
        },

        /**
         * Get selected country name (returns phone code for display)
         */
        getSelectedCountryName: function () {
            var countries = this.countryCodes();
            var selectedIso = this.selectedCountryIso();
            var country = countries.find(function (c) {
                return c.iso === selectedIso;
            });
            return country ? country.code : '';
        },

        /**
         * Setup click outside handler for dropdown
         */
        setupDropdownClickOutside: function () {
            var self = this;
            $(document).on('click', function (event) {
                var dropdown = $('.simplyin-custom-dropdown');
                if (dropdown.length && !dropdown.is(event.target) && dropdown.has(event.target).length === 0) {
                    self.countryDropdownOpen(false);
                }
            });
        },

        /**
         * Place order
         */
        placeOrder: function (data, event) {
            var self = this;
            var selectedMethod = this.selectedPaymentMethod();

            // Prevent default form submission
            if (event) {
                event.preventDefault();
            }

            // Validate phone number first if new account creation is enabled
            if (!this.validatePhoneNumber()) {
                return false;
            }

            if (!this.validate()) {
                return false;
            }

            var authToken = sessionStorageManager.getAuthToken();

            if (authToken && !selectedMethod) {
                self.messageContainer.addErrorMessage({
                    message: $.mage.__('Please select a payment method.')
                });
                return false;
            }

            // If Card method (New CARD only), tokenize first
            if (selectedMethod && selectedMethod.type === 'add_card' && !selectedMethod.isSavedCard) {

                if (!this.ccInstance) {
                    console.error('SimplyIn: ccInstance not initialized');
                    self.messageContainer.addErrorMessage({
                        message: $.mage.__('Card payment not ready. Please wait for the card form to load.')
                    });
                    return false;
                }

                fullScreenLoader.startLoader();

                var tokenOptions = {};
                
                this.ccInstance.createToken(tokenOptions).then(function (result) {
                    if (result && result.oneTimeToken) {
                        // Token created, proceed to place order with token data
                        self.placeOrderWithCardToken(result);
                    } else {
                        fullScreenLoader.stopLoader();
                        $('.loading-mask').hide();
                        self.messageContainer.addErrorMessage({
                            message: $.mage.__('Invalid card data. Please check details.')
                        });
                    }
                }).catch(function (error) {
                    fullScreenLoader.stopLoader();
                    $('.loading-mask').hide();
                    console.error('SimplyIn: Token Error', error);
                    self.messageContainer.addErrorMessage({
                        message: $.mage.__('Card processing failed: ') + (error.message || 'Please try again.')
                    });
                });
                return false;
            }

            // For Saved Card, skip tokenization and place order directly (One Click)
            if (selectedMethod && selectedMethod.isSavedCard) {
                this.processStandardOrder();
                return false;
            }

            // For BLIK and other payment methods
            this.processStandardOrder();
            return false;
        },

        placeOrderWithCardToken: function (tokenData) {
            var self = this;
            this.cardTokenData = tokenData;
            this.processStandardOrder();
        },

        processStandardOrder: function () {
            var self = this;
            fullScreenLoader.startLoader();

            var authToken = sessionStorageManager.getAuthToken();
            var isNewUser = sessionStorageManager.isNewUser();
            var shouldCreateAccount = this.createSimplyInAccount();

            // NEW FLOW: Process payment FIRST, then place Magento order only if payment succeeds
            // This allows customer to retry payment if it fails without creating an order
            self.processPaymentFirst().done(function (paymentResponse) {
                if (paymentResponse.success) {
                    // Payment processed successfully (or pending 3DS)
                    // Now place the Magento order
                    $.when(self.getPlaceOrderDeferredObject())
                        .done(function (orderId, response) {
                            // Store the Magento order ID
                            self.magentoOrderId = orderId;
                            
                            // Handle payment response (3DS redirect, BLIK verification, etc.)
                            self.handlePaymentResponse(paymentResponse, orderId);
                        })
                        .fail(function (response) {
                            console.error('SimplyIn: Failed to place Magento order after payment', response);
                            fullScreenLoader.stopLoader();
                            $('.loading-mask').hide();
                            self.isPlaceOrderActionAllowed(true);

                            // Payment was processed but order creation failed
                            // This is a critical error - payment was taken but no order
                            self.messageContainer.addErrorMessage({
                                message: $.mage.__('Payment was processed but order creation failed. Please contact support with your payment reference.')
                            });
                        });
                } else {
                    // Payment failed - stay on checkout page, allow retry
                    fullScreenLoader.stopLoader();
                    $('.loading-mask').hide();
                    self.isPlaceOrderActionAllowed(true);
                    
                    // Show error message
                    self.messageContainer.addErrorMessage({
                        message: paymentResponse.message || $.mage.__('Payment processing failed. Please try again or use a different payment method.')
                    });
                }
            }).fail(function (xhr, status, error) {
                console.error('SimplyIn: Payment processing request failed', error);
                fullScreenLoader.stopLoader();
                $('.loading-mask').hide();
                self.isPlaceOrderActionAllowed(true);
                
                var errorMessage = $.mage.__('Payment processing failed. Please try again.');
                if (xhr && xhr.responseJSON && xhr.responseJSON.message) {
                    errorMessage = xhr.responseJSON.message;
                }
                
                self.messageContainer.addErrorMessage({
                    message: errorMessage
                });
            });
        },

        /**
         * Process payment first without creating Magento order
         * This allows retry if payment fails
         */
        processPaymentFirst: function () {
            var self = this;
            var authToken = sessionStorageManager.getAuthToken();
            var isNewUser = sessionStorageManager.isNewUser();
            
            // Check if user wants to create account using global section component
            var simplyinSection = window.simplyinAccountSection;
            var createAccount = simplyinSection && 
                simplyinSection.shouldShowNewAccountSection && 
                simplyinSection.shouldShowNewAccountSection() && 
                simplyinSection.createSimplyInAccount();

            var quoteData = quote.totals();
            var shippingAddress = quote.shippingAddress();
            var billingAddress = quote.billingAddress();
            var selectedMethod = this.selectedPaymentMethod();

            var orderData = {
                quoteId: quote.getQuoteId(),
                // No magentoOrderId yet - order not created
                price: quoteData.grand_total,
                shippingPrice: quoteData.shipping_amount || 0,
                currency: quoteData.quote_currency_code,
                items: this.getOrderItems(),
                shippingData: this.formatAddress(shippingAddress, 'shipping'),
                billingData: this.formatAddress(billingAddress, 'billing'),
                shopName: 'Magento',
                shopUserEmail: quote.guestEmail || (window.customerData && window.customerData.email),
                paymentMethod: selectedMethod ? selectedMethod.type : null,
                paymentMethodName: selectedMethod ? selectedMethod.name : null,
                saveCard: (isNewUser && createAccount) ? true : this.saveCard(),
                blikCode: (selectedMethod && (selectedMethod.type === 'blik' || selectedMethod.code === 'blik')) ? this.blikCode() : null
            };

            // Add phone number if creating account
            if (simplyinSection && 
                simplyinSection.shouldShowNewAccountSection && 
                simplyinSection.shouldShowNewAccountSection() && 
                simplyinSection.createSimplyInAccount()) {
                orderData.phoneNumber = simplyinSection.selectedCountryCode() + simplyinSection.phoneNumber().trim();
                orderData.countryCode = simplyinSection.selectedCountryCode();
            }

            // Add parcel locker data if delivery type is parcel_locker
            var deliveryType = sessionStorageManager.getSelectedDeliveryType();
            orderData.deliveryType = deliveryType;

            if (deliveryType === 'parcel_locker') {
                var parcelLockerData = sessionStorageManager.getSelectedParcelLocker();
                if (parcelLockerData) {
                    orderData.parcelLockerData = parcelLockerData;
                }
            }

            // Get user data from session storage to check for existing addresses
            var userData = sessionStorageManager.getUserData();

            // PRIORITY 1: Use COMPLETE stored address objects from session storage
            // This ensures ALL fields (including _id, icon, addressName, taxId, etc.) are sent to the API
            // The API may require all fields to recognize an existing address
            var storedBillingAddress = sessionStorageManager.getItem('selected_billing_address');
            var storedShippingAddress = sessionStorageManager.getItem('selected_shipping_address');
            
            if (storedBillingAddress) {
                try {
                    var billingAddrObj = typeof storedBillingAddress === 'string' ? 
                        JSON.parse(storedBillingAddress) : storedBillingAddress;
                    
                    // Use the complete stored address, preserving all SimplyIN fields
                    orderData.billingData = billingAddrObj;
                } catch (e) {
                    console.error('SimplyIn: Error parsing stored billing address:', e);
                    // Fallback to ID-only approach
                    var storedBillingId = sessionStorageManager.getItem('selected_billing_address_id');
                    if (storedBillingId) {
                        orderData.billingData._id = storedBillingId;
                    }
                }
            } else {
                // Fallback: try to use just the ID
                var storedBillingId = sessionStorageManager.getItem('selected_billing_address_id');
                if (storedBillingId) {
                    orderData.billingData._id = storedBillingId;
                }
            }
            
            if (storedShippingAddress) {
                try {
                    var shippingAddrObj = typeof storedShippingAddress === 'string' ? 
                        JSON.parse(storedShippingAddress) : storedShippingAddress;
                    
                    // Use the complete stored address, preserving all SimplyIN fields
                    orderData.shippingData = shippingAddrObj;
                } catch (e) {
                    console.error('SimplyIn: Error parsing stored shipping address:', e);
                    // Fallback to ID-only approach
                    var storedShippingId = sessionStorageManager.getItem('selected_shipping_address_id');
                    if (storedShippingId) {
                        orderData.shippingData._id = storedShippingId;
                    }
                }
            } else {
                // Fallback: try to use just the ID
                var storedShippingId = sessionStorageManager.getItem('selected_shipping_address_id');
                if (storedShippingId) {
                    orderData.shippingData._id = storedShippingId;
                }
            }

            // PRIORITY 2: Fallback to matching addresses if no stored addresses (only for authenticated users)
            // This handles cases where user didn't select from modal but addresses might still match
            if (userData && authToken) {
                if (!orderData.billingData._id) {
                    var billingAddressId = this.findMatchingAddressId(
                        orderData.billingData,
                        userData.billingAddresses || []
                    );
                    if (billingAddressId) {
                        orderData.billingData._id = billingAddressId;
                    }
                }
                
                if (!orderData.shippingData._id) {
                    var shippingAddressId = this.findMatchingAddressId(
                        orderData.shippingData,
                        userData.shippingAddresses || []
                    );
                    if (shippingAddressId) {
                        orderData.shippingData._id = shippingAddressId;
                    }
                }
            }

            // Add card token data if available
            if (this.cardTokenData) {
                orderData.cardToken = this.cardTokenData.oneTimeToken;
                orderData.cardLast4 = this.cardTokenData.last4digits;
                orderData.cardProvider = (this.cardTokenData.brand || 'visa').toLowerCase();
                orderData.cardName = (isNewUser && createAccount) ? 'Card' : (this.cardName() || this.cardTokenData.cardholderName || 'Card');
            }

            // Handle saved card payment
            if (selectedMethod && selectedMethod.isSavedCard) {
                orderData.useSavedCard = true;
                orderData.savedCardId = selectedMethod.cardId;
                orderData.savedCardToken = selectedMethod.cardToken;
                orderData.cardLast4 = selectedMethod.last4;
                orderData.cardBrand = selectedMethod.brand;
            }

            return ajaxClient.post('simplyin/api/processPayment', {
                orderData: orderData,
                authToken: authToken,
                isNewUser: isNewUser,
                createAccount: createAccount,
                paymentOnly: true  // Flag to indicate payment-first flow
            });
        },

        /**
         * Handle payment response after Magento order is placed
         */
        handlePaymentResponse: function (paymentResponse, magentoOrderId) {
            var self = this;
            
            // Store order info
            if (paymentResponse.order && paymentResponse.order._id) {
                this.simplyInOrderId = paymentResponse.order._id;
            }

            if (paymentResponse.paymentInfo) {
                this.paymentInfo = paymentResponse.paymentInfo;
            }

            if (paymentResponse.authToken) {
                sessionStorageManager.setAuthToken(paymentResponse.authToken);
            }

            // Update Magento order with payment info
            this.updateMagentoOrderWithPayment(magentoOrderId, paymentResponse);

            // Check if 3D Secure redirect is required
            var redirectUrl = paymentResponse.paymentInfo ? paymentResponse.paymentInfo.simplyin_redirect_url : null;
            var paymentStatus = paymentResponse.paymentInfo ? paymentResponse.paymentInfo.simplyin_payment_status : null;

            if (redirectUrl && paymentStatus === 'PENDING') {
                // 3D Secure redirect required
                this.store3DSSessionData(paymentResponse, magentoOrderId);
                
                fullScreenLoader.stopLoader();
                $('.loading-mask').hide();
                
                window.location.replace(redirectUrl);
                return;
            }

            // Check if BLIK or other payment that needs verification
            var selectedMethod = this.selectedPaymentMethod();
            var isBlik = selectedMethod && (selectedMethod.type === 'blik' || selectedMethod.code === 'blik');
            var paymentId = paymentResponse.paymentInfo ? paymentResponse.paymentInfo.simplyin_payment_id : null;
            
            if (paymentId && (isBlik || paymentStatus === 'PENDING')) {
                this.store3DSSessionData(paymentResponse, magentoOrderId);
            }

            // Payment complete - redirect to success
            this.redirectToSuccess();
        },

        /**
         * Update Magento order with payment information
         */
        updateMagentoOrderWithPayment: function (magentoOrderId, paymentResponse) {
            // Fire and forget - update order with payment info
            ajaxClient.postSilent('simplyin/api/updateOrderPayment', {
                orderId: magentoOrderId,
                paymentInfo: paymentResponse.paymentInfo,
                simplyinOrderId: paymentResponse.order ? paymentResponse.order._id : null
            });
        },

        /**
         * Create SimplyIN order after Magento order is placed
         * @deprecated Use processPaymentFirst flow instead
         */
        createSimplyInOrderAfterMagento: function (magentoOrderId) {
            var self = this;
            
            this.createSimplyInOrder(magentoOrderId).done(function (response) {
                if (response.success) {
                    // Store order info
                    if (response.order && response.order._id) {
                        self.simplyInOrderId = response.order._id;
                    }

                    if (response.paymentInfo) {
                        self.paymentInfo = response.paymentInfo;
                    }

                    if (response.authToken) {
                        sessionStorageManager.setAuthToken(response.authToken);
                    }

                    // Check if 3D Secure redirect is required
                    var redirectUrl = response.paymentInfo ? response.paymentInfo.simplyin_redirect_url : null;
                    var paymentStatus = response.paymentInfo ? response.paymentInfo.simplyin_payment_status : null;

                    if (redirectUrl && paymentStatus === 'PENDING') {
                        // 3D Secure redirect required
                        // Store payment state before redirect (include Magento order ID)
                        self.store3DSSessionData(response, magentoOrderId);
                        
                        // Stop loader before redirect
                        fullScreenLoader.stopLoader();
                        $('.loading-mask').hide();
                        
                        // Redirect to 3D Secure page (handled by payment provider)
                        window.location.replace(redirectUrl);
                        return;
                    }

                    // No 3D Secure required - check if BLIK or other payment that needs verification
                    var selectedMethod = self.selectedPaymentMethod();
                    var isBlik = selectedMethod && (selectedMethod.type === 'blik' || selectedMethod.code === 'blik');
                    var paymentId = response.paymentInfo ? response.paymentInfo.simplyin_payment_id : null;
                    
                    // For BLIK and other payments that need status verification, store session data
                    if (paymentId && (isBlik || paymentStatus === 'PENDING')) {
                        self.store3DSSessionData(response, magentoOrderId);
                    }

                    // Payment is complete or pending verification - redirect to success
                    self.redirectToSuccess();
                } else {
                    // Payment failed - stay on checkout page for retry
                    fullScreenLoader.stopLoader();
                    $('.loading-mask').hide();
                    self.isPlaceOrderActionAllowed(true);
                    
                    self.messageContainer.addErrorMessage({
                        message: response.message || $.mage.__('Payment processing failed. Please try again or use a different payment method.')
                    });
                }
            }).fail(function (xhr, status, error) {
                console.error('SimplyIn: Failed to create SimplyIN order', error);
                fullScreenLoader.stopLoader();
                $('.loading-mask').hide();
                self.isPlaceOrderActionAllowed(true);
                
                var errorMessage = $.mage.__('Payment processing failed. Please try again.');
                if (xhr && xhr.responseJSON && xhr.responseJSON.message) {
                    errorMessage = xhr.responseJSON.message;
                }
                
                self.messageContainer.addErrorMessage({
                    message: errorMessage
                });
            });
        },

        /**
         * Place Magento order using standard checkout flow
         * @deprecated Use processStandardOrder instead which places Magento order first
         */
        placeMagentoOrder: function () {
            var self = this;

            // Use Magento's standard place order
            $.when(this.getPlaceOrderDeferredObject())
                .done(function (orderId, response) {
                    // Redirect to success page
                    self.redirectToSuccess();
                })
                .fail(function (response) {
                    console.error('SimplyIn: Failed to place Magento order', response);
                    fullScreenLoader.stopLoader();
                    $('.loading-mask').hide();
                    self.isPlaceOrderActionAllowed(true);

                    // Show error message
                    if (response && response.responseJSON && response.responseJSON.message) {
                        self.messageContainer.addErrorMessage({
                            message: response.responseJSON.message
                        });
                    } else {
                        self.messageContainer.addErrorMessage({
                            message: $.mage.__('Failed to place order. Please try again.')
                        });
                    }
                });
        },

        /**
         * Store 3D Secure session data before redirect (also used for BLIK verification)
         */
        store3DSSessionData: function (response, magentoOrderId) {
            try {
                var selectedMethod = this.selectedPaymentMethod();
                var isBlik = selectedMethod && (selectedMethod.type === 'blik' || selectedMethod.code === 'blik');
                
                // Get payment method logo - check both logoThumbnailUrl and logoUrl
                var methodLogoUrl = selectedMethod ? (selectedMethod.logoThumbnailUrl || selectedMethod.logoUrl) : null;
                var methodName = selectedMethod ? selectedMethod.name : 'Card';
                
                // For BLIK, ensure we have proper name
                if (isBlik) {
                    methodName = selectedMethod.name || 'BLIK';
                }
                
                var sessionData = {
                    simplyInOrderId: this.simplyInOrderId,
                    magentoOrderId: magentoOrderId || this.magentoOrderId,
                    paymentInfo: this.paymentInfo,
                    paymentId: response.paymentInfo ? response.paymentInfo.simplyin_payment_id : null,
                    authToken: sessionStorageManager.getAuthToken(),
                    paymentMethod: selectedMethod ? selectedMethod.type : 'card',
                    paymentMethodName: methodName,
                    paymentMethodLogoUrl: methodLogoUrl,
                    isBlik: isBlik,
                    providerName: this.paymentProviderName ? this.paymentProviderName() : null,
                    providerLogoUrl: this.paymentProviderLogoUrl ? this.paymentProviderLogoUrl() : null,
                    timestamp: Date.now()
                };
                
                // Store in sessionStorage
                sessionStorage.setItem('simplyin_3ds_session', JSON.stringify(sessionData));
                
                // Also store in cookie for reliability across redirects (expires in 30 minutes)
                var expires = new Date();
                expires.setTime(expires.getTime() + (30 * 60 * 1000));
                document.cookie = 'simplyin_3ds_session=' + encodeURIComponent(JSON.stringify(sessionData)) + 
                    ';expires=' + expires.toUTCString() + ';path=/;SameSite=Lax';
            } catch (e) {
                console.error('SimplyIn: Failed to store payment session data:', e);
            }
        },

        /**
         * Check if returning from 3D Secure redirect
         */
        checkReturn3DS: function () {
            try {
                // First try sessionStorage
                var sessionDataStr = sessionStorage.getItem('simplyin_3ds_session');
                
                // If not in sessionStorage, try cookie
                if (!sessionDataStr) {
                    var cookies = document.cookie.split(';');
                    for (var i = 0; i < cookies.length; i++) {
                        var cookie = cookies[i].trim();
                        if (cookie.indexOf('simplyin_3ds_session=') === 0) {
                            sessionDataStr = decodeURIComponent(cookie.substring('simplyin_3ds_session='.length));
                            break;
                        }
                    }
                }
                
                if (!sessionDataStr) {
                    return null;
                }
                
                var sessionData = JSON.parse(sessionDataStr);
                
                // Check if session is still valid (30 minutes)
                var elapsed = Date.now() - sessionData.timestamp;
                
                if (elapsed > 30 * 60 * 1000) {
                    this.clear3DSSession();
                    return null;
                }
                
                return sessionData;
            } catch (e) {
                console.error('SimplyIn: Failed to check 3DS return:', e);
                return null;
            }
        },

        /**
         * Clear 3D Secure session data
         */
        clear3DSSession: function () {
            try {
                // Clear sessionStorage
                sessionStorage.removeItem('simplyin_3ds_session');
                
                // Clear cookie
                document.cookie = 'simplyin_3ds_session=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/';
            } catch (e) {
                console.warn('SimplyIn: Failed to clear 3DS session:', e);
            }
        },

        /**
         * Handle return from 3D Secure redirect
         */
        handle3DSReturn: function () {
            var self = this;
            
            var sessionData = this.checkReturn3DS();
            
            if (!sessionData) {
                return;
            }
            
            // Restore session data
            if (sessionData.simplyInOrderId) {
                this.simplyInOrderId = sessionData.simplyInOrderId;
            }
            if (sessionData.magentoOrderId) {
                this.magentoOrderId = sessionData.magentoOrderId;
            }
            if (sessionData.paymentInfo) {
                this.paymentInfo = sessionData.paymentInfo;
            }
            if (sessionData.authToken) {
                sessionStorageManager.setAuthToken(sessionData.authToken);
            }
            
            // Clear the 3DS session data
            this.clear3DSSession();
            
            // Start polling for payment status
            if (sessionData.paymentId) {
                fullScreenLoader.startLoader();
                
                this.pollPaymentStatus(sessionData.paymentId, sessionData.authToken, sessionData.magentoOrderId);
            } else if (sessionData.magentoOrderId) {
                // No payment ID but we have Magento order - redirect to success
                this.redirectToSuccess();
            }
        },

        /**
         * Poll payment status after 3D Secure return
         * @param {string} paymentId - The payment ID to check
         * @param {string} authToken - The auth token
         * @param {string} magentoOrderId - The Magento order ID (order already exists)
         */
        pollPaymentStatus: function (paymentId, authToken, magentoOrderId) {
            var self = this;
            var attempts = 0;
            var maxAttempts = 30;
            var pollInterval = 2000; // 2 seconds
            
            var poll = function () {
                attempts++;
                
                ajaxClient.postSilent('simplyin/api/checkPaymentStatus', {
                    paymentId: paymentId,
                    authToken: authToken,
                    orderId: magentoOrderId // Pass order ID to check local status
                }).done(function (response) {
                    if (response.success && response.status) {
                        if (response.status === 'COMPLETED' || response.status === 'SUCCESS' || response.status === 'PAID') {
                            // Payment completed - Magento order already exists, just redirect to success
                            self.redirectToSuccess();
                        } else if (response.status === 'FAILED' || response.status === 'CANCELLED' || response.status === 'REJECTED') {
                            // Payment failed - Magento order exists but payment failed
                            // Order will remain in "pending payment" status
                            fullScreenLoader.stopLoader();
                            $('.loading-mask').hide();
                            self.messageContainer.addErrorMessage({
                                message: $.mage.__('Payment failed or was cancelled. Your order has been created but requires payment.')
                            });
                            // Still redirect to success page after delay - order exists
                            setTimeout(function() {
                                self.redirectToSuccess();
                            }, 3000);
                        } else if (response.status === 'PENDING' && attempts < maxAttempts) {
                            // Still pending, continue polling
                            setTimeout(poll, pollInterval);
                        } else {
                            // Max attempts reached - payment is still being processed
                            // This is normal for 3DS payments - webhook will update the order
                            fullScreenLoader.stopLoader();
                            $('.loading-mask').hide();
                            // Don't show error - payment might still be processing
                            // Just redirect to success page
                            self.redirectToSuccess();
                        }
                    } else {
                        // Error in response
                        if (attempts < maxAttempts) {
                            setTimeout(poll, pollInterval);
                        } else {
                            fullScreenLoader.stopLoader();
                            $('.loading-mask').hide();
                            // Don't show error - just redirect to success
                            self.redirectToSuccess();
                        }
                    }
                }).fail(function (xhr, status, error) {
                    console.error('SimplyIn: Payment status check failed:', error);
                    if (attempts < maxAttempts) {
                        setTimeout(poll, pollInterval);
                    } else {
                        fullScreenLoader.stopLoader();
                        $('.loading-mask').hide();
                        // Don't show error - just redirect to success
                        self.redirectToSuccess();
                    }
                });
            };
            
            // Start polling
            poll();
        },

        /**
         * Redirect to success page
         */
        redirectToSuccess: function () {
            fullScreenLoader.stopLoader();
            $('.loading-mask').hide();

            // Use direct URL redirect to ensure we reach the success page
            // The checkout session should already have the order info from getPlaceOrderDeferredObject()
            var successUrl = window.checkoutConfig.defaultSuccessPageUrl;
            if (!successUrl) {
                successUrl = urlBuilder.build('checkout/onepage/success');
            }
            
            window.location.href = successUrl;
        },

        /**
         * Format card name
         */
        formatCardName: function (brand, last4) {
            brand = brand.charAt(0).toUpperCase() + brand.slice(1);
            return brand + ' •••• ' + last4;
        },

        /**
         * Get card brand logo
         */
        getCardBrandLogo: function (brand) {
            var brandLower = brand.toLowerCase();
            var logos = {
                'visa': 'https://js.stripe.com/v3/fingerprinted/img/visa-729c05c240c4bdb47b03ac81d9945bfe.svg',
                'mastercard': 'https://js.stripe.com/v3/fingerprinted/img/mastercard-4d8844094130711885b5e41b28c9848f.svg',
                'amex': 'https://js.stripe.com/v3/fingerprinted/img/amex-a49b82f46c5cd6a96a6e418a6ca1717c.svg',
                'discover': 'https://js.stripe.com/v3/fingerprinted/img/discover-ac52cd46f89fa40a29a0bfb954e33173.svg'
            };
            return logos[brandLower] || '';
        },

        /**
         * Get SimplyIN hosted card brand logo URL
         * Uses the same URL pattern as WooCommerce plugin
         */
        getSimplyInCardLogo: function (brand) {
            var brandLower = brand.toLowerCase();
            // SimplyIN hosted card provider logos
            var baseUrl = 'https://sasincoreordersimgpreprd.blob.core.windows.net/app-resources/img/card-providers/';
            return baseUrl + brandLower + '.svg';
        },

        /**
         * Capitalize first letter of a string
         */
        capitalizeFirstLetter: function (str) {
            if (!str) return '';
            return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
        },

        /**
         * Get combined BLIK code from individual digit observables
         */
        getBlikCode: function () {
            return (this.blikDigit1() || '') +
                   (this.blikDigit2() || '') +
                   (this.blikDigit3() || '') +
                   (this.blikDigit4() || '') +
                   (this.blikDigit5() || '') +
                   (this.blikDigit6() || '');
        },

        /**
         * Update combined BLIK code from individual digits
         */
        updateBlikCode: function () {
            var code = (this.blikDigit1() || '') +
                       (this.blikDigit2() || '') +
                       (this.blikDigit3() || '') +
                       (this.blikDigit4() || '') +
                       (this.blikDigit5() || '') +
                       (this.blikDigit6() || '');
            this.blikCode(code);
        },

        /**
         * Handle BLIK digit input - auto-focus to next input
         * Note: 'this' is bound to the component via $parent in template
         */
        handleBlikInput: function (viewModel, event) {
            var self = this; // 'this' is the component ($parent)
            var input = event.target;
            var index = parseInt(input.getAttribute('data-index'), 10);
            var value = input.value;

            // Only allow digits
            if (value && !/^\d$/.test(value)) {
                input.value = '';
                // Clear the observable too
                var digitObservables = [self.blikDigit1, self.blikDigit2, self.blikDigit3, self.blikDigit4, self.blikDigit5, self.blikDigit6];
                if (digitObservables[index]) {
                    digitObservables[index]('');
                }
                return true;
            }

            // Auto-focus to next input if digit entered
            if (value && index < 5) {
                var nextInput = document.querySelector('.simplyin-blik-digit[data-index="' + (index + 1) + '"]');
                if (nextInput) {
                    setTimeout(function() {
                        nextInput.focus();
                        nextInput.select();
                    }, 10);
                }
            }

            // Update the combined blikCode observable
            self.updateBlikCode();

            return true;
        },

        /**
         * Handle BLIK keydown - handle backspace navigation
         */
        handleBlikKeydown: function (viewModel, event) {
            var input = event.target;
            var index = parseInt(input.getAttribute('data-index'), 10);

            // Handle backspace - go to previous input if current is empty
            if (event.keyCode === 8 && !input.value && index > 0) {
                var prevInput = document.querySelector('.simplyin-blik-digit[data-index="' + (index - 1) + '"]');
                if (prevInput) {
                    setTimeout(function() {
                        prevInput.focus();
                        prevInput.select();
                    }, 10);
                }
            }

            // Handle left arrow
            if (event.keyCode === 37 && index > 0) {
                var prevInput = document.querySelector('.simplyin-blik-digit[data-index="' + (index - 1) + '"]');
                if (prevInput) {
                    prevInput.focus();
                }
            }

            // Handle right arrow
            if (event.keyCode === 39 && index < 5) {
                var nextInput = document.querySelector('.simplyin-blik-digit[data-index="' + (index + 1) + '"]');
                if (nextInput) {
                    nextInput.focus();
                }
            }

            return true;
        },

        /**
         * Handle BLIK paste - distribute digits across inputs
         */
        handleBlikPaste: function (viewModel, event) {
            var self = this; // 'this' is the component ($parent)
            
            // Get clipboard data - handle both jQuery event and native event
            var clipboardData;
            if (event.originalEvent && event.originalEvent.clipboardData) {
                clipboardData = event.originalEvent.clipboardData;
            } else if (event.clipboardData) {
                clipboardData = event.clipboardData;
            } else if (window.clipboardData) {
                clipboardData = window.clipboardData;
            }
            
            var pastedText = clipboardData ? clipboardData.getData('text') || clipboardData.getData('Text') : '';

            // Extract only digits
            var digits = pastedText.replace(/\D/g, '').substring(0, 6);

            if (digits.length > 0) {
                event.preventDefault();
                event.stopPropagation();

                // Set each digit observable
                self.blikDigit1(digits[0] || '');
                self.blikDigit2(digits[1] || '');
                self.blikDigit3(digits[2] || '');
                self.blikDigit4(digits[3] || '');
                self.blikDigit5(digits[4] || '');
                self.blikDigit6(digits[5] || '');

                // Update combined code
                self.updateBlikCode();

                // Focus last filled input or the 6th input
                var focusIndex = Math.min(digits.length, 5);
                var focusInput = document.querySelector('.simplyin-blik-digit[data-index="' + focusIndex + '"]');
                if (focusInput) {
                    setTimeout(function() {
                        focusInput.focus();
                    }, 10);
                }
                
                return false;
            }

            return true;
        },

        /**
         * Validate payment data
         */
        validate: function () {
            var method = this.selectedPaymentMethod();
            if (!method) {
                this.messageContainer.addErrorMessage({
                    message: $.mage.__('Please select a payment method.')
                });
                return false;
            }

            // Validate saved card logic checks
            // Since we use Tokenizer now, we rely on createToken() failure for validation.
            // The savedCardCvv observable is no longer bound to an input.
            /*
            if (method.isSavedCard) {
                var cvv = this.savedCardCvv();
                if (!cvv || !/^\d{3,4}$/.test(cvv)) {
                    this.messageContainer.addErrorMessage({
                        message: 'Please enter a valid CVV (3 or 4 digits).'
                    });
                    return false;
                }
            }
            */

            if (method.type === 'blik' || method.code === 'blik') {
                var code = this.blikCode();
                if (!code || !/^\d{6}$/.test(code)) {
                    this.messageContainer.addErrorMessage({
                        message: $.mage.__('The BLIK code must be exactly 6 digits.')
                    });
                    return false;
                }
            }

            return true;
        },

        /**
         * Get data to send to backend
         */
        getData: function () {
            var additionalData = {
                'simplyin_order_id': this.simplyInOrderId
            };

            // Include payment info if available
            if (this.paymentInfo) {
                $.extend(additionalData, this.paymentInfo);
            }

            // Include new account creation data if applicable - use global section component
            var simplyinSection = window.simplyinAccountSection;
            if (simplyinSection && 
                simplyinSection.shouldShowNewAccountSection && 
                simplyinSection.shouldShowNewAccountSection() && 
                simplyinSection.createSimplyInAccount()) {
                additionalData.simplyin_create_account = true;
                additionalData.simplyin_phone_number = simplyinSection.selectedCountryCode() + simplyinSection.phoneNumber().trim();
                additionalData.simplyin_country_code = simplyinSection.selectedCountryCode();
            }

            return {
                'method': this.item.method,
                'additional_data': additionalData
            };
        },

        /**
         * Create order in Simply.IN
         * @param {string} magentoOrderId - The Magento order increment ID (optional, for new flow)
         */
        createSimplyInOrder: function (magentoOrderId) {
            var self = this;
            var authToken = sessionStorageManager.getAuthToken();
            var isNewUser = sessionStorageManager.isNewUser();
            
            // Check if user wants to create account using global section component
            var simplyinSection = window.simplyinAccountSection;
            var createAccount = simplyinSection && 
                simplyinSection.shouldShowNewAccountSection && 
                simplyinSection.shouldShowNewAccountSection() && 
                simplyinSection.createSimplyInAccount();

            var quoteData = quote.totals();
            var shippingAddress = quote.shippingAddress();
            var billingAddress = quote.billingAddress();
            var selectedMethod = this.selectedPaymentMethod();

            // Get user data from session storage to check for existing addresses
            var userData = sessionStorageManager.getUserData();

            var orderData = {
                quoteId: quote.getQuoteId(), // Send quote ID to backend
                magentoOrderId: magentoOrderId, // Pass the Magento order ID
                price: quoteData.grand_total,
                shippingPrice: quoteData.shipping_amount || 0,
                currency: quoteData.quote_currency_code,
                items: this.getOrderItems(),
                shippingData: this.formatAddress(shippingAddress, 'shipping'),
                billingData: this.formatAddress(billingAddress, 'billing'),
                shopName: 'Magento',
                shopUserEmail: quote.guestEmail || (window.customerData && window.customerData.email),
                // Add selected payment method
                paymentMethod: selectedMethod ? selectedMethod.type : null,
                paymentMethodName: selectedMethod ? selectedMethod.name : null,

                // Card saving logic:
                // - For new users creating account: always save card (will be set to true with "Card" name later)
                // - For authenticated users: respect their checkbox choice
                saveCard: (isNewUser && createAccount) ? true : this.saveCard(),
                blikCode: (selectedMethod.type === 'blik' || selectedMethod.code === 'blik') ? this.blikCode() : null
            };

            // Add phone number if creating account - use global section component
            var simplyinSection = window.simplyinAccountSection;
            if (simplyinSection && 
                simplyinSection.shouldShowNewAccountSection && 
                simplyinSection.shouldShowNewAccountSection() && 
                simplyinSection.createSimplyInAccount()) {
                orderData.phoneNumber = simplyinSection.selectedCountryCode() + simplyinSection.phoneNumber().trim();
                orderData.countryCode = simplyinSection.selectedCountryCode();
            }

            // Add parcel locker data if delivery type is parcel_locker (Requirements 6.4, 9.1)
            var deliveryType = sessionStorageManager.getSelectedDeliveryType();
            orderData.deliveryType = deliveryType;

            if (deliveryType === 'parcel_locker') {
                var parcelLockerData = sessionStorageManager.getSelectedParcelLocker();
                if (parcelLockerData) {
                    orderData.parcelLockerData = parcelLockerData;
                }
            }

            // PRIORITY 1: Use COMPLETE stored address objects from session storage
            // This ensures ALL fields (including _id, icon, addressName, taxId, etc.) are sent to the API
            // The API may require all fields to recognize an existing address
            var storedBillingAddress = sessionStorageManager.getItem('selected_billing_address');
            var storedShippingAddress = sessionStorageManager.getItem('selected_shipping_address');
            
            if (storedBillingAddress) {
                try {
                    var billingAddrObj = typeof storedBillingAddress === 'string' ? 
                        JSON.parse(storedBillingAddress) : storedBillingAddress;
                    
                    // Use the complete stored address, preserving all SimplyIN fields
                    orderData.billingData = billingAddrObj;
                } catch (e) {
                    console.error('SimplyIn: Error parsing stored billing address:', e);
                    // Fallback to ID-only approach
                    var storedBillingId = sessionStorageManager.getItem('selected_billing_address_id');
                    if (storedBillingId) {
                        orderData.billingData._id = storedBillingId;
                    }
                }
            } else {
                // Fallback: try to use just the ID
                var storedBillingId = sessionStorageManager.getItem('selected_billing_address_id');
                if (storedBillingId) {
                    orderData.billingData._id = storedBillingId;
                }
            }
            
            if (storedShippingAddress) {
                try {
                    var shippingAddrObj = typeof storedShippingAddress === 'string' ? 
                        JSON.parse(storedShippingAddress) : storedShippingAddress;
                    
                    // Use the complete stored address, preserving all SimplyIN fields
                    orderData.shippingData = shippingAddrObj;
                } catch (e) {
                    console.error('SimplyIn: Error parsing stored shipping address:', e);
                    // Fallback to ID-only approach
                    var storedShippingId = sessionStorageManager.getItem('selected_shipping_address_id');
                    if (storedShippingId) {
                        orderData.shippingData._id = storedShippingId;
                    }
                }
            } else {
                // Fallback: try to use just the ID
                var storedShippingId = sessionStorageManager.getItem('selected_shipping_address_id');
                if (storedShippingId) {
                    orderData.shippingData._id = storedShippingId;
                }
            }

            // PRIORITY 2: Fallback to matching addresses if no stored addresses (only for authenticated users)
            // This handles cases where user didn't select from modal but addresses might still match
            if (userData && authToken) {
                if (!orderData.billingData._id) {
                    var billingAddressId = this.findMatchingAddressId(
                        orderData.billingData,
                        userData.billingAddresses || []
                    );
                    if (billingAddressId) {
                        orderData.billingData._id = billingAddressId;
                    }
                }
                
                if (!orderData.shippingData._id) {
                    var shippingAddressId = this.findMatchingAddressId(
                        orderData.shippingData,
                        userData.shippingAddresses || []
                    );
                    if (shippingAddressId) {
                        orderData.shippingData._id = shippingAddressId;
                    }
                }
            }

            // Handle saved card payment
            if (selectedMethod.isSavedCard) {
                orderData.useSavedCard = true;
                orderData.savedCardId = selectedMethod.cardId;
                orderData.savedCardToken = selectedMethod.cardToken;
                // orderData.savedCardCvv = this.savedCardCvv(); // No longer used

                orderData.cardLast4 = selectedMethod.last4;
                orderData.cardBrand = selectedMethod.brand;
                orderData.savedCardName = selectedMethod.cardName;
            }
            // Append card token data if available (new card)
            else if (this.cardTokenData) {
                orderData.cardToken = this.cardTokenData.oneTimeToken;
                orderData.cardLast4 = this.cardTokenData.last4digits;
                orderData.cardProvider = (this.cardTokenData.brand || 'visa').toLowerCase();
                
                // Card name logic:
                // - For authenticated SimplyIN users: use the card name they entered (if saving card)
                // - For new users (creating account): use static "Card" name
                // - Fallback: use cardholder name from token or billing name
                if (authToken && this.saveCard() && this.cardName()) {
                    // Authenticated user saving card with custom name
                    orderData.cardName = this.cardName();
                    orderData.saveCard = true;
                } else if (isNewUser && createAccount) {
                    // New user creating account - always save card with static name "Card"
                    orderData.cardName = 'Card';
                    orderData.saveCard = true;
                } else {
                    // Fallback to cardholder name or billing name
                    orderData.cardName = this.cardTokenData.cardholderName || (billingAddress.firstname + ' ' + billingAddress.lastname);
                    // For authenticated users, respect their saveCard checkbox choice
                    if (authToken) {
                        orderData.saveCard = this.saveCard();
                        if (this.saveCard() && this.cardName()) {
                            orderData.cardName = this.cardName();
                        }
                    }
                }
            }

            return ajaxClient.post('simplyin/api/createOrder', {
                orderData: orderData,
                authToken: authToken,
                isNewUser: isNewUser,
                createAccount: createAccount
            }).done(function (response) {
                if (response.success && response.order && response.order._id) {
                    self.simplyInOrderId = response.order._id;

                    // Store payment info for Magento order
                    if (response.paymentInfo) {
                        self.paymentInfo = response.paymentInfo;
                    }

                    // Store auth token if account was created
                    if (response.authToken) {
                        sessionStorageManager.setAuthToken(response.authToken);
                    }
                }
            });
        },

        /**
         * Find matching address ID from user's existing addresses
         * Compares key fields to determine if addresses match
         */
        findMatchingAddressId: function (newAddress, existingAddresses) {
            if (!newAddress || !existingAddresses || existingAddresses.length === 0) {
                return null;
            }

            // Normalize address for comparison
            var normalizeAddress = function(addr) {
                return {
                    street: (addr.street || '').trim().toLowerCase(),
                    city: (addr.city || '').trim().toLowerCase(),
                    postalCode: (addr.postalCode || addr.postcode || '').trim().replace(/\s+/g, '').toLowerCase(),
                    country: (addr.country || addr.countryId || '').trim().toUpperCase()
                };
            };

            var newNormalized = normalizeAddress(newAddress);

            // Find matching address
            for (var i = 0; i < existingAddresses.length; i++) {
                var existing = existingAddresses[i];
                var existingNormalized = normalizeAddress(existing);

                // Compare key fields
                if (existingNormalized.street === newNormalized.street &&
                    existingNormalized.city === newNormalized.city &&
                    existingNormalized.postalCode === newNormalized.postalCode &&
                    existingNormalized.country === newNormalized.country) {

                    // Match found - return the address ID
                    return existing._id || existing.id;
                }
            }

            return null; // No match found
        },

        /**
         * Get order items
         */
        getOrderItems: function () {
            var items = [];
            var quoteItems = quote.getItems();

            quoteItems.forEach(function (item) {

                // Calculate tax fields
                var taxAmount = 0;
                var taxRate = 0;
                var priceNet = item.price || 0;
                var priceGross = item.price || 0;

                // Get tax information from item
                if (item.tax_amount && item.qty) {
                    // Tax amount per item (total tax divided by quantity)
                    taxAmount = parseFloat(item.tax_amount) / parseFloat(item.qty);

                    // Calculate net price (price without tax)
                    priceNet = priceGross - taxAmount;

                    // Calculate tax rate percentage
                    if (priceNet > 0) {
                        taxRate = (taxAmount / priceNet) * 100;
                    }
                } else if (item.tax_percent) {
                    // Alternative: use tax_percent if available
                    taxRate = parseFloat(item.tax_percent);
                    priceNet = priceGross / (1 + (taxRate / 100));
                    taxAmount = priceGross - priceNet;
                }

                // Round to 2 decimal places
                taxAmount = Math.round(taxAmount * 100) / 100;
                taxRate = Math.round(taxRate * 100) / 100;
                priceNet = Math.round(priceNet * 100) / 100;
                priceGross = Math.round(priceGross * 100) / 100;

                // Try to get product URL from multiple sources
                var productUrl = '';

                // First try: item.product.url (if available)
                if (item.product && item.product.url) {
                    productUrl = item.product.url;
                }
                // Second try: item.product.request_path (Magento product URL key)
                else if (item.product && item.product.request_path) {
                    productUrl = urlBuilder.build(item.product.request_path);
                }
                // Third try: construct from product_id if available
                else if (item.product_id) {
                    productUrl = urlBuilder.build('catalog/product/view/id/' + item.product_id);
                }
                // Fourth try: extension_attributes (some Magento versions store it here)
                else if (item.extension_attributes && item.extension_attributes.product_url) {
                    productUrl = item.extension_attributes.product_url;
                }

                items.push({
                    name: item.name,
                    url: productUrl,
                    price: priceGross,           // Price including tax
                    price_net: priceNet,         // Price excluding tax
                    tax_amount: taxAmount,       // Tax amount per item
                    tax_rate: taxRate,           // Tax rate percentage
                    quantity: item.qty,
                    currency: quote.totals().quote_currency_code,
                    thumbnailUrl: item.thumbnail || '',
                    item_id: item.item_id || ''
                });
            });

            return items;
        },

        /**
         * Format address for Simply.IN
         * Matches WooCommerce plugin structure for API compatibility
         */
        formatAddress: function (address, type) {
            if (!address) {
                return {};
            }

            var regionValue = address.region || '';

            // If region is an object (Magento sometimes returns {region: "Name", region_code: "XX"})
            if (typeof regionValue === 'object' && regionValue !== null) {
                regionValue = regionValue.region || regionValue.region_code || '';
            }

            var formatted = {
                name: address.firstname || '',
                surname: address.lastname || '',
                street: address.street ? address.street[0] : '',
                appartmentNumber: address.street && address.street[1] ? address.street[1] : '',
                city: address.city || '',
                postalCode: address.postcode || '',
                country: address.countryId || '',
                county: regionValue,
                state: regionValue,
                companyName: address.company || ''
            };

            // For shipping addresses, include icon and addressName (matching WooCommerce)
            if (type === 'shipping') {
                formatted.icon = '🏡';
                formatted.addressName = '';
            }

            return formatted;
        }
    });
});
