;(function ( $, window, document, undefined ) {

    var pluginName = "eaBootstrap",

    defaults = {
        main_selector: '#ea-bootstrap-main',
        main_template: null,
        overview_selector: "#ea-appointments-overview",
        overview_template: null,
        store: {},
        ajaxCount: 0,
        initScrollOff: false
    };

    // The actual plugin constructor
    function Plugin ( element, options ) {
        this.element = element;
        this.$element = jQuery(element);
        this.settings = jQuery.extend( {}, defaults, options );
        this._defaults = defaults;
        this._name = pluginName;
        this.init();
    }

    jQuery.extend(Plugin.prototype, {
        vacation: function(workerId, day, serviceId=null) {
            var response = [true, day, ''];
            jQuery.each(ea_service_start_data, function(index, service_start_data) {
                if (serviceId == service_start_data.id && jQuery.inArray(day, service_start_data.booking_date_skip) !== -1) {
                    response = [false, 'blocked vacation', 'Not Avaiable'];
                }
            });

            // block days from shortcode
            if (Array.isArray(ea_settings.block_days) && ea_settings.block_days.includes(day)) {
                return [
                    false,
                    'blocked',
                    ea_settings.block_days_tooltip
                ];
            }

            if (!Array.isArray(ea_vacations) || ea_vacations.length === 0) {
                return response;
            }

            jQuery.each(ea_vacations, function(index, vacation) {
                // Check events
                // Case we have workers selected
                if (vacation.workers.length > 0) {
                    // extract worker ids
                    var workerIds = jQuery.map(vacation.workers, function(worker) {
                        return worker.id;
                    });
                    // selected worker is not in vacation list exit
                    if (jQuery.inArray(workerId, workerIds) === -1) {
                        return true;
                    }

                }

                if (jQuery.inArray(day, vacation.days) === -1) {
                    return true;
                }

                //  Check if it's a full-day vacation
                if (vacation.time && vacation.time.fullDay === false) {
                    var startTime = vacation.time.startTime ? moment(vacation.time.startTime) : null;
                    var endTime = vacation.time.endTime ? moment(vacation.time.endTime) : null;

                    if (startTime && endTime) {
                        // attach a flag so we can disable specific time slots later
                        if (!window.ea_partial_vacations) window.ea_partial_vacations = [];
                        window.ea_partial_vacations.push({
                            day: day,
                            start: startTime.format('HH:mm'),
                            end: endTime.format('HH:mm'),
                            workerId: workerId,
                            tooltip: vacation.tooltip
                        });
                        return true; // don't block the whole day
                    }
                }

                response = [false, 'blocked vacation', vacation.tooltip];

                return false;
            });

            return response;
        },
        /**
         * Plugin init
         */
        init: function () {
            var plugin = this;

            if (ea_settings['datepicker'] && ea_settings['datepicker'].length > 1) {
                moment.locale(ea_settings['datepicker'].substr(0,2));
            }

            plugin.settings.main_template = _.template(jQuery(plugin.settings.main_selector).html());

            plugin.settings.overview_template = _.template(jQuery(plugin.settings.overview_selector).html());
            this.$element.html(plugin.settings.main_template({settings:ea_settings}));

            // close plugin if something is missing
            if (!this.settingsOk()) {
                return;
            }

            this.$element.find('.ea-phone-number-part, .ea-phone-country-code-part').change(function() {
                plugin.parsePhoneField($(this));
            });

            // set default value for phone fields
            this.$element.find('.ea-phone-country-code-part').each(function(index, select) {
                $(select).val($(select).data('default'));
            });

            // handle form validation with scroll to field with error
            this.$element.find('form').validate({
                focusInvalid: false,
                invalidHandler: function(form, validator) {
                    if (!validator.numberOfInvalids())
                        return;
                    $('html, body').animate({
                        scrollTop: ($(validator.errorList[0].element).offset().top - 30)
                    }, 1000);
                }
            });

            // select change event
            this.$element.find('select').not('.custom-field').change(jQuery.proxy( this.getNextOptions, this ));

            jQuery.datepicker.setDefaults( jQuery.datepicker.regional[ea_settings.datepicker] );

            var firstDay = ea_settings.start_of_week;
            var minDate = (ea_settings.min_date === null) ? 0 : ea_settings.min_date;

            // datePicker
            this.$element.find('.date').datepicker({
                onSelect : jQuery.proxy( plugin.dateChange, plugin ),
                dateFormat : 'yy-mm-dd',
                minDate: minDate,
                firstDay: firstDay,
                maxDate: ea_settings.max_date,
                defaultDate: ea_settings.default_date,
                showWeek: ea_settings.show_week === '1',
                // on month change event
                onChangeMonthYear: function(year, month, widget) {
                    plugin.selectChange(month, year);
                },
                // add class to every field, so we can later find it
                beforeShowDay: function(date) {
                    var month = date.getMonth() + 1;
                    var days = date.getDate();

                    if(month < 10) {
                        month = '0' + month;
                    }

                    if(days < 10) {
                        days = '0' + days;
                    }

                    var dateString = date.getFullYear() + '-' + month + '-' + days;
                    var workerId = plugin.$element.find('[name="worker"]').val();
                    var serviceId = plugin.$element.find('[name="service"]').val();

                    return plugin.vacation(workerId, dateString,serviceId);
                }
            });

            // hide options with one choice
            this.hideDefault();

            // time is selected
            this.$element.find('.ea-bootstrap').on('click', '.time-value', function(event) {

                event.preventDefault();
                var parentForm = jQuery(this).closest('form');

                var result = plugin.selectTimes(jQuery(this));

                plugin.triggerSlotSelectEvent();

                // check if we can select that field
                if (!result) {
                    if (ea_settings['trans.slot-not-selectable'] !== undefined) {
                        alert(ea_settings['trans.slot-not-selectable']);                        
                    }else{
                        alert('Not enough time please choose an earlier slot');
                    }
                    return;
                }

                if (ea_settings['pre.reservation'] === '1') {
                    plugin.appSelected.apply(plugin);
                } else {
                    // for booking overview
                    var booking_data = {};

                    booking_data.location = parentForm.find('[name="location"] > option:selected').text();
                    booking_data.service = parentForm.find('[name="service"] > option:selected').text();
                    booking_data.worker = parentForm.find('[name="worker"] > option:selected').text();
                    booking_data.date = parentForm.find('.date').datepicker().val();
                    booking_data.time = parentForm.find('.selected-time').data('val');
                    booking_data.price = parentForm.find('[name="service"] > option:selected').data('price');
                    if (ea_settings['is_multiple_booking_allowed'] == '1') {
                        booking_data.price = parentForm.find('.selected-time').length * booking_data.price;
                    }

                    var format = ea_settings['date_format'] + ' ' + ea_settings['time_format'];
                    booking_data.date_time = moment(booking_data.date + 'T' + booking_data.time, ea_settings['defult_detafime_format']).format(format);

                    // set overview cancel_appointment
                    var overview_content = '';

                    overview_content = plugin.settings.overview_template({data: booking_data, settings: ea_settings});

                    parentForm.find('#booking-overview').html(overview_content);

                    parentForm.find('#ea-total-amount').on('checkout:done', function( event, checkoutId ) {
                        var paypal_input = parentForm.find('#paypal_transaction_id');

                        if (paypal_input.length == 0) {
                            paypal_input = jQuery('<input id="paypal_transaction_id" class="custom-field" name="paypal_transaction_id" type="hidden"/>');
                            parentForm.find('.final').append(paypal_input);
                        }

                        paypal_input.val(checkoutId);

                        // make final conformation
                        plugin.singleConformation(event);
                    });

                    // parentForm.find('.step').addClass('disabled');
                    parentForm.find('.final').removeClass('disabled');

                    if (ea_settings['is_multiple_booking_allowed'] != '1') {
                        parentForm.find('.final').find('select,input').first().focus();
                        plugin.scrollToElement(parentForm.find('.final'));
                    }
                    plugin.$element.find('#ea-payment-select').show();

                    // trigger global event when time slot is selected
                    jQuery(document).trigger('ea-timeslot:selected');
                }

                // only load form if that option is not turned off
                if (ea_settings['save_form_content'] !== '0') {
                    // load custom fields from localStorage
                    plugin.loadPreviousFormData(plugin.$element.find('form'));
                }
            });

            // init blur next steps
            this.blurNextSteps(this.$element.find('.step:visible:first'), true, true);

            if (ea_settings['pre.reservation'] === '1') {
                this.$element.find('.ea-submit').on('click', jQuery.proxy( plugin.finalComformation, plugin ));
            } else {
                this.$element.find('.ea-submit').on('click', jQuery.proxy( plugin.singleConformation, plugin ));
            }

            this.$element.find('.ea-cancel').on('click', jQuery.proxy( plugin.cancelApp, plugin ));

            setTimeout(function() {
                jQuery(document).trigger('ea-init:completed');
            }, 1000);
        },

        selectTimes: function ($element) {
            var plugin = this;

            // =======================
            // FEATURE FLAG CHECK
            // =======================
            if (ea_settings['is_multiple_booking_allowed'] != '1') {
                // ----------------------------------------
                // ORIGINAL SINGLE-SLOT LOGIC (unchanged)
                // ----------------------------------------
                var serviceData = plugin.$element.find('[name="service"] > option:selected').data();
                var duration = serviceData.duration;
                var slot_step = serviceData.slot_step;

                var takeSlots = 1; // original logic
                var $nextSlots = $element.nextAll();

                var forSelection = [];
                forSelection.push($element);

                if (($nextSlots.length + 1) < takeSlots) {
                    return false;
                }

                $element.parent().children().removeClass('selected-time');

                jQuery.each($nextSlots, function (index, elem) {
                    var $elem = jQuery(elem);

                    var startTime = moment($element.data('val'), 'HH:mm');
                    var calculatedTime = (index + 1) * slot_step;
                    var expectedTime = startTime.add(calculatedTime, 'minutes').format('HH:mm');

                    if ($elem.data('val') !== expectedTime) {
                        return false;
                    }

                    if (index + 2 > takeSlots) {
                        return false;
                    }

                    if ($elem.hasClass('time-disabled')) {
                        return false;
                    }

                    forSelection.push($elem);
                });

                if (forSelection.length < takeSlots) {
                    return false;
                }

                jQuery.each(forSelection, function (index, elem) {
                    elem.addClass('selected-time');
                });

                return true;
            }

            // =======================
            // NEW MULTI-SLOT LOGIC
            // =======================

            var slot_step = parseInt(
                plugin.$element.find('[name="service"] > option:selected').data('slot_step')
            );

            // If no slot selected yet — user is picking START time
            if (plugin.multiStart == null) {
                plugin.multiStart = $element;
                plugin.$element.find('.time-value').removeClass('selected-time');
                $element.addClass('selected-time');
                return true;
            }

            // If start is selected and user selects end time
            var startTime = moment(plugin.multiStart.data('val'), 'HH:mm');
            var endTime = moment($element.data('val'), 'HH:mm');

            if (endTime.isBefore(startTime)) {
                alert("End time must be after start time.");
                plugin.multiStart = null;
                return false;
            }

            // Mark all slots between start → end
            plugin.$element.find('.time-value').removeClass('selected-time');

            var current = startTime.clone();
            while (current <= endTime) {
                let t = current.format('HH:mm');
                let $slot = plugin.$element.find('.time-value[data-val="' + t + '"]');

                if ($slot.length === 0 || $slot.hasClass('time-disabled')) {
                    alert("One or more selected slots are unavailable.");
                    plugin.multiStart = null;
                    return false;
                }

                $slot.addClass('selected-time');
                current.add(slot_step, 'minutes');
            }

            // Save selected range
            plugin.multiSelectedStart = startTime.format('HH:mm');
            plugin.multiSelectedEnd   = endTime.add(slot_step, 'minutes').format('HH:mm');

            return true;
        },


        /**
         * Check if settings are ok
         *
         * @returns {boolean}
         */
        settingsOk: function () {
            var selectOptions = this.$element.find('select').not('.custom-field');
            var errors = jQuery('<div style="border: 1px solid gray; padding: 20px;">');
            var valid = true;

            selectOptions.each(function(index, element) {
                var $el = jQuery(element);
                var options = $el.children('option');

                // <option value="">-</option>
                if (options.length === 1 && options.attr('value') == '') {
                    jQuery(document.createElement('p'))
                        .html('You need to define at least one <strong>' + $el.attr('name') + '</strong>.')
                        .appendTo(errors);

                    valid = false;
                }
            });

            if (!valid) {
                errors.prepend('<h4>East Appointments - Settings validation:</h4>');
                errors.append('<p>There should be at least one Connection.</p>');

                this.$element.html(errors);
            }

            return valid;
        },
        /**
         * If there is only one select option used don't need to choose
         */
        hideDefault: function () {
            var steps = this.$element.find('.step');
            var counter = 0;

            steps.each(function (index, element) {
                var select = jQuery(element).find('select').not('.custom-field');

                if (select.length < 1) {
                    return;
                }

                var options = select.children('option');

                if (options.length !== 1) {
                    return;
                }

                if (options.value !== '') {
                    jQuery(element).hide();
                    counter++;
                }
            });

            if (counter === 3) {
                this.settings.initScrollOff = true;
            }
        },
        /**
         * Find all previous options that are selected
         * @param element
         * @returns {{}}
         */
        getPrevousOptions: function (element) {
            var step = element.parents('.step');

            var options = {};

            var data_prev = step.prevAll('.step');

            data_prev.each(function (index, elem) {
                // var option = jQuery(elem).find('select,input').first();
                var input_field = jQuery(elem).find('.filter').filter('input, select');

                options[jQuery(input_field).data('c')] = input_field.val();
            });

            return options;
        },
        /**
         * Get next select option
         */
        getNextOptions: function (event) {
            var current = jQuery(event.target);

            var step = current.closest('.step');

            // blur next options
            this.blurNextSteps(step);

            // nothing selected
            if (current.val() === '') {
                return;
            }

            var options = {};

            options[current.data('c')] = current.val();

            var data_prev = step.prevAll('.step');

            data_prev.each(function (index, elem) {
                var option = jQuery(elem).find('select,input').first();

                options[jQuery(option).data('c')] = option.val();
            });
            // hidden
            this.$element.find('.step:hidden').each(function (index, elem) {
                var option = jQuery(elem).find('select,input').first();

                options[jQuery(option).data('c')] = option.val();
            });

            //only visible step
            var nextStep = step.nextAll('.step:visible:first');

            var next = jQuery(nextStep).find('select,input');

            if (next.length === 0) {
                this.blurNextSteps(nextStep);
                //nextStep.removeClass('disabled');
                return;
            }

            options.next = next.data('c');

            this.callServer(options, next);
        },
        /**
         * Standard call for select options (location, service, worker)
         */
        callServer: function (options, next_element) {
            var plugin = this;

            options.action = 'ea_next_step';
            options.check  = ea_settings['check'];
            options._cb    = Math.floor(Math.random() * 1000000);

            this.placeLoader(next_element.parent());

            var req = jQuery.get(ea_ajaxurl, options, function (response) {
                next_element.empty();
                var default_option_value = '-';
                if (options.next == 'service') {
                    default_option_value = ea_settings['trans.service'];
                }
                if (options.next == 'location') {
                    default_option_value = ea_settings['trans.location'];
                }
                if (options.next == 'worker') {
                    default_option_value = ea_settings['trans.worker'];
                }
                plugin.$element.find('[id="repeat_booking"]').parents('.form-group').hide();
                // default
                next_element.append('<option value="">'+default_option_value+'</option>');

                var option_count = 0;

                // options
                jQuery.each(response, function (index, element) {
                    var name = element.name;
                    var $option = jQuery('<option value="' + element.id + '">' + name + '</option>');

                    if ('price' in element) {
                        // set price for service
                        $option.data('price', element.price);

                        if (ea_settings['price.hide'] !== '1' && ea_settings['price.hide.service'] !== '1') {
                            if (ea_settings['hide.decimal_in_price'] == '1' && !isNaN(element.price)) {
                                element.price = Math.round(element.price);
                            }
                            // see if currency is before price or now
                            if (ea_settings['currency.before'] === '1') {
                                $option.text(element.name + ' - ' + next_element.data('currency') + element.price);
                            } else {
                                $option.text(element.name + ' - ' + element.price + next_element.data('currency'));
                            }
                        }
                    }

                    if ('slot_step' in element) {
                        $option.data('slot_step', element.slot_step);
                        $option.data('duration', element.duration);
                    }

                    next_element.append($option);

                    option_count++;
                });

                // enabled
                next_element.closest('.step').removeClass('disabled');

                plugin.removeLoader();

                plugin.scrollToElement(next_element.parent());

                // if there is only one option auto select it
                if (ea_settings['auto_select_option'] === '1' && option_count === 1) {
                    next_element
                        .children()
                        .last()
                        .prop('selected', true)
                        .trigger('change');
                }
            }, 'json');

            // in case of failed ajax request
            req.fail(function(xhr, status) {

                if (xhr.status === 403) {
                    alert(ea_settings['trans.nonce-expired']);
                }

                if (xhr.status === 404) {
                    alert(ea_settings['trans.ajax-call-not-available']);
                }

                if (xhr.status === 500) {
                    alert(ea_settings['trans.internal-error']);
                }

                plugin.removeLoader();
            });
        },
        placeLoader: function ($element) {
            if (++this.settings.ajaxCount !== 1) {
                return;
            }

            var width = $element.width();
            var height = $element.height();
            jQuery('#ea-loader').prependTo($element);
            jQuery('#ea-loader').css({
                'width': width,
                'height': height
            });
            jQuery('#ea-loader').show();
        },
        removeLoader: function () {
            if (--this.settings.ajaxCount > 1) {
                return;
            }

            this.settings.ajaxCount = 0;

            jQuery('#ea-loader').hide();
        },
        getCurrentStatus: function () {
            var options = jQuery(this.element).find('select').not('.custom-field');
        },
        blurNextSteps: function (current, dontScroll, initialCall) {

            // check if there is scroll param
            dontScroll = dontScroll || false;

            initialCall = initialCall || false;

            current.removeClass('disabled');

            var nextSteps = current.nextAll('.step:visible');

            var nextParentSteps = current.parent().nextAll('.step:visible');

            jQuery.merge(nextSteps, nextParentSteps);
            // find all next steps in second column

            nextSteps.each(function (index, element) {
                jQuery(element).addClass('disabled');
            });

            // if next step is calendar
            if (current.hasClass('calendar')) {

                var calendar = this.$element.find('.date');

                // refresh calendar
                calendar.datepicker("refresh");

                // skip auto select date if
                if (!initialCall || ea_settings.cal_auto_select !== '0') {
                    this.selectChange();
                }

                if (!dontScroll) {
                    this.scrollToElement(calendar);
                }
            }
        },
        /**
         * Change of date - datepicker
         */
        dateChange: function (dateString, calendar) {
            var plugin = this, next_element, calendarEl;

            calendarEl = jQuery(calendar.dpDiv).parents('.date');

            if (plugin.settings.currentDate === dateString && calendarEl.find('.time-row').length > 0) {
                calendarEl.find('.time-row').remove();
                return;
            }

            plugin.settings.currentDate = dateString;

            calendarEl.parent().next().addClass('disabled');

            var options = this.getPrevousOptions(calendarEl);

            options.action = 'ea_date_selected';
            options.date   = dateString;
            options.check  = ea_settings['check'];

            this.placeLoader(calendarEl);
            

            // var req = jQuery.get(ea_ajaxurl, options, function (response) {
            var req = jQuery.get(ea_ajaxurl, options, function (response_m) {
                var response = response_m.calendar_slots;
                if (response_m.connection_details && response_m.connection_details.repeat_booking == 1) {
                    plugin.$element.find('[id="repeat_booking"]').parents('.form-group').show();
                }else{
                    plugin.$element.find('[id="repeat_booking"]').parents('.form-group').hide();
                }

                next_element = jQuery(document.createElement('div'))
                    .addClass('time well well-lg');

                var fromTo = ea_settings["label.from_to"] == "1";
                var classAMPM = (ea_settings["time_format"] == "am-pm") ? ' am-pm' : '';

                if (fromTo) {
                    next_element.addClass('time well well-lg col-50');
                }

                // sort response by value 11:00, 12:00, 13:00...
                response.sort(function (a, b) {
                    var a1 = a.value, b1 = b.value;

                    if (a1 == b1) {
                        return 0;
                    }

                    return a1 > b1 ? 1 : -1;
                });

                


                // TR > TD WITH TIME SLOTS
                jQuery.each(response, function (index, element) {
                    var selectLabel = fromTo ? element.show + ' - ' + element.ends : element.show;

                    //  Check if time falls into partial vacation window
                    var isDisabled = false;
                    if (window.ea_partial_vacations && window.ea_partial_vacations.length > 0) {
                        var selectedWorker = plugin.$element.find('[name="worker"]').val();
                        window.ea_partial_vacations.forEach(function(vac) {
                            if (vac.day === plugin.settings.currentDate && vac.workerId == selectedWorker) {
                                var slotTime = moment(element.value, 'HH:mm');
                                var start = moment(vac.start, 'HH:mm');
                                var end = moment(vac.end, 'HH:mm');
                                if (slotTime.isBetween(start, end, null, '[)')) {
                                    isDisabled = true;
                                }
                            }
                        });
                    }

                    if (element.count > 0 && !isDisabled) {
                        next_element.append('<a href="#" class="time-value' + classAMPM + '" data-val="' + element.value + '">' + selectLabel + '</a>');
                    } else {
                        next_element.append('<a class="time-disabled' + classAMPM + '" title="Vacation">' + selectLabel + '</a>');
                    }
                });


                if (response.length === 0) {
                    next_element.html('<p class="time-message">' + ea_settings['trans.please-select-new-date'] + '</p>');
                }

                // if we have column that shows week number then it is 8
                var colSpan = ea_settings.show_week === '1' ? 8 : 7;

                var newRow = jQuery(document.createElement('tr'))
                    .addClass('time-row')
                    .append('<td colspan="' + colSpan +'" />');

                newRow.find('td').append(next_element);

                jQuery(calendar.dpDiv).find('.ui-datepicker-current-day').closest('tr').after(newRow);

                // enabled
                next_element.parent().removeClass('disabled');

                if (!plugin.settings.initScrollOff) {
                    next_element.find('.time-value:first').focus();
                } else {
                    plugin.settings.initScrollOff = false;
                }

                // auto select time slot if there is only one available
                if (ea_settings.auto_select_slot === '1') {
                    if (next_element.find('.time-value').not('.time-disabled').length === 1) {
                        next_element.find('.time-value').not('.time-disabled').click();
                    }
                }

            }, 'json');

            req.always(function () {
                plugin.refreshData(plugin.settings.store);
                plugin.removeLoader();
            });

            // in case of failed ajax request
            req.fail(function(xhr, status) {

                if (xhr.status === 403) {
                    alert(ea_settings['trans.nonce-expired']);
                }

                if (xhr.status === 404) {
                    alert(ea_settings['trans.ajax-call-not-available']);
                }

                if (xhr.status === 500) {
                    alert(ea_settings['trans.internal-error']);
                }

                plugin.removeLoader();
            });
        },
        /**
         * Change month in calendar
         *
         * @param month
         * @param year
         */
        selectChange: function (month, year) {
            var self = this;
            self.placeLoader(self.$element.find('.calendar'));

            var simulateClick = false;

            if (typeof month === 'undefined' || typeof year === 'undefined') {

                var $firstDay = this.$element.find('[data-handler="selectDay"]:first');
                month = parseInt($firstDay.data('month')) + 1;
                year = $firstDay.data('year');
            }

            simulateClick = true;

            // check is all filled
            if (this.checkStatus()) {
                var selects = this.$element.find('select').not('.custom-field');

                var fields = selects.serializeArray();

                fields.push({'name': 'action', 'value': 'ea_month_status'});
                fields.push({'name': 'month', 'value': month});
                fields.push({'name': 'year', 'value': year});

                fields.push({'name': 'check', 'value': ea_settings['check']});

                fields.push({'name': '_cb', 'value': Math.floor(Math.random() * 1000000)});

                var req = jQuery.get(ea_ajaxurl, fields, function (result) {
                    self.settings.store = result;
                    self.refreshData(result);

                    // simulate click for current date if there is one on calendar
                    if (simulateClick) {
                        // current day TD
                        var $cDay = self.$element.find('.ui-datepicker-current-day');

                        // it's free day after refresh
                        if ($cDay.hasClass('free')) {
                            // but only if auto select is off
                            if (ea_settings.cal_auto_select !== '0') {
                                $cDay.click();
                            }
                        } else {
                            // remove time slots row
                            self.$element.find('.time-row').remove();
                        }
                    }
                }, 'json');

                req.fail(function (xhr, status) {
                    if (xhr.status === 403) {
                        alert(ea_settings['trans.nonce-expired']);
                    }

                    if (xhr.status === 404) {
                        alert(ea_settings['trans.ajax-call-not-available']);
                    }

                    if (xhr.status === 500) {
                        alert(ea_settings['trans.internal-error']);
                    }

                    plugin.removeLoader();
                });
            }
        },
        /**
         * Refresh table cells
         * @param data
         */
        refreshData: function (data) {

            var datepicker = this.$element.find('.date');

            jQuery.each(data, function (key, status) {
                var $td = datepicker.find('.' + key);

                // remove all class and leave just date 2020-01-01
                $td.removeClass('free');
                $td.removeClass('busy');
                $td.removeClass('no-slots');

                $td.addClass(status);
            });

            this.removeLoader();
        },
        /**
         * Is everything selected
         * @return {boolean} Is ready for sending data
         */
        checkStatus: function () {
            var selects = this.$element.find('select').not('.custom-field');

            var isComplete = true;

            selects.each(function (index, element) {
                isComplete = isComplete && jQuery(element).val() !== '';
            });

            return isComplete;
        },
        /**
         * Appointment information - before user add personal
         * information
         */
        appSelected: function (element) {
            var plugin = this;

            this.placeLoader(this.$element.find('.selected-time'));

            // make pre reservation
            var options = {
                location: this.$element.find('[name="location"]').val(),
                service: this.$element.find('[name="service"]').val(),
                worker: this.$element.find('[name="worker"]').val(),
                repeat_booking: this.$element.find('[name="repeat_booking"]').val(),
                repeat_start_date: this.$element.find('[name="repeat_start_date"]').val(),
                repeat_end_date: this.$element.find('[name="repeat_end_date"]').val(),
                date: this.$element.find('.date').datepicker().val(),
                end_date: this.$element.find('.date').datepicker().val(),
                check: ea_settings['check'],
                action: 'ea_res_appointment'
            };
            if (ea_settings['is_multiple_booking_allowed'] == '1' && plugin.multiSelectedEnd) {
                options.start = plugin.multiSelectedStart;
                options.end   = plugin.multiSelectedEnd;
            } else {
                options.start = this.$element.find('.selected-time').data('val');
            }

            options._cb = Math.floor(Math.random() * 1000000);

            // for booking overview
            var booking_data = {};
            booking_data.location = this.$element.find('[name="location"] > option:selected').text();
            booking_data.service = this.$element.find('[name="service"] > option:selected').text();
            booking_data.worker = this.$element.find('[name="worker"] > option:selected').text();
            booking_data.date = this.$element.find('.date').datepicker().val();
            booking_data.time = this.$element.find('.selected-time').data('val');
            booking_data.price = this.$element.find('[name="service"] > option:selected').data('price');

            var format = ea_settings['date_format'] + ' ' + ea_settings['time_format'];
            booking_data.date_time = moment(booking_data.date + ' ' + booking_data.time, ea_settings['defult_detafime_format']).format(format);

            var req = jQuery.get(ea_ajaxurl, options, function (response) {
                plugin.res_app = response.id;

                plugin.$element.find('.ea-cancel').data('_hash', response._hash);

                plugin.$element.find('.step').addClass('disabled');
                plugin.$element.find('.final').removeClass('disabled');

                plugin.scrollToElement(plugin.$element.find('.final'));

                // set overview cancel_appointment
                var overview_content = '';

                overview_content = plugin.settings.overview_template({data: booking_data, settings: ea_settings});

                plugin.$element.find('#booking-overview').html(overview_content);

                plugin.$element.find('#ea-total-amount').on('checkout:done', function( event, checkoutId ) {
                    var paypal_input = plugin.$element.find('#paypal_transaction_id');

                    if (paypal_input.length == 0) {
                        paypal_input = jQuery('<input id="paypal_transaction_id" class="custom-field" name="paypal_transaction_id" type="hidden"/>');
                        plugin.$element.find('.final').append(paypal_input);
                    }

                    paypal_input.val(checkoutId);

                    // make final conformation
                    plugin.finalComformation(event);
                });

            }, 'json');

            req.fail(function (xhr, status) {
                if (xhr.status === 403) {
                    alert(ea_settings['trans.nonce-expired']);
                }

                if (xhr.status === 404) {
                    alert(ea_settings['trans.ajax-call-not-available']);
                }

                if (xhr.status === 500) {
                    alert(ea_settings['trans.internal-error']);
                }

                plugin.removeLoader();
            });

            req.always(jQuery.proxy(function () {
                plugin.removeLoader();
            }));
        },
        /**
         *
         * @param $form
         */
        loadPreviousFormData: function ($form) {

            if (typeof localStorage === 'undefined') {
                return;
            }

            // load data from local storage
            var options = JSON.parse(localStorage.getItem('ea-form-options'));

            if (options === null) {
                options = {};
            }

            var params = this.getJsonFromUrl();
            
            if (options == null && params == null) {
                return;
            }

            // place values inside form fields
            Object.keys(options).forEach(function (key) {
                $form.find('[name="' + key + '"]').val(options[key]);
            });

            // place values inside form fields
            Object.keys(params).forEach(function (key) {
                $form.find('[name="' + key + '"]').val(params[key]);
            });
        },

        /**
         *
         * @param options
         */
        storeFormData: function (options) {
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem('ea-form-options', JSON.stringify(options));
            }
        },

        formatRedirect: function (urlString, data) {
            var parsedUrl = urlString;

            jQuery.each(data, function (key, value) {
                parsedUrl = parsedUrl.replaceAll('{{' + key + '}}', encodeURIComponent(value));
            });

            return parsedUrl;
        },

        /**
         * Comform appointment
         */
        finalComformation: function (event) {
            event.preventDefault();

            var plugin = this;

            var form = this.$element.find('form');

            if (!form.valid()) {
                return;
            }

            this.$element.find('.ea-submit').prop('disabled', true);

            // make pre reservation
            var options = {
                id: this.res_app,
                check: ea_settings['check']
            };

            this.$element.find('.custom-field').not('.dummy').each(function (index, element) {
                var name = jQuery(element).attr('name');
                options[name] = jQuery(element).val();
            });

            options.action = 'ea_final_appointment';
            options._cb    = Math.floor(Math.random() * 1000000);

            var req = jQuery.get(ea_ajaxurl, options, function (response) {
                // store values from form
                plugin.storeFormData(options);

                // disable fields
                plugin.$element.find('.ea-submit').hide();
                plugin.$element.find('.ea-cancel').hide();
                plugin.$element.find('#paypal-button').hide();

                if (ea_settings['show.display_thankyou_note'] == 1) {                    
                    plugin.$element.find('.step').hide();
                    var table_html = plugin.$element.find('#booking-overview').find('table').html();
                    plugin.$element.find('#booking-overview').show();
                    plugin.$element.find('#booking-overview').find('table').hide();
                    plugin.$element.find('.final').show();
                    plugin.$element.find('.ea_hide_show').hide();
                    plugin.$element.find('.ea-confirmation-subtext').hide();
                    plugin.$element.find('#booking-overview-header').hide();
                    plugin.$element.find('#ea-overview-message').hide();
                    plugin.$element.find('#ea-success-box').show();
                    plugin.$element.find('#ea-overview-details').html(table_html);
    
                    const meta = document.getElementById('ea-meta-data');
                    if (meta) {
                        const rawDateTime = meta.dataset.dateTime;
                        const service = meta.dataset.service;
                        const worker = meta.dataset.worker;
                        const location = meta.dataset.location;
                        const price = document.getElementById('ea-total-amount')?.dataset.price || '';
                        const currency = meta.dataset.currency;
                        const title = `${service} with ${worker}`;
                        const description = `Service: ${service}\nWorker: ${worker}\nPrice: ${price}${currency}`;
                        const startDateObj = new Date(rawDateTime);
                        if (isNaN(startDateObj.getTime())) {
                            console.error('Invalid date:', rawDateTime);
                        }else{
                            const endDateObj = new Date(startDateObj.getTime() + 60 * 60 * 1000); // +1 hour
        
                            const formatDateForGoogle = (dateObj) =>
                                dateObj.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
        
                            const start = formatDateForGoogle(startDateObj);
                            const end = formatDateForGoogle(endDateObj);
        
                            const calendarUrl = new URL("https://calendar.google.com/calendar/render");
                            calendarUrl.searchParams.set("action", "TEMPLATE");
                            calendarUrl.searchParams.set("text", title);
                            calendarUrl.searchParams.set("dates", `${start}/${end}`);
                            calendarUrl.searchParams.set("details", description);
                            calendarUrl.searchParams.set("location", location);
                            calendarUrl.searchParams.set("trp", "false");
        
                            document.getElementById("ea-add-to-calendar").href = calendarUrl.toString();

                        }
    
                    }
                    plugin.$element.find('.ea-status-note').text(ea_settings['default_status_message']);
                    window.scrollTo({ top: 0, behavior: 'smooth' });
                }else{
                    plugin.$element.find('.final').append('<h3 class="ea-done-message">' + _.escape(ea_settings['trans.done_message']) + '</h3>');
                }


                plugin.$element.find('form').find('input,select,textarea').prop('disabled', true);
                plugin.$element.find('.calendar').addClass('disabled');
                plugin.$element.find('.g-recaptcha').remove();

                plugin.triggerEvent();

                var redirected = false;

                // if there is redirect do that
                if (ea_settings['advance.redirect'] !== '') {
                    var data = JSON.parse(ea_settings['advance.redirect'].replaceAll('&quot;', '"'));
                    var service = plugin.$element.find('[name="service"]').val();

                    var redirect = data.find(function(el) {
                        return el.service === service;
                    });

                    if (redirect) {
                        redirected = true;
                        setTimeout(function () {
                            window.location.href = plugin.formatRedirect(redirect.url, options);
                        }, 2000);
                    }
                }

                // if there is redirect do that
                if (ea_settings['submit.redirect'] !== '' && redirected === false) {
                    setTimeout(function () {
                        window.location.href = plugin.formatRedirect(ea_settings['submit.redirect'], options);
                    }, 2000);
                }
            }, 'json')
            .fail(jQuery.proxy(function (response, status, error) {
                if (response.responseJSON.message) {
                    alert(response.responseJSON.message);                    
                }
                this.$element.find('.ea-submit').prop('disabled', false);
            }, plugin));
        },

        /**
         * Checkout process
         * @param event
         */
        singleConformation: function (event) {
            if (typeof event !== 'undefined') {
                event.preventDefault();
            }

            var plugin = this;

            var form = this.$element.find('form');

            if (!form.valid()) {
                return;
            }

            this.$element.find('.ea-submit').prop('disabled', true);

            // make pre reservation
            var options = {
                location: this.$element.find('[name="location"]').val(),
                service: this.$element.find('[name="service"]').val(),
                worker: this.$element.find('[name="worker"]').val(),
                repeat_booking: this.$element.find('[name="repeat_booking"]').val(),
                repeat_start_date: this.$element.find('[name="repeat_start_date"]').val(),
                repeat_end_date: this.$element.find('[name="repeat_end_date"]').val(),
                date: this.$element.find('.date').datepicker().val(),
                end_date: this.$element.find('.date').datepicker().val(),
                check: ea_settings['check'],
                action: 'ea_res_appointment'
            };
            if (ea_settings['is_multiple_booking_allowed'] == '1' && plugin.multiSelectedEnd) {
                options.start = plugin.multiSelectedStart;
                options.end   = plugin.multiSelectedEnd;
            } else {
                options.start = this.$element.find('.selected-time').data('val');
            }

            if (this.$element.find('.g-recaptcha-response').length === 1) {
                options.captcha = this.$element.find('.g-recaptcha-response').val();
            }

            // recaptcha v3
            if (ea_settings['captcha3.site-key'] && grecaptcha) {
                grecaptcha.ready(function() {
                    grecaptcha.execute(ea_settings['captcha3.site-key'], { action: 'submit' }).then(function(token) {
                        options.captcha = token;
                        options._cb    = Math.floor(Math.random() * 1000000);

                        jQuery.get(ea_ajaxurl, options, function (response) {
                            plugin.res_app = response.id;

                            plugin.finalComformation(event);
                        }, 'json')
                            .fail(jQuery.proxy(function (response) {
                                alert(response.responseJSON.message);
                                this.$element.find('.ea-submit').prop('disabled', false);
                            }, plugin))
                            .always(jQuery.proxy(function () {
                                plugin.removeLoader();
                            }, plugin));
                    });
                });

                return;
            }

            options._cb    = Math.floor(Math.random() * 1000000);

            // simple call
            jQuery.get(ea_ajaxurl, options, function (response) {
                plugin.res_app = response.id;

                plugin.finalComformation(event);
            }, 'json')
            .fail(jQuery.proxy(function (response) {
                alert(response.responseJSON.message);
                this.$element.find('.ea-submit').prop('disabled', false);
            }, plugin))
            .always(jQuery.proxy(function () {
                plugin.removeLoader();
            }, plugin));
        },
        /**
         * Event when new appointment is booked
         */
        triggerEvent: function () {
            var plugin = this;
            var booking_data = {};
            booking_data.location = plugin.$element.find('[name="location"] > option:selected').text();
            booking_data.service = plugin.$element.find('[name="service"] > option:selected').text();
            booking_data.worker = plugin.$element.find('[name="worker"] > option:selected').text();
            booking_data.date = plugin.$element.find('.date').datepicker().val();
            booking_data.time = plugin.$element.find('.selected-time').data('val');
            booking_data.price = plugin.$element.find('[name="service"] > option:selected').data('price');

            // Create the event.
            var event = new CustomEvent('easyappnewappointment', { detail: booking_data });

            // send event to document
            document.dispatchEvent(event);
        },

        /**
         * Event when customer select time slot
         */
        triggerSlotSelectEvent: function () {
            // Create the event.
            var event = new Event('easyappslotselect');

            // send event to document
            document.dispatchEvent(event);
        },
        /**
         * Cancel appointment
         */
        cancelApp: function (event) {
            event.preventDefault();
            var plugin = this;

            if (ea_settings['pre.reservation'] === '0') {
                plugin.chooseStep();
                plugin.res_app = null;
                this.$element.find('.step:not(.final)').prevAll('.step').removeClass('disabled');
                return false;
            }

            this.$element.find('.final').addClass('disabled');
            this.$element.find('.step:not(.final)').prevAll('.step').removeClass('disabled');

            var _hash = plugin.$element.find('.ea-cancel').data('_hash');

            var options = {
                id: this.res_app,
                check: ea_settings['check'],
                _hash: _hash,
                action: 'ea_cancel_appointment'
            };

            options._cb = Math.floor(Math.random() * 1000000);

            jQuery.get(ea_ajaxurl, options, function (response) {
                if (response.data) {
                    // remove selected time
                    plugin.$element.find('.time').find('.selected-time').removeClass('selected-time');

                    //plugin.scrollToElement(plugin.$element.find('.date'));
                    plugin.chooseStep();
                    plugin.res_app = null;

                }
            }, 'json');
        },
        chooseStep: function () {
            var plugin = this;
            var $temp;

            // if there i advance redirect do that
            if (ea_settings['advance_cancel.redirect'] !== '') {
                var data = JSON.parse(ea_settings['advance_cancel.redirect']);
                var service = plugin.$element.find('[name="service"]').val();

                var redirect = data.find(function(el) {
                    return el.service === service;
                });

                if (redirect) {
                    setTimeout(function () {
                        window.location.href = redirect.url;
                    }, 2000);
                }
                return;
            }

            switch (ea_settings['cancel.scroll']) {
                case 'calendar':
                    plugin.scrollToElement(plugin.$element.find('.date'));
                    break;
                case 'worker' :
                    $temp = plugin.$element.find('[name="worker"]');
                    $temp.val('');
                    $temp.change();
                    $temp.closest('.step').nextAll('.step').find('select').val('');
                    this.$element.find('.time-row').remove();
                    plugin.scrollToElement($temp);
                    break;
                case 'service' :
                    $temp = plugin.$element.find('[name="service"]');
                    $temp.val('');
                    $temp.change();
                    $temp.closest('.step').nextAll('.step').find('select').val('');
                    this.$element.find('.time-row').remove();
                    plugin.scrollToElement($temp);
                    break;
                case 'location' :
                    $temp = plugin.$element.find('[name="location"]');
                    $temp.val('');
                    $temp.change();
                    $temp.closest('.step').nextAll('.step').find('select').val('');
                    this.$element.find('.time-row').remove();
                    plugin.scrollToElement($temp);
                    break;
                case 'pagetop':
                    break;
            }
        },
        scrollToElement: function (element) {
            if (ea_settings.scroll_off === 'true') {
                return;
            }

            jQuery('html, body').animate({
                scrollTop: ( element.offset().top - 20 )
            }, 500);
        },

        getJsonFromUrl: function() {
            var query = location.search.substr(1);
            var result = {};

            query.split("&").forEach(function(part) {
                var item = part.split("=");
                result[item[0]] = decodeURIComponent(item[1]);
            });

            return result;
        },

        parsePhoneField: function ($el) {
            var code = $el.parent().find('.ea-phone-country-code-part').val();
            var number = $el.parent().find('.ea-phone-number-part').val().replace(/^0+/, '');

            $el.parent().find('.full-value').val('+' + code + number);
        }
    });

    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    jQuery.fn[pluginName] = function (options) {
        this.each(function () {
            if (!jQuery.data(this, "plugin_" + pluginName)) {
                jQuery.data(this, "plugin_" + pluginName, new Plugin(this, options));
            }
        });
        // chain jQuery functions
        return this;
    };
})(jQuery, window, document);


(function ($) {
    jQuery('.ea-bootstrap').eaBootstrap();

    

})(jQuery);
jQuery(document).ready(function () {
    if (ea_settings['allow_customer_search'] == 1) {
        jQuery('#ea_customer_search').select2({
            placeholder: ea_settings['trans.customer_search_label'],
            minimumInputLength: 2,
            ajax: {
                url: ea_ajaxurl,
                dataType: 'json',
                delay: 250,
                data: function (params) {
                    return {
                        action: 'ea_search_customers',
                        q: params.term,
                        nonce: ea_settings['check']
                    };
                },
                processResults: function (data) {
                    return {
                        results: data.map(function (c) {
                            return { id: c.id, text: c.name + ' (' + c.email + ')' };
                        })
                    };
                }
            }
        });

        jQuery('#ea_customer_search').on('select2:select', function (e) {
            const customerId = e.params.data.id;
            var parentForm = jQuery(this).closest('form');
            jQuery.post(ea_ajaxurl, {
                action: 'ea_get_customer_detail',
                id: customerId,
                nonce: ea_settings['check']
            }, function (c) {
                parentForm.find('[name="name"]').val(c.name);
                parentForm.find('[name="email"]').val(c.email);
                parentForm.find('[name="phone"]').val(c.mobile);
            });
        });
    }

    
});


jQuery(document).ready(function() {
    jQuery('select#repeat_booking').on('change', function() {
        if (jQuery(this).val() === '2') {
            jQuery('#custom-recurrence-modal').show();
            jQuery('#custom-recurrence-overlay').show();
        }
        if (jQuery(this).val() === '1') {
            jQuery('input[name="repeat_booking"]').val(1);
            jQuery('input[name="repeat_start_date"]').val(0);
            jQuery('input[name="repeat_end_date"]').val(0);
            jQuery('#recurrence-summary').hide();
        }
        if (jQuery(this).val() === '0') {
            jQuery('input[name="repeat_booking"]').val(0);
            jQuery('input[name="repeat_start_date"]').val(0);
            jQuery('input[name="repeat_end_date"]').val(0);
            jQuery('#recurrence-summary').hide();
        }
    });

  jQuery('#modal-end-never').on('change', function() {
    jQuery('#modal-end-date').prop('disabled', true);
  });

  jQuery('#modal-end-on').on('change', function() {
    jQuery('#modal-end-date').prop('disabled', false);
  });

  jQuery('#modal-cancel-btn').on('click', function() {
    jQuery('#custom-recurrence-modal').hide();
    jQuery('#custom-recurrence-overlay').hide();
    jQuery('select#repeat_booking').val('0'); // Reset to 'Does Not Repeat'
  });

  jQuery('#modal-save-btn').on('click', function() {
    var repeatWeek = jQuery('#modal-repeat-week').val();
    var startDate = jQuery('#modal-start-date').val();
    var endType = jQuery('input[name="modal-end-type"]:checked').val();
    var endDate = (endType == 'date') ? jQuery('#modal-end-date').val() : 'never';

    if (endType === 'date' && endDate !== '' && startDate !== '') {
        if (new Date(endDate) < new Date(startDate)) {
            alert('End date cannot be earlier than start date.');
            return;
        }
    }

    // Save to hidden inputs
    jQuery('input[name="repeat_booking"]').val(repeatWeek);
    jQuery('input[name="repeat_start_date"]').val(startDate);
    jQuery('input[name="repeat_end_date"]').val(endDate);

    jQuery('#summary-repeat-week').text(`${repeatWeek} week(s)`);
    jQuery('#summary-start-date').text(startDate);
    jQuery('#summary-end-date').text(endType == 'date' ? endDate : 'Never');
    jQuery('#recurrence-summary').show();

    // Hide modal
    jQuery('#custom-recurrence-modal').hide();
    jQuery('#custom-recurrence-overlay').hide();
  });
});
