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

    $(function () {
        var config = window.nxtpdfSetupWizard || {};
        var $root = $('#nxtpdf-setup-wizard');

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

        var $form = $root.find('#nxtpdf-setup-form');
        var $steps = $root.find('[data-wizard-step]');

        if (!$form.length || !$steps.length) {
            return;
        }

        var currentStep = 0;
        var totalSteps = $steps.length;

        var $progressText = $root.find('[data-wizard-progress-text]');
        var $progressBar = $root.find('[data-wizard-progress-bar]');
        var $indicators = $root.find('[data-wizard-indicator]');

        var $backButton = $root.find('[data-wizard-back]');
        var $skipButton = $root.find('[data-wizard-skip]');
        var $nextButton = $root.find('[data-wizard-next]');
        var $finishButton = $root.find('[data-wizard-finish]');
        var $errorText = $root.find('[data-wizard-error]');
        var isSubmitting = false;

        function getString(key, fallback) {
            if (config.strings && typeof config.strings[key] === 'string' && config.strings[key] !== '') {
                return config.strings[key];
            }

            return fallback;
        }

        function escapeHtml(value) {
            return $('<div/>').text(String(value || '')).html();
        }

        function escapeAttribute(value) {
            return escapeHtml(value).replace(/"/g, '&quot;');
        }

        function clearError() {
            $errorText.text('');
            $errorText.addClass('nxtpdf-hidden');
        }

        function showError(message) {
            $errorText.text(message || getString('unexpectedError', 'Something went wrong. Please try again.'));
            $errorText.removeClass('nxtpdf-hidden');
        }

        function updateProgress() {
            var currentLabel = currentStep + 1;
            var percentage = Math.round((currentLabel / totalSteps) * 100);
            var label = getString('stepLabel', 'Step') + ' ' + currentLabel + ' ' + getString('ofLabel', 'of') + ' ' + totalSteps;

            $progressText.text(label);
            $progressBar.css('width', percentage + '%');

            $indicators.each(function (index) {
                var $indicator = $(this);

                $indicator.removeClass('is-current is-pending is-complete');

                if (index < currentStep) {
                    $indicator.addClass('is-complete');
                    return;
                }

                if (index === currentStep) {
                    $indicator.addClass('is-current');
                    return;
                }

                $indicator.addClass('is-pending');
            });
        }

        function updateNavigation() {
            var isFirst = currentStep === 0;
            var isLast = currentStep === totalSteps - 1;

            $backButton.prop('disabled', isFirst);
            $backButton.toggleClass('is-disabled', isFirst);

            $skipButton.toggleClass('nxtpdf-hidden', isLast);
            $nextButton.toggleClass('nxtpdf-hidden', isLast);
            $finishButton.toggleClass('nxtpdf-hidden', !isLast);
        }

        function showStep(index) {
            if (index < 0 || index >= totalSteps) {
                return;
            }

            currentStep = index;
            $steps.addClass('nxtpdf-hidden');
            $steps.eq(currentStep).removeClass('nxtpdf-hidden');

            clearError();
            updateProgress();
            updateNavigation();
        }

        function initSingleSelect2($select) {
            if (!$select.length || typeof $.fn.select2 === 'undefined') {
                return;
            }

            if ($select.data('select2')) {
                return;
            }

            var allowSearch = String($select.data('nxtf-select2-search')) !== '0';
            var placeholder = $select.data('nxtf-select2-placeholder') || '';
            var isMultiple = !!$select.prop('multiple');

            var select2Config = {
                width: '100%',
            };

            if (!allowSearch) {
                select2Config.minimumResultsForSearch = Infinity;
            }

            if (placeholder) {
                select2Config.placeholder = placeholder;
                if (!isMultiple) {
                    select2Config.allowClear = true;
                }
            }

            $select.select2(select2Config);
        }

        function renderStateField(countryCode) {
            var statesByCountry = config.states && typeof config.states === 'object' ? config.states : {};
            var selectedStates = statesByCountry[countryCode] || null;

            var $currentStateField = $form.find('#company_state');
            if (!$currentStateField.length) {
                return;
            }

            var currentValue = String($currentStateField.val() || '');
            var fieldName = String($currentStateField.attr('name') || '');
            var fieldClass = String($currentStateField.attr('class') || '');

            var selectPlaceholder = getString('statePlaceholder', 'Select state / province');
            var textPlaceholder = getString('stateInputPlaceholder', 'State or province');

            if (selectedStates && typeof selectedStates === 'object' && Object.keys(selectedStates).length > 0) {
                if ($currentStateField.is('select') && $currentStateField.data('select2')) {
                    $currentStateField.select2('destroy');
                }

                var optionsMarkup = '<option value="">' + escapeHtml(selectPlaceholder) + '</option>';

                $.each(selectedStates, function (stateCode, stateName) {
                    var stateCodeString = String(stateCode || '');
                    var isSelected = stateCodeString === currentValue;

                    optionsMarkup += '<option value="' + escapeAttribute(stateCodeString) + '"' + (isSelected ? ' selected' : '') + '>' + escapeHtml(stateName) + '</option>';
                });

                var selectMarkup = '<select id="company_state" name="' + escapeAttribute(fieldName) + '" class="' + escapeAttribute(fieldClass) + '" data-nxtf-select2="1" data-nxtf-select2-search="1" data-nxtf-select2-placeholder="' + escapeAttribute(selectPlaceholder) + '">' + optionsMarkup + '</select>';
                $currentStateField.replaceWith(selectMarkup);

                initSingleSelect2($form.find('#company_state'));
                return;
            }

            if ($currentStateField.is('select') && $currentStateField.data('select2')) {
                $currentStateField.select2('destroy');
            }

            var inputMarkup = '<input type="text" id="company_state" name="' + escapeAttribute(fieldName) + '" class="' + escapeAttribute(fieldClass) + '" value="' + escapeAttribute(currentValue) + '" placeholder="' + escapeAttribute(textPlaceholder) + '">';
            $currentStateField.replaceWith(inputMarkup);
        }

        function setupCountryStateBinding() {
            var $countryField = $form.find('#company_country');
            if (!$countryField.length) {
                return;
            }

            initSingleSelect2($countryField);
            renderStateField(String($countryField.val() || ''));

            $countryField.on('change', function () {
                renderStateField(String($(this).val() || ''));
            });
        }

        function setLoading(loading) {
            isSubmitting = loading;
            $backButton.prop('disabled', loading || currentStep === 0);
            $skipButton.prop('disabled', loading);
            $nextButton.prop('disabled', loading);
            $finishButton.prop('disabled', loading);

            if (loading) {
                $finishButton.data('original-label', $finishButton.text());
                $finishButton.text(getString('saving', 'Saving...'));
                return;
            }

            var originalLabel = $finishButton.data('original-label');
            $finishButton.text(originalLabel || getString('finish', 'Finish Setup'));
        }

        function parseErrorMessage(response) {
            if (response && response.data && typeof response.data.message === 'string' && response.data.message !== '') {
                return response.data.message;
            }

            return getString('saveError', 'Unable to save setup wizard settings.');
        }

        function serializeWizardForm() {
            var markerSelector = 'input[data-wizard-empty-marker="1"]';
            $form.find(markerSelector).remove();

            $form.find('select[multiple]').each(function () {
                var $field = $(this);
                var fieldName = String($field.attr('name') || '');
                var value = $field.val();
                var hasValue = $.isArray(value) ? value.length > 0 : !!value;

                if (!fieldName || hasValue) {
                    return;
                }

                $('<input>', {
                    type: 'hidden',
                    name: fieldName,
                    value: '',
                    'data-wizard-empty-marker': '1',
                }).appendTo($form);
            });

            var serializedData = $form.serialize();
            $form.find(markerSelector).remove();

            return serializedData;
        }

        function submitWizard() {
            if (isSubmitting) {
                return;
            }

            clearError();

            var ajaxUrl = config.ajaxUrl || window.ajaxurl || '';
            if (!ajaxUrl) {
                showError(getString('saveError', 'Unable to save setup wizard settings.'));
                return;
            }

            setLoading(true);

            $.ajax({
                url: ajaxUrl,
                method: 'POST',
                dataType: 'json',
                data: {
                    action: config.action || 'nxtpdf_setup_wizard_save',
                    nonce: config.nonce || '',
                    settings: serializeWizardForm(),
                },
            })
                .done(function (response) {
                    if (response && response.success) {
                        var redirectUrl = response.data && response.data.redirect_url ? response.data.redirect_url : config.redirectUrl;

                        if (redirectUrl) {
                            window.location.assign(redirectUrl);
                            return;
                        }

                        window.location.reload();
                        return;
                    }

                    showError(parseErrorMessage(response));
                })
                .fail(function (xhr) {
                    if (xhr && xhr.responseJSON && xhr.responseJSON.data && typeof xhr.responseJSON.data.message === 'string') {
                        showError(xhr.responseJSON.data.message);
                        return;
                    }

                    showError(getString('unexpectedError', 'Something went wrong. Please try again.'));
                })
                .always(function () {
                    setLoading(false);
                });
        }

        $backButton.on('click', function () {
            if (isSubmitting) {
                return;
            }
            showStep(currentStep - 1);
        });

        $skipButton.on('click', function () {
            if (isSubmitting) {
                return;
            }
            showStep(currentStep + 1);
        });

        $nextButton.on('click', function () {
            if (isSubmitting) {
                return;
            }
            showStep(currentStep + 1);
        });

        $finishButton.on('click', function () {
            submitWizard();
        });

        $form.on('submit', function (event) {
            event.preventDefault();

            if (currentStep < totalSteps - 1) {
                showStep(currentStep + 1);
                return;
            }

            submitWizard();
        });

        $form.find('select[data-nxtf-select2]').each(function () {
            initSingleSelect2($(this));
        });

        setupCountryStateBinding();
        showStep(0);
    });
})(jQuery);
