/*!
 * Copyright 2024-2025 Simply.IN Sp. z o.o.
 *
 * NOTICE OF LICENSE
 * Licensed under the EUPL-1.2 or later.
 * You may not use this work except in compliance with the Licence.
 * Copy of the Licence is available at: https://joinup.ec.europa.eu/software/page/eupl
 * It is bundled with this package in the file LICENSE.txt
 *
 * @author    Simply.IN Sp. z o.o.
 * @copyright 2024-2025 Simply.IN Sp. z o.o.
 * @license   https://joinup.ec.europa.eu/software/page/eupl
 */

(function (window, $) {
    'use strict';

    var PhoneCheckboxManager = function (options) {
        this.options = $.extend({
            checkoutType: 'classic',
            emailFieldSelector: null,
            containerSelector: null,
            ajaxUrl: null,
            ajaxToken: null,
            debug: false
        }, options);

        this.state = {
            isCheckboxVisible: false,
            isPhoneValid: false,
            isInitialized: false,
            isLoggedIn: false,
            userExistsInSimplyIn: false
        };

        this.phones = null;
        this.checkboxElement = null;

        this.init();
    };

    PhoneCheckboxManager.prototype = {

        init: function () {
            if (this.state.isInitialized) {
                return;
            }

            if (typeof simplyin !== 'undefined' && simplyin.customer && simplyin.customer.has_token) {
                this.state.isLoggedIn = true;
            }

            this.autoDetectSelectors();
            this.loadPhoneCountries();
            this.setupPaymentStepWatcher();
            this.bindAddressCountryChange();

            this.state.isInitialized = true;
        },

        autoDetectSelectors: function () {
            if (!this.options.emailFieldSelector) {
                switch (this.options.checkoutType) {
                    case 'thecheckout':
                        this.options.emailFieldSelector = '.account-fields input[name="email"]';
                        this.options.containerSelector = '#confirm_order';
                        break;
                    case 'classic':
                    default:
                        this.options.emailFieldSelector = '#customer-form input[name="email"]';
                        this.options.containerSelector = '#checkout-payment-step .payment-options';
                        break;
                }
            }
        },

        
        
        formatDigits: function (digits) {
            var out = digits.replace(/(\d{3})(?=\d)/g, '1 '.replace('1', '$1'));
            return out.replace(/ (\d)$/, '$1');
        },

        
        
        visibleCheckboxExists: function () {

            return $('[id="simplyin-phone-checkbox"]').filter(function () {
                return !this.closest('[id="simplyin-phone-prerender"]');
            }).length > 0;
        },

        
        removeAllPrerenders: function () {
            $('[id="simplyin-phone-prerender"]').remove();
        },

        
        revalidateVisible: function () {
            if (!this.visibleCheckboxExists()) {
                return;
            }
            var phoneInput = $('#simplyin-phone-checkbox .phone-input input');
            if (phoneInput.length && phoneInput.val() !== '') {
                if (this.validatePhoneNumber()) {
                    this.storePhoneNumber();
                }
            }
        },

        // A fresh pre-render arriving while the widget is already visible means the
        // step was re-rendered server-side (e.g. the address/phone changed): rebuild
        // the widget from it so the prefill reflects the new data.
        refreshFromPrerender: function () {
            var self = this;
            var html = this.consumePrerender();
            if (!html || this.state.isLoggedIn || this.state.userExistsInSimplyIn) {
                return;
            }
            $('[id="simplyin-phone-checkbox"]').filter(function () {
                return !this.closest('[id="simplyin-phone-prerender"]');
            }).remove();
            this.insertCheckboxIntoDOM(html);
            this.initCheckboxEvents();
            this.state.isCheckboxVisible = true;
            this.syncCountryFromCurrentAddressSelection();
            this.revalidateVisible();
            void self;
        },

        setupPaymentStepWatcher: function () {
            var self = this;

            if (this.options.checkoutType !== 'classic') {
                return;
            }

            var checkoutEl = document.getElementById('checkout');
            if (!checkoutEl) {
                return;
            }

            var maybeShow = function () {
                var step = document.getElementById('checkout-payment-step');
                if (!step || !step.classList.contains('-current')) {
                    return;
                }
                if (!self.visibleCheckboxExists()) {
                    self.showCheckbox();
                } else if ($('[id="simplyin-phone-prerender"]').length) {

                    self.refreshFromPrerender();
                }
            };

            

            maybeShow();

            
            
            var paymentStepObserver = new MutationObserver(maybeShow);
            
            paymentStepObserver.observe(checkoutEl, { attributes: true, childList: true, subtree: true, attributeFilter: ['class'] });
        },

        showCheckbox: function () {
            var self = this;

            if (this.state.isLoggedIn || this.state.userExistsInSimplyIn) {
                return;
            }

            if (this._showingCheckbox) {
                return;
            }
            this._showingCheckbox = true;

            
            $('#simplyin-phone-checkbox').filter(function () {
                return !this.closest('#simplyin-phone-prerender');
            }).remove();
            this.state.isCheckboxVisible = false;

            this.fetchCheckboxHtml().then(function (html) {
                self._showingCheckbox = false;
                if (!html) {
                    return;
                }

                if (self.state.isLoggedIn || self.state.userExistsInSimplyIn) {
                    return;
                }

                self.insertCheckboxIntoDOM(html);
                self.initCheckboxEvents();
                self.state.isCheckboxVisible = true;
                self.syncCountryFromCurrentAddressSelection();
            });
        },

        hideCheckbox: function (loggedIn) {
            if (loggedIn) {
                this.state.isLoggedIn = true;
            }

            $('#simplyin-phone-checkbox').fadeOut(300, function () {
                $(this).remove();
            });

            this.state.isCheckboxVisible = false;
        },

        fetchCheckboxHtml: function () {
            var self = this;

            

            
            
            if (self.options.checkoutType !== 'thecheckout') {
                return self.waitForPrerender(600).then(function (html) {
                    if (html) {
                        return html;
                    }
                    return self.fetchCheckboxHtmlAjax();
                });
            }

            return self.fetchCheckboxHtmlAjax();
        },

        consumePrerender: function () {
            var prerenders = $('[id="simplyin-phone-prerender"]');
            if (!prerenders.length) {
                return null;
            }

            var html = prerenders.last().html();
            prerenders.remove();
            if (html && html.indexOf('simplyin-phone-checkbox') !== -1) {
                return html;
            }
            return null;
        },

        waitForPrerender: function (timeoutMs) {
            var self = this;
            var found = self.consumePrerender();
            if (found) {
                return Promise.resolve(found);
            }
            return new Promise(function (resolve) {
                var done = false;
                var observer = new MutationObserver(function () {
                    var html = self.consumePrerender();
                    if (html && !done) {
                        done = true;
                        observer.disconnect();
                        resolve(html);
                    }
                });
                observer.observe(document.body, { childList: true, subtree: true });
                setTimeout(function () {
                    if (!done) {
                        done = true;
                        observer.disconnect();
                        resolve(null);
                    }
                }, timeoutMs);
            });
        },

        fetchCheckboxHtmlAjax: function () {
            var self = this;

            return new Promise(function (resolve) {
                $.ajax({
                    url: self.options.ajaxUrl,
                    method: 'POST',
                    data: {
                        action: 'getNewAccountForm',
                        ajax: 1,
                        ajax_token: self.options.ajaxToken,
                        checkout_type: self.options.checkoutType
                    },
                    dataType: 'json'
                }).done(function (data) {
                    if (data.success && data.html) {
                        resolve(data.html);
                    } else {
                        resolve(null);
                    }
                }).fail(function () {
                    resolve(null);
                });
            });
        },

        insertCheckboxIntoDOM: function (html) {
            
            this.removeAllPrerenders();
            var container = $(this.options.containerSelector);

            if (!container.length) {

                return;
            }

            switch (this.options.checkoutType) {
                case 'thecheckout':
                    container.parent().before(html);
                    break;

                case 'classic':
                default:
                    container.append(html);
                    break;
            }

            this.checkboxElement = $('#simplyin-phone-checkbox');
        },

        initCheckboxEvents: function () {
            var self = this;

            $(document).off('change.simplyin', '#simplyin-phone-checkbox #simply-save-checkbox');
            $(document).on('change.simplyin', '#simplyin-phone-checkbox #simply-save-checkbox', function () {
                if ($(this).is(':checked')) {
                    self.showPhoneInput();
                } else {
                    self.hidePhoneInput();
                }
            });

            $(document).off('change.simplyin', '#simplyin-phone-checkbox #simplyin-phone-country');
            $(document).on('change.simplyin', '#simplyin-phone-checkbox #simplyin-phone-country', function () {
                self.updateCountryFlag();
            });

            $(document).off('input.simplyin change.simplyin', '#simplyin-phone-checkbox .phone-input input');
            $(document).on('input.simplyin change.simplyin', '#simplyin-phone-checkbox .phone-input input', function () {
                $(this).val($(this).val().replace(/[^\d\s]/g, ''));
                if (self.validatePhoneNumber()) {
                    self.storePhoneNumber();
                }
            });

            $(document).off('keypress.simplyin', '#simplyin-phone-checkbox .phone-input input');
            $(document).on('keypress.simplyin', '#simplyin-phone-checkbox .phone-input input', function (e) {
                if (e.which < 48 || e.which > 57) {
                    e.preventDefault();
                }
            });

            $(document).off('click.simplyin', '#simplyin-phone-checkbox .phone-input');
            $(document).on('click.simplyin', '#simplyin-phone-checkbox .phone-input', function () {
                $('#simplyin-phone-checkbox .phone-input input').focus();
            });

            this.bindOrderButton();

            if ($('#simplyin-phone-checkbox #simply-save-checkbox').prop('checked')) {
                this.showPhoneInput();
            }

        },

        showPhoneInput: function () {
            $('#simplyin-phone-checkbox .simplyin-phone-input').slideDown(300);

            var phoneInput = $('#simplyin-phone-checkbox .phone-input input');
            if (phoneInput.val() === '' && this.options.checkoutType !== 'thecheckout') {
                setTimeout(function () {
                    phoneInput.focus();
                }, 350);
            } else if (phoneInput.val() !== '') {
                // Store only numbers that pass validation - persisting garbage made the
                // stale value shadow a later address-phone change on re-render.
                if (this.validatePhoneNumber()) {
                    this.storePhoneNumber();
                }
            }
        },

        hidePhoneInput: function () {
            $('#simplyin-phone-checkbox .simplyin-phone-input').slideUp(300);
            this.hideValidationWarning();
            this.storePhoneNumber(true);
        },

        // Shared flag/prefix DOM update for whichever <option> is now selected -
        // display-only, no side effects, safe to call from a background sync
        // (unlike updateCountryFlag() below, which also focuses the phone input
        // and triggers the save-checkbox's change handler, appropriate only when
        // the customer just interacted with the widget's own country dropdown).
        applyCountrySelectionDisplay: function ($option) {
            var flag = $option.data('flag');
            var prefix = $option.data('prefix');

            $('.simplyin-flag-display img').attr(
                'src',
                simplyin.files_url + 'views/img/flags/' + flag + '.svg'
            );
            $('.phone-country-select .prefix').html(prefix);
            $('#simplyin-phone-checkbox .phone-input .prefix').html(prefix);
        },

        updateCountryFlag: function () {
            var selected = $('#simplyin-phone-checkbox #simplyin-phone-country option:selected');
            this.applyCountrySelectionDisplay(selected);
            $('#simplyin-phone-checkbox .phone-input input').focus();

            $('#simplyin-phone-checkbox #simply-save-checkbox').trigger('change.simplyin');
        },

        // PrestaShop's checkout/account address forms mark their Country <select>
        // with the ".js-country" class (see themes/_core/js/address.js) and fire a
        // plain "change" on it whenever the customer picks a different country -
        // this listener is document-delegated so it keeps working across the
        // address form being replaced wholesale on every country change (PrestaShop
        // re-renders it via AJAX to refresh state/postcode fields).
        bindAddressCountryChange: function () {
            var self = this;

            $(document).off('change.simplyin', '.js-country');
            $(document).on('change.simplyin', '.js-country', function () {
                var idCountry = parseInt($(this).val(), 10);
                if (idCountry) {
                    self.syncCountryFromAddressCountry(idCountry);
                }
            });
        },

        // Applies whatever address country is currently selected on the page (if
        // any) - used right after the widget is (re)rendered, so a country picked
        // during the address step *before* the widget ever appeared is still
        // reflected, not just live changes made afterwards.
        syncCountryFromCurrentAddressSelection: function () {
            var $countrySelect = $('.js-country').filter(function () {
                return $(this).val();
            }).first();

            if (!$countrySelect.length) {
                return;
            }

            var idCountry = parseInt($countrySelect.val(), 10);
            if (idCountry) {
                this.syncCountryFromAddressCountry(idCountry);
            }
        },

        // Baseline default: keeps the widget's own country selector in
        // sync with the checkout address's Country field, so a bare-digit number
        // (no "+"/"00") validates against the country the customer actually chose
        // for the order, not a stale shop default.
        //
        // Precedence: skipped once the widget's phone number field already has a
        // value. A non-empty value means either the explicit "+"/"00" prefix
        // detection (parseAndSetPhoneNumber) already resolved a country from it, or
        // the customer is mid-typing against the country currently shown - in both
        // cases silently recomputing the country here would invalidate a number the
        // customer already trusts, so we leave it alone; a manual pick via the
        // widget's own selector always remains available. This is the deliberately
        // simple choice for a rare edge case rather than tracking an extra "was this
        // explicit" flag through the whole lifecycle.
        //
        // Uses applyCountrySelectionDisplay() rather than updateCountryFlag(): this
        // runs automatically, without the customer touching the widget, so it must
        // not steal focus or trigger the save-checkbox's change handler (which would
        // fire an unconditional storeNewAccountDetails write) the way a genuine
        // manual dropdown pick should. parseAndSetPhoneNumber's explicit-prefix
        // detection makes the same choice, for the same reason.
        syncCountryFromAddressCountry: function (idCountry) {
            if (!this.visibleCheckboxExists()) {
                return;
            }

            var phoneInput = $('#simplyin-phone-checkbox .phone-input input');
            if (phoneInput.length && phoneInput.val() !== '') {
                return;
            }

            if (typeof simplyin === 'undefined' || !simplyin.country_iso_by_id) {
                return;
            }

            var iso = simplyin.country_iso_by_id[idCountry];
            if (!iso) {
                return;
            }

            var $select = $('#simplyin-phone-checkbox #simplyin-phone-country');
            var $option = $select.find('option[value="' + iso + '"]');
            if (!$option.length || $select.val() === $option.val()) {
                return;
            }

            $select.val($option.val());
            this.applyCountrySelectionDisplay($option);
        },

        validatePhoneNumber: function (blinkError) {
            var phoneInput = $('#simplyin-phone-checkbox .phone-input input');

            if (!phoneInput.length) {
                return true;
            }

            var phoneNumberRaw = phoneInput.val().replace(/\D/g, '');
            var prefix = $('#simplyin-phone-checkbox #simplyin-phone-country option:selected')
                .data('prefix');

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

            var country = this.phones.find(function (c) {
                return c.country_code === prefix;
            });

            if (!country) {
                this.showValidationWarning(blinkError);
                this.state.isPhoneValid = false;
                return false;
            }

            

            if (phoneNumberRaw.charAt(0) === '0') {
                var stripped = phoneNumberRaw.slice(1);
                var strippedFits = country.phone_number_lengths.indexOf(stripped.length) !== -1
                    && country.mobile_begin_with.some(function (start) {
                        return stripped.indexOf(start) === 0;
                    });
                if (strippedFits) {
                    phoneNumberRaw = stripped;
                }
            }

            var isValidLength = country.phone_number_lengths.indexOf(phoneNumberRaw.length) !== -1;
            var isMobile = country.mobile_begin_with.some(function (start) {
                return phoneNumberRaw.indexOf(start) === 0;
            });

            
            
            var formatted = this.formatDigits(phoneNumberRaw);

            phoneInput.val(formatted);

            if (!isValidLength || !isMobile) {
                this.showValidationWarning(blinkError);
                this.state.isPhoneValid = false;
                return false;
            } else {
                this.hideValidationWarning();
                this.state.isPhoneValid = true;
                return true;
            }
        },

        showValidationWarning: function (blink) {
            var warning = $('#simplyin-phone-checkbox .phone-input-warning');
            if (blink) {
                warning.hide().fadeIn();
            } else {
                warning.show();
            }
        },

        hideValidationWarning: function () {
            $('#simplyin-phone-checkbox .phone-input-warning').hide();
        },

        storePhoneNumber: function (clear) {
            var phone = '0';

            if (!clear) {
                var phoneInput = $('#simplyin-phone-checkbox .phone-input input');
                var prefix = $('#simplyin-phone-checkbox #simplyin-phone-country option:selected')
                    .data('prefix');
                var phoneNumber = phoneInput.val().replace(/\D/g, '');
                phone = prefix + ' ' + phoneNumber;
            }

            $.ajax({
                url: this.options.ajaxUrl,
                method: 'POST',
                data: {
                    action: 'storeNewAccountDetails',
                    ajax: 1,
                    ajax_token: this.options.ajaxToken,
                    phone: phone
                },
                dataType: 'json'
            });
        },

        bindOrderButton: function () {
            var button = document.querySelector('#payment-confirmation button');
            if (!button) {
                return;
            }

            var self = this;
            var handler = function (e) {
                var checkbox = $('#simplyin-phone-checkbox #simply-save-checkbox');

                if (checkbox.is(':checked')) {
                    var phoneInput = $('#simplyin-phone-checkbox .phone-input input');
                    var prefix = $('#simplyin-phone-checkbox #simplyin-phone-country option:selected').data('prefix');
                    var phoneNumber = phoneInput.val().replace(/\D/g, '');
                    var phone = prefix + ' ' + phoneNumber;

                    $.ajax({
                        url: self.options.ajaxUrl,
                        method: 'POST',
                        data: {
                            action: 'storeNewAccountDetails',
                            ajax: 1,
                            ajax_token: self.options.ajaxToken,
                            phone: phone
                        },
                        dataType: 'json',
                        async: false
                    });

                    if (!self.validatePhoneNumber(true)) {
                        e.preventDefault();
                        e.stopPropagation();
                        e.stopImmediatePropagation();
                        return false;
                    }
                }
            };

            if (button._simplyinPhoneHandler) {
                button.removeEventListener('click', button._simplyinPhoneHandler, { capture: true });
            }

            button.addEventListener('click', handler, { capture: true });
            button._simplyinPhoneHandler = handler;
        },

        loadPhoneCountries: function () {
            var self = this;

            $.getJSON(simplyin.files_url + 'views/json/phones.json', function (data) {
                self.phones = data;

                self.revalidateVisible();
            }).fail(function () {
            });
        },

        removeCountryPrefix: function (phoneValue) {
            if (!phoneValue) return phoneValue;

            var cleanPhone = phoneValue.trim().replace(/\s+/g, '');

            var selectedCountry = $('#simplyin-phone-checkbox #simplyin-phone-country').find('option:selected');
            if (!selectedCountry.length) {
                return cleanPhone;
            }

            var selectedPrefix = selectedCountry.data('prefix');
            if (!selectedPrefix) {
                return cleanPhone;
            }

            var prefixWithPlus = selectedPrefix;
            var prefixWithoutPlus = selectedPrefix.indexOf('+') === 0
                ? selectedPrefix.substring(1)
                : selectedPrefix;

            if (cleanPhone.indexOf(prefixWithPlus) === 0) {
                return cleanPhone.substring(prefixWithPlus.length);
            }

            if (cleanPhone.indexOf(prefixWithoutPlus) === 0) {
                return cleanPhone.substring(prefixWithoutPlus.length);
            }

            return cleanPhone;
        },

        getMaxPhoneLengthForSelectedCountry: function () {
            var selectedPrefix = $('#simplyin-phone-checkbox #simplyin-phone-country')
                .find('option:selected')
                .data('prefix');

            if (!this.phones) return 9;

            var countryData = this.phones.find(function (c) {
                return c.country_code === selectedPrefix;
            });

            if (!countryData || !countryData.phone_number_lengths) return 9;

            return Math.max.apply(null, countryData.phone_number_lengths);
        },

        parseAndSetPhoneNumber: function (fullNumber) {
            var self = this;

            if (!fullNumber) {
                return;
            }

            if (!this.phones) {
                setTimeout(function () {
                    self.parseAndSetPhoneNumber(fullNumber);
                }, 500);
                return;
            }

            var cleaned = fullNumber.replace(/[^\d+]/g, '');

            var matchedCountry = null;
            var longestMatch = 0;

            var cleanedWithPlus = cleaned.indexOf('+') === 0 ? cleaned : '+' + cleaned;

            for (var i = 0; i < this.phones.length; i++) {
                var country = this.phones[i];
                var prefix = country.country_code.replace(/\s/g, '');

                if (cleanedWithPlus.indexOf(prefix) === 0 && prefix.length > longestMatch) {
                    matchedCountry = country;
                    longestMatch = prefix.length;
                }
            }

            if (matchedCountry) {
                var $select = $('#simplyin-phone-checkbox #simplyin-phone-country');
                var $option = $select.find('option[data-prefix="' + matchedCountry.country_code + '"]');

                if ($option.length === 0) {
                    $('#simplyin-phone-checkbox .phone-input input').val(cleaned);
                    return false;
                }

                $select.val($option.val());
                self.applyCountrySelectionDisplay($option);

                var numberWithoutPrefix = cleanedWithPlus.substring(longestMatch);

                
                if (numberWithoutPrefix.charAt(0) === '0') {
                    var strippedNp = numberWithoutPrefix.slice(1);
                    var fitsNp = matchedCountry.phone_number_lengths.indexOf(strippedNp.length) !== -1
                        && matchedCountry.mobile_begin_with.some(function (start) {
                            return strippedNp.indexOf(start) === 0;
                        });
                    if (fitsNp) {
                        numberWithoutPrefix = strippedNp;
                    }
                }

                var formatted = self.formatDigits(numberWithoutPrefix);

                $('#simplyin-phone-checkbox .phone-input input').val(formatted);

                setTimeout(function () {
                    if (self.validatePhoneNumber()) {
                        self.storePhoneNumber();
                    }
                }, 100);

                return true;
            }

            $('#simplyin-phone-checkbox .phone-input input').val(cleaned);
            return false;
        },
        destroy: function () {
            $(document).off('.simplyin');
            $('#simplyin-phone-checkbox').remove();
            this.state.isInitialized = false;
        }
    };

    window.SimplyInPhoneCheckboxManager = PhoneCheckboxManager;

})(window, jQuery);
