(function ($) {
    "use strict";

    /* ===================================
        SweetAlert2
    ====================================== */

    const GigneoAlert = Swal.mixin({});

    GigneoAlert.toast = (options = {}) => GigneoAlert.fire({
        toast: true,
        position: 'bottom-end',
        customClass: { popup: 'gigneo-sweetalert2-toast' },
        showConfirmButton: false,
        timer: 5000,
        timerProgressBar: true,
        topLayer: true,
        showCloseButton: true,
        icon: 'error',
        title: GigneoCommon?.error || 'Error',
        text: GigneoCommon?.went_wrong || 'Something went wrong!',
        ...options
    });

    GigneoAlert.confirm = (options = {}) => {
        const defaultClasses = {
            popup: 'gn-sweetalert2',
            confirmButton: 'gn-btn',
            cancelButton: 'gn-btn',
        };

        const userClasses = options.customClass || {};
        const icon = options.icon || 'warning';

        const mergedClasses = {
            popup: [defaultClasses.popup, userClasses.popup].filter(Boolean).join(' '),
            confirmButton: userClasses.confirmButton
                ? [defaultClasses.confirmButton, userClasses.confirmButton].filter(Boolean).join(' ')
                : [defaultClasses.confirmButton, icon === 'error' ? 'gn-btn-danger' : (icon === 'success' ? 'gn-btn-primary' : `gn-btn-${icon}`)].filter(Boolean).join(' '),
            cancelButton: [defaultClasses.cancelButton, userClasses.cancelButton].filter(Boolean).join(' '),
        };

        const {
            customClass: _ignoredCustomClass,
            ...restOptions
        } = options;

        return Swal.fire({
            toast: false,
            position: 'center',
            icon: options.icon || 'warning',
            title: options.title || GigneoCommon?.confirmation_title || 'Are you sure?',
            text: options.text || GigneoCommon?.confirmation_desc || 'Please confirm.',
            showCancelButton: true,
            confirmButtonText: options.confirmButtonText || GigneoCommon?.yes || 'Yes',
            cancelButtonText: options.cancelButtonText || GigneoCommon?.close || 'Close',
            showLoaderOnConfirm: options.showLoaderOnConfirm || false,
            customClass: mergedClasses,
            ...restOptions
        });
    };

    window.GigneoAlert = GigneoAlert;

    /* ===================================
        Select2
    ====================================== */

    window.GigneoSelect2 = {
        init: function () {

            $(document).find('.gn-select2').each(function () {
                let _this = $(this);
                let selector = _this.find('select');
                let dataAttrs = selector.data();
                let select2Config = {
                    theme: dataAttrs?.theme || 'default gn-select2-dropdown',
                    placeholder: selector.attr('placeholder') || GigneoCommon?.select2_placeholder || 'Select an option',
                    allowClear: false,
                    allowEmpty: true,
                    dropdownCssClass: dataAttrs?.dropdownClass || '',
                    containerCssClass: dataAttrs?.containerClass || '',
                    language: {
                        noResults: () => GigneoCommon?.select2_not_found || 'No results found',
                        searching: () => GigneoCommon?.select2_searching || 'Searching...',
                        maximumSelected: () => GigneoCommon?.select2_max_selection || 'You have reached the maximum limit',
                    }
                };

                if (dataAttrs?.dropdownParent) {
                    select2Config.dropdownParent = $(dataAttrs?.dropdownParent);
                }

                if (dataAttrs?.allowClear !== undefined) select2Config.allowClear = dataAttrs.allowClear;
                if (dataAttrs?.minimumInputLength !== undefined) select2Config.minimumInputLength = dataAttrs.minimumInputLength;
                if (dataAttrs?.maximumSelectionLength !== undefined) select2Config.maximumSelectionLength = dataAttrs.maximumSelectionLength;
                if (dataAttrs?.minimumResultsForSearch !== undefined) select2Config.minimumResultsForSearch = dataAttrs.minimumResultsForSearch;

                $(selector).select2(select2Config);

                if (dataAttrs?.dynamicTags !== undefined) {
                    let selectedValues = selector.val() || [];
                    let search_field = $(selector).data('select2').$container.find('.select2-search__field');
                    let placeholder = selector.attr('placeholder') || GigneoCommon?.select2_placeholder || 'Select an option';
                    let tags_wrapper = _this.find('.gn-select2-tags');

                    search_field.attr('placeholder', placeholder);

                    $.each(selectedValues, function (index, value) {
                        let displayText = _this.find('option[value="' + value + '"]').text();
                        _this.find('.gn-select2-tags-list').append(
                            '<span class="gn-selected-tag">' + displayText +
                            '<span class="gn-remove-tag" data-value="' + value + '">x</span></span>'
                        );
                    });

                    $(selector).on('select2:select select2:unselect select2:open', function (e) {
                        if (e.type !== 'select2:open') select2RenderTags();
                        search_field.attr('placeholder', placeholder);
                    });

                    $(tags_wrapper).on('click', '.gn-remove-tag', function (e) {
                        e.preventDefault();
                        let tagValue = $(this).data('value');
                        let currentValues = selector.val() || [];
                        currentValues = currentValues.filter(value => value !== tagValue);
                        selector.val(currentValues).trigger('change');
                        select2RenderTags();
                        search_field.attr('placeholder', placeholder);
                    });

                    function select2RenderTags() {
                        if (tags_wrapper.length === 0) return;
                        let selectedValues = selector.val() || [];
                        tags_wrapper.empty();
                        $.each(selectedValues, function (index, value) {
                            let displayText = _this.find('option[value="' + value + '"]').text();
                            tags_wrapper.append(
                                '<li class="gn-selected-tag">' + displayText +
                                '<span class="gn-remove-tag" data-value="' + value + '"><i class="hi hi-x-mark" aria-hidden="true"></i></span></li>'
                            );
                        });
                    }
                }
            });
        }
    };

    /* ===================================
        Flatpickr
    ====================================== */

    // data-date-format="Y-m-d"
    // data-enable-time="true"
    // data-alt-input="true"
    // data-alt-format="F j, Y H:i"
    // data-allow-input="true"
    // data-default-date="2025-06-01"
    // data-min-date="2025-01-01"
    // data-max-date="2025-12-31"
    // data-mode="single"
    // data-inline="false"
    // data-disable-mobile="true"

    window.GigneoFlatpickr = {
        init: function () {
            $(document).find('.gn-datepicker').each(function () {
                let _this = $(this);
                let selector = _this.find('input.flatpickr-input');
                let dataAttrs = selector.data();

                let flatpickrConfig = {
                    altInput: false,
                    dateFormat: dataAttrs?.dateFormat || 'Y-m-d',
                    allowInput: dataAttrs?.allowInput !== undefined ? dataAttrs.allowInput : true,
                    altFormat: dataAttrs?.altFormat || GigneoCommon?.flatpickr_date_format || 'F j, Y',
                    onReady: function (selectedDates, dateStr, instance) {
                        instance.calendarContainer.classList.add("gn-flatpickr");
                    }
                };

                if (dataAttrs?.enableTime !== undefined) flatpickrConfig.enableTime = dataAttrs.enableTime;
                if (dataAttrs?.noCalendar !== undefined) flatpickrConfig.noCalendar = dataAttrs.noCalendar;
                if (dataAttrs?.altInput !== undefined) flatpickrConfig.altInput = dataAttrs.altInput;
                if (dataAttrs?.inline !== undefined) flatpickrConfig.inline = dataAttrs.inline;
                if (dataAttrs?.disableMobile !== undefined) flatpickrConfig.disableMobile = dataAttrs.disableMobile;
                if (dataAttrs?.defaultDate !== undefined) flatpickrConfig.defaultDate = dataAttrs.defaultDate;
                if (dataAttrs?.minDate !== undefined) flatpickrConfig.minDate = dataAttrs.minDate;
                if (dataAttrs?.maxDate !== undefined) flatpickrConfig.maxDate = dataAttrs.maxDate;
                if (dataAttrs?.mode !== undefined) flatpickrConfig.mode = dataAttrs.mode;
                if (dataAttrs?.locale !== undefined) flatpickrConfig.locale = dataAttrs.locale;

                selector.flatpickr(flatpickrConfig);
            });
        }
    };

    /* ===================================
        Plupload
    ====================================== */

    window.GigneoPlupload = {
        init: function (config) {
            let {
                browseButtonId,
                containerId,
                dropElementId,
                attachmentListId,
                allowedExtensions = ['jpg', 'jpeg', 'png'],
                maxFiles = 3,
                maxSizeMb = 1,
                errorMessages = {
                    maxFiles: `Maximum ${maxFiles} files allowed.`,
                    invalidExtension: 'Invalid file extension.',
                    maxSize: `File size exceeds ${maxSizeMb}MB.`,
                    error: GigneoCommon?.error || 'Something went wrong.'
                }
            } = config || {};

            if (!errorMessages.error) {
                errorMessages.error = GigneoCommon?.error || 'Something went wrong.'
            }

            let filesToUpload = [];
            let attachmentList = $(`#${attachmentListId}`);

            if (typeof plupload !== 'object') {
                console.error('Plupload library not loaded.');
                return { files: [], uploader: null };
            }

            // Validate DOM elements
            if ($(`#${browseButtonId}`).length === 0 || $(`#${containerId}`).length === 0 || $(`#${dropElementId}`).length === 0 || attachmentList.length === 0) {
                return { files: [], uploader: null };
            }

            // Initialize Plupload
            let pluploadArgs = {
                browse_button: browseButtonId,
                container: containerId,
                drop_element: dropElementId,
                filters: {
                    mime_types: [{ title: 'file', extensions: allowedExtensions.join(',') }],
                    max_file_size: maxSizeMb + 'mb'
                }
            };

            let uploader = new plupload.Uploader(pluploadArgs);
            uploader.init();

            // Handle FilesAdded event
            uploader.bind('FilesAdded', function (up, files) {
                if ((filesToUpload.length + files.length) > maxFiles) {
                    GigneoAlert?.toast({
                        icon: 'error',
                        title: errorMessages.error,
                        text: errorMessages.maxFiles
                    });
                    files.forEach(f => up.removeFile(f));
                    return;
                }

                for (let i = 0; i < files.length; i++) {
                    let file = files[i];
                    let ext = file.name.includes('.') ? file.name.split('.').pop().toLowerCase() : '';

                    if (ext && !allowedExtensions.includes(ext)) {
                        GigneoAlert?.toast({
                            icon: 'error',
                            title: errorMessages.error,
                            text: errorMessages.invalidExtension
                        });
                        up.removeFile(file);
                        continue;
                    }

                    if (file.size > maxSizeMb * 1024 * 1024) {
                        GigneoAlert?.toast({
                            icon: 'error',
                            title: errorMessages.error,
                            text: errorMessages.maxSize
                        });
                        up.removeFile(file);
                        continue;
                    }

                    filesToUpload.push(file);
                    attachmentList.append(
                        `<div id="${file.id}" class="gn-attachment-item" role="listitem"><span class="gn-name"> ${file.name} </span>` +
                        `<button type="button" class="gn-attachment-remove" data-file-id="${file.id}" aria-label="Remove ${file.name}">` +
                        `<i class="hi hi-trash" aria-hidden="true"></i></button></div>`
                    );
                }

                up.refresh();
            });

            // Handle Plupload errors
            uploader.bind('Error', function (up, err) {
                GigneoAlert?.toast({
                    icon: 'error',
                    title: errorMessages.error,
                    text: err.message || 'An error occurred during file upload.'
                });
            });

            // Handle file removal
            attachmentList.off('click.gigneoPlupload').on('click.gigneoPlupload', '.gn-attachment-remove', function () {
                let _this = $(this);
                let fileId = _this.data('file-id');
                let attachmentId = _this.data('attachment-id');
                let postId = _this.data('post-id');

                if (fileId) {
                    let file = uploader.getFile(fileId);
                    if (file) {
                        uploader.removeFile(file);
                        filesToUpload = filesToUpload.filter(f => f.id !== fileId);
                        _this.closest(`#${file.id}`).fadeOut(100, function () {
                            $(this).remove();
                        });
                    }
                }
            });

            // Store uploader instance on the container for external access
            $(`#${containerId}`).data('gn-plupload-instance', uploader);

            // Return filesToUpload and uploader for external use
            return { files: filesToUpload, uploader: uploader };
        }
    };

    /* ===================================
        Price Format
    ====================================== */

    window.GigneoPrice = {
        format: function (number, includeSymbol = false, useDecimals = true) {
            const settings = GigneoCommon.price_format || {};
            const currencySymbol = settings.currency_symbol || '$';
            const currencyPosition = settings.currency_position || 'left';
            const decimalSeparator = settings.decimal_separator || '.';
            const thousandSeparator = settings.thousand_separator || ',';
            const priceDecimals = useDecimals ? (parseInt(settings.price_decimals) || 2) : 0;

            let parts = Number(number).toFixed(priceDecimals).split('.');
            let integerPart = parts[0];
            let decimalPart = parts[1] || '';

            // Add thousand separators
            integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);

            let formattedNumber = integerPart;
            if (priceDecimals > 0) {
                formattedNumber += decimalSeparator + decimalPart;
            }

            if (!includeSymbol) {
                return formattedNumber;
            }

            // Add currency symbol based on position
            switch (currencyPosition) {
                case 'right':
                    return `${formattedNumber}${currencySymbol}`;
                case 'right_space':
                    return `${formattedNumber} ${currencySymbol}`;
                case 'left_space':
                    return `${currencySymbol} ${formattedNumber}`;
                case 'left':
                default:
                    return `${currencySymbol}${formattedNumber}`;
            }
        }
    };

    /* ===================================
        Textarea Counter
    ====================================== */

    window.GigneoTextareaCounter = {
        init: function () {
            $(document).find('textarea.gn-textarea-counter').each(function () {
                let _this = $(this);
                let maxLength = _this.data('max-length') || 100;
                let counterId = _this.attr('id') ? `${_this.attr('id')}-gntc` : `gntc-${Math.random().toString(36).substr(2, 9)}`;
                let counterText = GigneoCommon?.textarea_counter_text || '{remaining}/{max}';

                if ($(`#${counterId}`).length === 0) {
                    _this.after(`<div class="gntc-counter" id="${counterId}"></div>`);
                }

                _this.attr('maxlength', maxLength);

                let counter = $(`#${counterId}`);

                function updateCounter() {
                    let remaining = maxLength - _this.val().length;
                    counter.text(counterText
                        .replace('{remaining}', remaining)
                        .replace('{max}', maxLength)
                    );
                }

                updateCounter();

                // Update counter on input (avoid binding multiple listeners)
                _this.off('input.gigneoTextarea').on('input.gigneoTextarea', updateCounter);
            });
        }
    };

    /* ===================================
      Fancybox
    ====================================== */

    $('[data-gn-fancybox]').fancybox({
        selector: '[data-gn-fancybox]'
    });

    /* ===================================
      Quantity Input
    ====================================== */

    $(document).on('click', '.gn-qty-plus, .gn-qty-minus', function () {
        let container = $(this).closest('.gn-qty');
        let input = container.find('input[type="number"]');
        let current_val = parseInt(input.val(), 10) || 1;
        let min = parseInt(input.attr('min'), 10) || 1;
        let max = parseInt(input.attr('max'), 10) || 12;

        if ($(this).hasClass('gn-qty-plus')) {
            if (current_val < max) {
                input.val(current_val + 1).trigger('change');
            }
        } else {
            if (current_val > min) {
                input.val(current_val - 1).trigger('change');
            }
        }
    });

    /* ===================================
      Required Fields
    ====================================== */

    window.GigneoRequiredFormFields = {
        init: function (selector = $(this), proceed = true, notice = true) {
            selector.find('input,select,textarea').each(function () {
                let _input = $(this);
                let _input_type = _input.attr('type');
                let value = _input.val();

                if (_input.hasClass('gn-required-field')) {
                    if (_input_type === 'radio' || _input_type === 'checkbox') {
                        let radioGroupName = _input.attr('name');
                        if ($('input[name="' + radioGroupName + '"]:checked').length === 0) {
                            $('input[name="' + radioGroupName + '"]').addClass('gn-input-error');
                            proceed = false;
                        }
                    } else if (value === '') {
                        _input.addClass('gn-input-error');
                        proceed = false;
                    }
                }
            });

            if (!proceed && notice) {
                GigneoAlert.toast({
                    icon: 'error',
                    title: GigneoCommon.error,
                    text: GigneoCommon.required_fields
                });
            }

            return proceed;
        }
    };

        /* ===================================
       Saved item
    ====================================== */

    // Sav/unsave button click
    $(document).on('click', '.gn-save-btn', function (e) {
        e.preventDefault();

        // Check if user is logged in (instantly stop guests)
        if (Number(GigneoCommon.user_id) === 0) {
            GigneoAlert.toast({
                icon: 'error',
                title: GigneoCommon.error,
                text: GigneoCommon.login_required_msg
            });

            // Handle login flow after a short delay so user can read the message
            setTimeout(function () {
                if (GigneoCommon.auth_popup && $('#gn-auth-popup').length) {
                    let _popup_wrapper = $('#gn-auth-popup');
                    let _forms = _popup_wrapper.find('.gn-auth-content > form');
                    _forms.hide();
                    _forms.filter('#gn-auth-login').show();
                    _popup_wrapper.addClass('gn-active');
                } else {
                    window.location.href = GigneoCommon.login_url || GigneoCommon.home_url;
                }
            }, 700);

            return;
        }

        let _this = $(this);
        let _id = _this.data('gn-id');
        let _type = _this.data('gn-type');

        // Prevent double click
        if (_this.hasClass('gn-loading')) {
            return;
        }

        _this.addClass('gn-loading').attr('disabled', true);

        $.ajax({
            url: GigneoCommon.ajax_url,
            type: 'POST',
            data: {
                action: 'gigneo_save_item',
                security: GigneoCommon.security,
                id: _id,
                type: _type
            },
            success: function (response) {
                _this.removeClass('gn-loading').attr('disabled', false);


                if (response.success) {

                    // Toggle active state
                    if (_this.hasClass('gn-saved')) {
                        _this.removeClass('gn-saved');
                    } else {
                        _this.addClass('gn-saved');
                    }

                    // Optional toast message
                    if (response?.data?.message) {
                        GigneoAlert.toast({
                            icon: 'success',
                            title: GigneoCommon.success,
                            text: response.data.message
                        });
                    }

                    let wrapper = $('.gn-dashboard-section.gn-saved-listing-wrapper.gn-service-listing-wrapper');

                    if (wrapper.length) {
                        window.location.reload();
                    }
                }
            },
            error: function (xhr) {
                _this.removeClass('gn-loading').attr('disabled', false);

                let error_message =
                    xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;

                GigneoAlert.toast({
                    icon: 'error',
                    title: GigneoCommon.error,
                    text: error_message
                });
            }
        });
    });

    //Chat Request
    $(document).on("click", ".gn-message-request", function (e) {
        e.preventDefault();
        let _this = $(this);
        const profileId = _this.data("profile-id");
        const memberProfileId = _this.data("member-id");

        if (!profileId || !memberProfileId) {
            return;
        }

        _this.addClass("gn-loading");

        $.ajax({
            url: GigneoCommon.ajax_url,
            type: "POST",
            data: {
                action: "gigneo_add_member",
                profile_id: profileId,
                member_profile_id: memberProfileId,
                security: GigneoCommon.security,
            },
            success: function (response) {
                _this.removeClass("gn-loading");
                window.location.href = response.data.dashboard_url;
            },
            error: function (xhr, status, error,) {
                _this.removeClass("gn-loading");
                // Handle error
                GigneoAlert.toast({
                    icon: 'error',
                    title: GigneoCommon.error,
                    text: error.message || GigneoCommon.went_wrong
                });
                console.error("AJAX Error adding Member:", status, error);
            },
        });
    });

    //Remove error class
    $(document).on('input', '.gn-input-error', function () {
        $(this).removeClass('gn-input-error');
    });

    /* ===================================
      Document Ready
    ====================================== */

    $(document).ready(function () {
        GigneoSelect2.init(); //Init Select2
        GigneoFlatpickr.init(); //Init FlatPickr
        GigneoTextareaCounter.init(); //Init TextArea Counter
    });

    /* ===================================
         Modal Popup
     ====================================== */

    //Modal Toggle
    $(document).on('click', '[data-gn-modal-toggle]', function (e) {
        let _this = $(this),
            modal_id = _this.data('gn-modal-toggle'),
            modal = $('#' + modal_id);

        if (modal.length) {
            e.preventDefault();

            $(document).trigger('gigneo_modal_before_open', [_this, modal_id]);

            modal.addClass('gn-active');
            $('body').addClass('gn-modal-open');

            $(document).trigger('gigneo_modal_after_open', [_this, modal_id]);

        }
    });

    //Modal Close
    $(document).on('click', '[data-gn-modal-close]', function (e) {
        let _this = $(this),
            modal_id = _this.data('gn-modal-close'),
            modal = $('#' + modal_id);

        if (modal.length) {
            e.preventDefault();
            modal.removeClass('gn-active');
            $('body').removeClass('gn-modal-open');
            $(document).trigger('gn_modal:closed', [_this, modal_id]);
        }
    });

    /* ===================================
          Form
     ====================================== */

    //Password reveal
    $(document).on('click', '.gn-form-field .gn-password-revealed', function () {
        let _this = $(this);
        if (_this.hasClass('hi-eye-slash')) {
            _this.removeClass('hi-eye-slash').addClass('hi-eye');
            _this.siblings('input').attr('type', 'text');
        } else if (_this.hasClass('hi-eye')) {
            _this.removeClass('hi-eye').addClass('hi-eye-slash');
            _this.siblings('input').attr('type', 'password');
        }
    });

    //Password strength
    $(document).on('input', '#gn-register-password,#gn-change-password', function () {
        let _this = $(this);
        let value = _this.val();

        let password_strength = GigneoCommon.password_strength;
        let password_notices = _this.parents('.gn-form-field').find('.gn-password-notice > li');

        let rulePatterns = {
            length: /.{8,}/,         // At least 8 characters
            uppercase: /[A-Z]/,       // At least one uppercase letter
            lowercase: /[a-z]/,       // At least one lowercase letter
            number: /[0-9]/,          // At least one number
            special: /[!@#$%^&*(),.?":{}|<>]/ // At least one special character
        };

        let firstErrorFound = false;

        password_strength.forEach(rule => {
            let noticeItem = password_notices.filter(`.${rule}`);
            if (!firstErrorFound && rulePatterns[rule] && !rulePatterns[rule].test(value)) {
                noticeItem.show();
                firstErrorFound = true;
                _this.addClass('gn-input-invalid');
                _this.parents('#gn-auth-register-basic').find('.gn-auth-register-continue-btn').attr('disabled', true);
                _this.parents('#gn-auth-change-password').find('#gn-change-password-form-submit-btn').attr('disabled', true);
            } else {
                noticeItem.hide();
                if (!firstErrorFound) {
                    _this.removeClass('gn-input-invalid');
                    _this.parents('#gn-auth-register-basic').find('.gn-auth-register-continue-btn').attr('disabled', false);
                    _this.parents('#gn-auth-change-password').find('#gn-change-password-form-submit-btn').attr('disabled', false);
                }
            }
        });
    });

    /* ===================================
        Dropdown
    ====================================== */

    $(document).on('click', '.gn-dropdown-toggle', function (e) {
        e.stopPropagation();
        const dropdown = $($(this).data('gn-target'));
        if (dropdown.length) {
            $(this).toggleClass('gn-active');
            dropdown.toggleClass('gn-active');
        }
    });

    // Click outside to close
    $(document).on('click', function (e) {
        // If click is NOT inside dropdown or toggle
        if (!$(e.target).closest('.gn-dropdown-content, .gn-dropdown-toggle').length) {
            $('.gn-dropdown-toggle.gn-active').removeClass('gn-active');
            $('.gn-dropdown-content.gn-active').removeClass('gn-active');
        }
    });

    $(document).on('click', '.gn-dropdown-content.gn-active .gn-dropdown-item', function (e) {
        $('.gn-dropdown-toggle.gn-active').removeClass('gn-active');
        $('.gn-dropdown-content.gn-active').removeClass('gn-active');
    });

    /* ===================================
        Accordion
    ====================================== */

    $(document).on('click', '.gn-accordion-wrapper .gn-accordion-item .gn-head', function (e) {
        e.preventDefault();
        let _this = $(this);
        _this.parent().siblings().removeClass('gn-active');
        _this.parent().toggleClass('gn-active');
    });

    /* ===================================
        User Menu
     ====================================== */

    //Show a menu on avatar click
    $(document).on('click', '.gn-user-action-menu .gn-user-avatar', function (e) {
        e.stopPropagation();
        $(this).parents('.gn-user-action-menu').toggleClass('gn-active');
        $('.gn-user-notification,.gn-user-chat').removeClass('gn-active');
    });

    //Close the menu when clicking outside
    $(document).on('click', function (e) {
        if (!$(e.target).closest('.gn-user-action-menu').length) {
            $('.gn-user-action-menu').removeClass('gn-active');
        }
    });

    //Switch profile
    $(document).on('click', '#gn-switch-profile', function (e) {
        e.preventDefault();

        let _this = $(this);

        if (_this.hasClass('gn-loading')) {
            return false;
        }

        _this.addClass('gn-loading');

        $.ajax({
            url: GigneoCommon.ajax_url,
            type: 'POST',
            data: {
                action: 'gigneo_switch_profile',
                security: GigneoCommon.security
            },
            success: function (response) {
                _this.removeClass('gn-loading');
                if (response.success) {
                    window.location.href = response.data.redirect || GigneoCommon.home_url;
                } else {
                    GigneoAlert.toast({
                        icon: 'error',
                        text: GigneoCommon.went_wrong
                    });
                }
            },
            error: function (xhr) {
                _this.removeClass('gn-loading');
                let error_message = xhr?.responseJSON?.data.message || GigneoCommon.went_wrong;
                GigneoAlert.toast({
                    icon: 'error',
                    text: error_message
                });
            }
        });

    });

    /* ===================================
        Heart Beat Notification
    ====================================== */

    var last_check = null;
    let last_unread_notifications = 0;
    let last_unread_messages = 0;

    if ('heartbeat' === GigneoCommon.notification_type) {
        if (typeof wp !== "undefined" && wp.heartbeat) {
            wp.heartbeat.interval(GigneoCommon.heartbeat_interval);
        }

        const is_logged_in = parseInt(GigneoCommon.profile_id, 10);

        if (!is_logged_in || isNaN(is_logged_in)) {
            return;
        }

        // Send data with Heartbeat
        $(document).on('heartbeat-send', function (e, data) {

            if (!last_check) {
                last_check = new Date(Date.now() - 60000);
            }

            const formatted_last_check = last_check.toISOString().slice(0, 19).replace('T', ' ');

            data['gigneo_notifications'] = { last_check: formatted_last_check };
            data['gigneo_messages'] = { last_check: formatted_last_check };

            if (GigneoCommon.notification_onscreen) {
                data['gigneo_onscreen_notifications'] = { last_check: formatted_last_check };
            }

            //Send Heartbeat
            $(document).trigger('gigneo_heartbeat_send', data);

        });

        // Handle Heartbeat response
        $(document).on('heartbeat-tick', function (e, data) {

            last_check = new Date();

            // Unread Notification Count
            if (data['gigneo_unread_notification_count'] != null && data['gigneo_unread_notification_count'] !== '') {
                let unread_notifications = data['gigneo_unread_notification_count'] ?? 0;

                if (unread_notifications !== last_unread_notifications) {
                    //Side Menu Link
                    let notification_sidebar_link = $(document).find('.gn-menu-notification .gn-count');
                    if (notification_sidebar_link.length) {
                        notification_sidebar_link.html(unread_notifications ?? '');
                    }

                    //Nav Menu Link
                    let notification_menu_link = $(document).find('.gn-user-notification .gn-icon > .gn-count');
                    if (notification_menu_link.length) {
                        notification_menu_link.html(unread_notifications ?? '');
                    }

                    if (unread_notifications !== last_unread_notifications) {
                        notification_dropdown_markup();
                    }
                }

                last_unread_notifications = unread_notifications;

            }

            //On Screen Notifications
            if (data['gigneo_onscreen_notifications'] && data['gigneo_onscreen_notifications'].length > 0) {
                let onscreen_notifications = data['gigneo_onscreen_notifications'];
                onscreen_notifications.forEach((notification, index) => {
                    GigneoAlert.toast({
                        icon: 'info',
                        title: notification.title,
                        text: notification.content
                    });
                });
            }

            // Unread Messages Count
            if (data['gigneo_unread_messages_count'] !== null && data['gigneo_unread_messages_count'] !== undefined && data['gigneo_unread_messages_count'] !== '') {
                let unread_messages = data['gigneo_unread_messages_count'] ?? 0;

                if (unread_messages !== last_unread_messages) {
                    //Side Menu Link
                    let message_sidebar_link = $(document).find('.gn-menu-message .gn-count');
                    if (message_sidebar_link.length) {
                        message_sidebar_link.html(unread_messages ?? '');
                    }

                    //Nav Menu Link
                    let message_menu_link = $(document).find('.gn-user-chat .gn-count');
                    if (message_menu_link.length) {
                        message_menu_link.html(unread_messages ?? '');
                    }

                    if (unread_messages !== last_unread_messages) {
                        chat_dropdown_markup();
                    }
                }

                last_unread_messages = unread_messages;
            }

            //Trigger Notification
            $(document).trigger('gigneo_heartbeat_trigger', data);

        });

    }

    $(document).on('gigneo_refresh_notification_dropdown', function () {
        notification_dropdown_markup();
    });

    $(document).on('gigneo_refresh_chat_dropdown', function () {
        chat_dropdown_markup();
    });

    /* ===================================
        Notification Dropdown
    ====================================== */

    $(document).on('click', '.gn-action-menu-wrapper .gn-user-notification > .gn-icon', function (e) {
        e.preventDefault();
        let _this = $(this);
        _this.parents('.gn-user-notification').toggleClass('gn-active');
    });

    //Close the menu when clicking outside
    $(document).on('click', function (e) {
        if (!$(e.target).closest('.gn-user-notification').length) {
            $('.gn-user-notification').removeClass('gn-active');
        }
    });

    //Mark notification as read/unread
    $(document).on('click', '.gn-dropdown-notification-mark-read', function (e) {
        e.preventDefault();
        let _this = $(this);
        let id = _this.attr('data-gn-id');
        let status = _this.attr('data-gn-status');

        _this.addClass('gn-loading').attr('disabled', 'disabled');

        $.ajax({
            url: GigneoCommon.ajax_url,
            type: 'POST',
            data: {
                action: 'gigneo_mark_notifications_status',
                security: GigneoCommon.security,
                ids: [id],
                status: status
            },
            success: function (response) {
                _this.removeClass('gn-loading').attr('disabled', false);
                if (response.success && response?.data?.ids && response?.data?.status) {
                    let notifications = response?.data?.ids;
                    let status_type = 'read' === response.data.status ? 'unread' : 'read';
                    _this.attr('data-gn-status', status_type);
                    $.each(notifications, function (key, id) {
                        $(document).find(`#gn-notification-in-line-${id}`).removeClass('gn-unread gn-read').addClass(`gn-${response.data.status}`);
                    });
                }
            },
            error: function (xhr) {
                _this.removeClass('gn-loading').attr('disabled', false);
                let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                GigneoAlert.toast({
                    icon: 'error',
                    title: GigneoCommon.error,
                    text: error_message
                });
            }
        });
    });

    //Notification Dropdown Markup
    function notification_dropdown_markup() {
        let selector = $(document).find('.gn-notification-dropdown');
        if (selector.length) {
            $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'GET',
                data: {
                    action: 'gigneo_notification_dropdown',
                    security: GigneoCommon.security
                },
                success: function (response) {
                    if (response.success && response?.data?.markup?.notification) {
                        let new_selector = $(response?.data?.markup?.notification);
                        let notifications = new_selector.find('.gn-notifications').html();
                        if (notifications.length) {
                            selector.find('.gn-notifications').html(notifications);
                        }
                    }
                }
            });
        }
    }

    /* ===================================
        Message Dropdown
     ====================================== */

    $(document).on('click', '.gn-action-menu-wrapper .gn-user-chat > .gn-icon', function (e) {
        e.preventDefault();
        let _this = $(this);
        _this.parents('.gn-user-chat').toggleClass('gn-active');
    });

    //Close the menu when clicking outside
    $(document).on('click', function (e) {
        if (!$(e.target).closest('.gn-user-chat').length) {
            $('.gn-user-chat').removeClass('gn-active');
        }
    });

    //Chat Dropdown Markup
    function chat_dropdown_markup() {
        let selector = $(document).find('.gn-chat-dropdown');
        if (selector.length) {
            $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'GET',
                data: {
                    action: 'gigneo_chat_dropdown',
                    security: GigneoCommon.security
                },
                success: function (response) {
                    if (response.success && response?.data?.markup?.chat) {
                        let new_selector = $(response?.data?.markup?.chat);
                        let chats = new_selector.find('.gn-chats').html();
                        if (chats.length) {
                            selector.find('.gn-chats').html(chats);
                        }
                    }
                }
            });
        }
    }

    let isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
    if (isIOS) {
        $(document).on('select2:open', '.gn-select2', function () {
            let search_field = document.find('.select2-search__field');
            if (search_field) {
                search_field.setAttribute('readonly', 'readonly');
                search_field.blur();
            }
        });
    }

}(jQuery));