(function ($) {
    "use strict";

    /* ===================================
       Profile Reviews - Show More
    ====================================== */

    $(document).on('click', '.gn-show-more-reviews', function (e) {
        e.preventDefault();

        let _this = $(this);
        let wrapper = _this.closest('.gn-section');
        let hidden_items = wrapper.find('.gn-review-item-hidden');

        let original_html = _this.data('original-html');
        let less_text = _this.data('less');

        if (!original_html) {
            original_html = _this.html();
            _this.data('original-html', original_html);
        }

        if (_this.hasClass('expanded')) {

            hidden_items.hide();
            _this.removeClass('expanded');
            _this.html(original_html);

        } else {

            hidden_items.show();
            _this.addClass('expanded');
            _this.html(less_text + ' <i class="hi hi-chevron-up"></i>');
        }
    });

    /* ===================================
        Authentication
     ====================================== */

    // Popups
    if ($('.gn-auth-popup-wrapper').length) {

        // Login toggle
        $(document).on('click', '.gn-login-popup-toggle', function (e) {
            e.preventDefault();
            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');
        });

        //Register toggle
        $(document).on('click', '.gn-register-popup-toggle', function (e) {
            e.preventDefault();
            let _popup_wrapper = $('#gn-auth-popup');
            let _forms = _popup_wrapper.find('.gn-auth-content > form');
            _forms.hide();
            _forms.filter('#gn-auth-register').show();
            _popup_wrapper.addClass('gn-active');
        });

        //Click Outside popup close
        $(document).on('click', '.gn-auth-popup-wrapper', function (event) {
            if (!$(event.target).closest('.gn-auth-inner').length) {
                $('.gn-auth-popup-wrapper').removeClass('gn-active');
            }
        });

        //Toggle forgot password
        $(document).on('click', '.gn-auth-popup-wrapper .gn-forgot-password', function (e) {
            e.preventDefault();
            let _wrapper = $(this).parents('.gn-auth-content');
            _wrapper.find('form').hide();
            _wrapper.find('form#gn-auth-forgot-password').show();
            _wrapper.find('form#gn-auth-change-password').show();
        });

        //Toggle sign in
        $(document).on('click', '.gn-auth-popup-wrapper .gn-sign-in', function (e) {
            e.preventDefault();
            let _wrapper = $(this).parents('.gn-auth-content');
            _wrapper.find('form').hide();
            _wrapper.find('form#gn-auth-login').show();
        });

        //Toggle sign up
        $(document).on('click', '.gn-auth-popup-wrapper .gn-sign-up', function (e) {
            e.preventDefault();
            let _wrapper = $(this).parents('.gn-auth-content');
            _wrapper.find('form').hide();
            _wrapper.find('form#gn-auth-register').show();
        });

        //Close popup
        $(document).on('click', '#gn-auth-popup-close', function (e) {
            e.preventDefault();
            $('.gn-auth-popup-wrapper').removeClass('gn-active');
        });

    }

    //Login form submit
    $(document).on('submit', '#gn-auth-login', function (e) {
        e.preventDefault();

        let _this = $(this);
        let action = _this.data('action');
        let proceed = true;
        let form_data = new FormData(this);
        form_data.append('action', action);
        form_data.append('security', GigneoCommon.security);

        //Fields validation
        proceed = window.GigneoRequiredFormFields.init(_this, proceed);

        if (proceed) {

            let submit_btn = _this.find('#gn-login-form-submit-btn');

            submit_btn.addClass('gn-loading');

            $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'POST',
                data: form_data,
                contentType: false,
                processData: false,
                success: function (response) {
                    submit_btn.removeClass('gn-loading');
                    if (response.data.message) {
                        GigneoAlert.toast({
                            icon: 'success',
                            title: GigneoCommon.success,
                            text: response.data.message
                        });
                    }
                    submit_btn.removeClass('gn-loading');
                    window.location.href = response.data.redirect || GigneoCommon.home_url;
                },
                error: function (xhr, status, error) {
                    submit_btn.removeClass('gn-loading');
                    let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                    GigneoAlert.toast({
                        icon: 'error',
                        text: error_message
                    });
                }
            });
        }
    });

    //Forgot password form submit
    $(document).on('submit', '#gn-auth-forgot-password', function (e) {
        e.preventDefault();

        let _this = $(this);
        let action = _this.data('action');
        let proceed = true;
        let form_data = new FormData(this);
        form_data.append('action', action);
        form_data.append('security', GigneoCommon.security);

        //Fields validation
        proceed = window.GigneoRequiredFormFields.init(_this, proceed);

        if (proceed) {

            let submit_btn = _this.find('#gn-forgot-password-form-submit-btn');

            submit_btn.addClass('gn-loading');

            $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'POST',
                data: form_data,
                contentType: false,
                processData: false,
                success: function (response) {
                    submit_btn.removeClass('gn-loading');
                    if (response.data.message) {
                        GigneoAlert.toast({
                            icon: 'success',
                            title: GigneoCommon.success,
                            text: response.data.message
                        });
                    }
                    submit_btn.removeClass('gn-loading');
                },
                error: function (xhr, status, error) {
                    submit_btn.removeClass('gn-loading');
                    let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                    GigneoAlert.toast({
                        icon: 'error',
                        text: error_message
                    });
                }
            });


        }

    });

    //Change password form submit
    $(document).on('submit', '#gn-auth-change-password', function (e) {
        e.preventDefault();

        let _this = $(this);
        let action = _this.data('action');
        let proceed = true;
        let form_data = new FormData(this);
        let urlParams = new URLSearchParams(window.location.search);

        urlParams.forEach((value, key) => {
            form_data.append(key, value);
        });

        form_data.append('action', action);
        form_data.append('security', GigneoCommon.security);

        //Fields validation
        proceed = window.GigneoRequiredFormFields.init(_this, proceed);

        if (proceed) {

            let submit_btn = _this.find('#gn-change-password-form-submit-btn');

            submit_btn.addClass('gn-loading');

            $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'POST',
                data: form_data,
                contentType: false,
                processData: false,
                success: function (response) {
                    submit_btn.removeClass('gn-loading');
                    if (response.data.message) {
                        GigneoAlert.toast({
                            icon: 'success',
                            title: GigneoCommon.success,
                            text: response.data.message
                        });
                    }
                    submit_btn.removeClass('gn-loading');
                    window.location.href = response.data.redirect || GigneoCommon.home_url;
                },
                error: function (xhr, status, error) {
                    submit_btn.removeClass('gn-loading');
                    let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                    GigneoAlert.toast({
                        icon: 'error',
                        text: error_message
                    });
                }
            });
        }

    });

    //Register multistep continue
    $(document).on('click', '.gn-auth-register-continue-btn', function (e) {
        e.preventDefault();

        let _this = $(this);
        let proceed = true;

        //Fields input validation
        proceed = window.GigneoRequiredFormFields.init(_this.parents('.gn-auth-register-step'), proceed);

        if (proceed) {

            let step = _this.data('step');
            let step_wrapper = $('#' + step);
            let siblings = step_wrapper.siblings('.gn-auth-register-step')

            siblings.hide();
            step_wrapper.show();

        }

    });

    //Register multistep back
    $(document).on('click', '.gn-auth-register-back-btn', function (e) {
        e.preventDefault();
        let _this = $(this);
        let step = _this.data('step');
        let step_wrapper = $('#' + step);
        let siblings = step_wrapper.siblings('.gn-auth-register-step')

        siblings.hide();
        step_wrapper.show();
    });

    let username_timeout;
    let username_ajaxRequest;
    let username_validate = false;

    //Validate username
    $(document).on('input', '#gn-user-name', function (e) {
        e.preventDefault();

        clearTimeout(username_timeout);
        if (username_ajaxRequest) {
            username_ajaxRequest.abort();
        }

        let _this = $(this);
        let value = _this.val();
        let sanitizedValue = value.replace(/[^a-z0-9_-]/g, "");

        _this.val(sanitizedValue);
        username_validate = false;

        _this.removeClass('gn-input-success');
        _this.removeClass('gn-input-invalid');
        _this.removeClass('gn-loading');

        if (sanitizedValue.length < 4) {
            return;
        }

        _this.addClass('gn-loading');
        _this.next('.gn-user-name-notice').remove();

        username_timeout = setTimeout(function () {
            username_ajaxRequest = $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'POST',
                data: {
                    action: 'gigneo_username_validate',
                    username: sanitizedValue,
                    security: GigneoCommon.security
                },
                success: function (response) {
                    username_validate = true;
                    _this.removeClass('gn-loading');
                    _this.addClass('gn-input-success');
                },
                error: function (xhr, status, error) {
                    username_validate = false;
                    let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                    _this.after('<p class="gn-user-name-notice" >' + error_message + '</p>');
                    _this.removeClass('gn-loading');
                    _this.addClass('gn-input-invalid');
                }
            });
        }, 1000);

    });

    //Register form submit
    $(document).on('submit', '#gn-auth-register', function (e) {
        e.preventDefault();

        let _this = $(this);
        let action = _this.data('action');
        let proceed = true;
        let form_data = new FormData(this);
        form_data.append('action', action);
        form_data.append('security', GigneoCommon.security);

        //Fields validation
        proceed = window.GigneoRequiredFormFields.init(_this, proceed);

        if (_this.find('#gn-user-name').length && !username_validate) {
            proceed = false;
            $('#gn-user-name').addClass('gn-input-error');
        }

        if (proceed) {

            let submit_btn = _this.find('#gn-register-form-submit-btn');

            submit_btn.addClass('gn-loading');

            $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'POST',
                data: form_data,
                contentType: false,
                processData: false,
                success: function (response) {
                    submit_btn.removeClass('gn-loading');
                    if (response.data.message) {
                        GigneoAlert.toast({
                            icon: 'success',
                            title: GigneoCommon.success,
                            text: response.data.message
                        });
                    }
                    window.location.href = response.data.redirect || GigneoCommon.home_url;
                },
                error: function (xhr, status, error) {
                    submit_btn.removeClass('gn-loading');
                    let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                    GigneoAlert.toast({
                        icon: 'error',
                        text: error_message
                    });
                }
            });


        }

    });

    /* ===================================
       Sticky Header
    ====================================== */

    $(document).ready(function () {
        let sticky_header = $('.gn-header-layout.gn-sticky');
        if (sticky_header.length) {
            let header_height = sticky_header.outerHeight();
            sticky_header.css('min-height', header_height + 'px');
            $(window).on('scroll', function () {
                if ($(window).scrollTop() > 300) {
                    sticky_header.addClass('gn-appear');
                } else {
                    sticky_header.removeClass('gn-appear');
                }
            });
        }
    });

    /* ===================================
       Social register
    ====================================== */

    //Google Auth
    $(document).on('input', '#gn-google-auth-username', function (e) {
        e.preventDefault();

        clearTimeout(username_timeout);
        if (username_ajaxRequest) {
            username_ajaxRequest.abort();
        }

        let _this = $(this);
        let value = _this.val();
        let role = $('input[google_auth_role="role"]:checked').val();
        let sanitizedValue = value.replace(/[^a-z0-9_-]/g, "");

        let create_button = $('#gn-register-google-account');

        _this.val(sanitizedValue);
        username_validate = false;

        _this.removeClass('gn-input-success');
        _this.removeClass('gn-input-invalid');
        _this.removeClass('gn-loading');
        _this.next('.gn-user-name-notice').remove();

        create_button.removeAttr('data-gn-google-url');
        create_button.attr('disabled', 'disabled');

        if (sanitizedValue.length < 4) {
            return;
        }

        _this.addClass('gn-loading');

        username_timeout = setTimeout(function () {
            username_ajaxRequest = $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'POST',
                data: {
                    action: 'gigneo_google_oauth_url',
                    username: sanitizedValue,
                    role: role,
                    security: GigneoCommon.security
                },
                success: function (response) {
                    if (response.success && response?.data?.google_url) {
                        create_button.removeAttr('disabled');
                        create_button.attr('data-gn-google-url', response?.data?.google_url)
                        username_validate = true;
                        _this.removeClass('gn-loading');
                        _this.addClass('gn-input-success');
                    } else {
                        let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                        _this.after('<p class="gn-user-name-notice" >' + error_message + '</p>');
                        _this.removeClass('gn-loading');
                        _this.addClass('gn-input-invalid');
                    }
                },
                error: function (xhr, status, error) {
                    username_validate = false;
                    create_button.removeAttr('data-gn-google-url');
                    create_button.attr('disabled', 'disabled');
                    let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                    _this.after('<p class="gn-user-name-notice" >' + error_message + '</p>');
                    _this.removeClass('gn-loading');
                    _this.addClass('gn-input-invalid');
                }
            });
        }, 1000);

    });

    $(document).on('click', '[data-gn-google-url]', function (e) {
        e.preventDefault();

        let _this = $(this);
        let google_url = _this.attr('data-gn-google-url');

        if (!google_url) {
            return false;
        }

        const popup = window.open(
            google_url,
            'google_auth',
            'width=600,height=700,left=' + (screen.width - 600) / 2 + ',top=' + (screen.height - 700) / 2
        );

        if (!popup) {
            return;
        }

        // This will now work because PHP sends real object
        window.addEventListener('message', function handler(e) {
            if (!e.data || !e.data.type) return;

            // Remove listener immediately
            window.removeEventListener('message', handler);

            if (e.data.type === 'GIGNEO_GOOGLE_SUCCESS') {
                GigneoAlert.toast({
                    icon: 'success',
                    title: 'Success',
                    text: e.data.message || 'Logged in!'
                });

                if (e.data.redirect) {
                    setTimeout(() => location.href = e.data.redirect, 1200);
                }
            }

            if (e.data.type === 'GIGNEO_GOOGLE_ERROR') {
                GigneoAlert.toast({
                    icon: 'error',
                    title: 'Error',
                    text: e.data.message
                });
            }
        });

    })

    // LinkedIn Auth
    $(document).on('click', '[data-gn-linkedin-url]', function (e) {
        e.preventDefault();

        const url = $(this).attr('data-gn-linkedin-url');
        if (!url) return;

        const popup = window.open(
            url,
            'linkedin_auth',
            'width=600,height=700,left=' + (screen.width - 600) / 2 + ',top=' + (screen.height - 700) / 2
        );

        if (!popup) return;

        window.addEventListener('message', function handler(e) {

            if (!e.data || !e.data.type) return;

            window.removeEventListener('message', handler);

            if (e.data.type === 'GIGNEO_LINKEDIN_SUCCESS') {
                GigneoAlert.toast({
                    icon: 'success',
                    title: 'Success',
                    text: e.data.message || 'LinkedIn Connected!'
                });

                if (e.data.redirect) {
                    setTimeout(() => location.href = e.data.redirect, 1200);
                }
            }

            if (e.data.type === 'GIGNEO_LINKEDIN_ERROR') {
                GigneoAlert.toast({
                    icon: 'error',
                    title: 'Error',
                    text: e.data.message
                });
            }
        });
    });

    $(document).on('input', '#gn-linkedin-auth-username', function (e) {
        e.preventDefault();

        clearTimeout(username_timeout);
        if (username_ajaxRequest) {
            username_ajaxRequest.abort();
        }

        let _this = $(this);
        let value = _this.val();
        let role = $('input[linkedin_auth_role="role"]:checked').val() || $('input[name="linkedin_auth_role"]:checked').val();
        // sanitize similar to google
        let sanitizedValue = value.replace(/[^a-z0-9_-]/g, "");

        let create_button = $('#gn-register-linkedin-account');

        _this.val(sanitizedValue);
        username_validate = false;

        _this.removeClass('gn-input-success gn-input-invalid gn-loading');
        _this.next('.gn-user-name-notice').remove();

        create_button.removeAttr('data-gn-linkedin-url').attr('disabled', 'disabled');

        if (sanitizedValue.length < 4) {
            return;
        }

        _this.addClass('gn-loading');

        username_timeout = setTimeout(function () {
            username_ajaxRequest = $.ajax({
                url: GigneoCommon.ajax_url,
                type: 'POST',
                data: {
                    action: 'gigneo_linkedin_oauth_url',
                    username: sanitizedValue,
                    role: role,
                    security: GigneoCommon.security
                },
                success: function (response) {
                    if (response.success && response?.data?.linkedin_url) {
                        create_button.removeAttr('disabled');
                        create_button.attr('data-gn-linkedin-url', response?.data?.linkedin_url);
                        username_validate = true;
                        _this.removeClass('gn-loading').addClass('gn-input-success');
                    } else {
                        let error_message = (response?.data?.message) ? response.data.message : GigneoCommon.went_wrong;
                        _this.after('<p class="gn-user-name-notice" >' + error_message + '</p>');
                        _this.removeClass('gn-loading').addClass('gn-input-invalid');
                    }
                },
                error: function (xhr, status, error) {
                    username_validate = false;
                    create_button.removeAttr('data-gn-linkedin-url').attr('disabled', 'disabled');
                    let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                    _this.after('<p class="gn-user-name-notice" >' + error_message + '</p>');
                    _this.removeClass('gn-loading').addClass('gn-input-invalid');
                }
            });
        }, 1000);
    });

    /* ===================================
       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
                });
            }
        });
    });

    /* ===================================
      Submit proposal
   ====================================== */

    // Submit proposal
    $(document).on('click', '.gn-job-error', function (e) {
        e.preventDefault();
        let _this = $(this);
        let msg_key = _this.data('gn-message');
        let message = GigneoCommon[msg_key];
        GigneoAlert.toast({
            icon: 'error', title: GigneoCommon.error, text: message || GigneoCommon.went_wrong
        });
    });

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

    //Responsive filter open/close
    $(document).on('click', '#gn-responsive-filter-toggle,#gn-responsive-filter-close', function (e) {
        e.preventDefault();
        let _this = $(this);
        _this.parents('.gn-archive-filter-wrapper').toggleClass('gn-active');
    });

    //Open dropdown
    $(document).on('click', '.gn-filter-dropdown-container:not(.gn-active) .gn-filter-dropdown-toggle', function (e) {
        e.preventDefault();
        let _this = $(this);
        $('.gn-filter-dropdown-container').removeClass('gn-active');
        _this.parents('.gn-filter-dropdown-container').addClass('gn-active');
    });

    //Close Dropdown
    $(document).on('click', '.gn-filter-dropdown-container.gn-active .gn-filter-dropdown-toggle', function (e) {
        e.preventDefault();
        let _this = $(this);
        _this.parents('.gn-filter-dropdown-container').removeClass('gn-active');
    });

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

    //Category change
    $(document).on('change', '.gn-archive-filters #gn-category', function () {
        let _this = $(this);
        let category = _this.val();
        let form = _this.closest('.gn-form-fields');
        let sub_selector = form.find('#gn-subcategory');
        let specific_types = form.find('.gn-specific-types');
        let categories = sub_selector.data('gn-categories') || {};

        // Reset fields
        sub_selector.empty().prop('disabled', true);
        specific_types.empty();

        // Check if category exists
        if (category && categories.hasOwnProperty(category)) {
            let sub_categories = categories[category];

            // Enable dropdown
            sub_selector.prop('disabled', false);

            // Default empty option
            sub_selector.append(
                $('<option>', {
                    value: '',
                    text: 'Select Subcategory'
                })
            );

            // Handle both OBJECT and ARRAY formats
            if (Array.isArray(sub_categories)) {
                sub_categories.forEach(function (item) {
                    sub_selector.append(
                        $('<option>', {
                            value: item.value || item.id,
                            text: item.label || item.name
                        })
                    );
                });
            } else {
                Object.entries(sub_categories).forEach(function ([value, label]) {
                    sub_selector.append(
                        $('<option>', {
                            value: value,
                            text: label
                        })
                    );
                });
            }

            // Refresh Select2 if used
            sub_selector.trigger('change.select2');
        }

    });

    //Sub Category change
    $(document).on('change', '.gn-archive-filters #gn-subcategory', function () {

        let _this = $(this);
        let category = _this.val();
        let formFields = _this.parents('.gn-form-fields');
        let specific_field = formFields.find('.gn-specific-types-field');
        let specific_types = formFields.find('.gn-specific-types');
        let categories = _this.data('gn-categories');

        specific_types.empty();
        specific_field.addClass('gn-hide');

        if (category && categories && categories[category] !== undefined) {

            let sub_categories = categories[category];

            if (sub_categories && Object.keys(sub_categories).length > 0) {

                Object.entries(sub_categories).forEach(function ([value, label]) {

                    if (typeof label !== "string") return;

                    let uniqueId = `gn-specific-type-${value}`;

                    let wrapper = $('<div>', {
                        class: 'gn-checkbox'
                    });

                    let input = $('<input>', {
                        type: 'checkbox',
                        value: value,
                        name: 'specific_types[]',
                        id: uniqueId
                    });

                    let labelEl = $('<label>', {
                        for: uniqueId
                    }).append(
                        $('<span>').text(label)
                    );

                    wrapper.append(input).append(labelEl);
                    specific_types.append(wrapper);
                });

                specific_field.removeClass('gn-hide');
            }
        }
    });

    //Price Range Slider
    $(document).ready(function () {
        let price_range_selector = $('.gn-price-range-slider');

        if (price_range_selector.length) {
            let price_min = price_range_selector.data('gn-min') || 0;
            let price_max = price_range_selector.data('gn-max') || 10000;

            let selected_min = $('#gn-min-price').val() || price_min;
            let selected_max = $('#gn-max-price').val() || price_max;

            let price_range_slider = noUiSlider.create(price_range_selector[0], {
                start: [selected_min, selected_max],
                step: 5,
                connect: true,
                range: {
                    'min': [price_min],
                    'max': [price_max]
                },
                format: {
                    to: function (value) {
                        return Math.round(value);
                    },
                    from: function (value) {
                        return Number(value);
                    }
                }
            });

            price_range_slider.on('update', function (values) {
                let min = values[0];
                let max = values[1];
                $('#gn-min-price').val(min);
                $('#gn-max-price').val(max);
            });
        }
    });

    //Radius Range Slider Simple
    $(document).ready(function () {
        let radius_range_selector = $('.gn-radius-range-slider');

        if (radius_range_selector.length) {
            let radius_min = radius_range_selector.data('gn-min') || 1;
            let radius_max = radius_range_selector.data('gn-max') || 100;
            let radius_start = radius_range_selector.data('gn-start') || 10;

            let radius_range_slider = noUiSlider.create(radius_range_selector[0], {
                start: [radius_start],
                step: 1,
                connect: [true, false],
                range: {
                    'min': [radius_min],
                    'max': [radius_max]
                },
                format: {
                    to: function (value) {
                        return Math.round(value);
                    },
                    from: function (value) {
                        return Number(value);
                    }
                }
            });

            radius_range_slider.on('slide', function (values) {
                let val = values[0];
                let wrapper = radius_range_selector.closest('.gn-radius-slider-wrapper');
                wrapper.find('#gn-radius-slider').val(val).trigger('input');
                wrapper.find('.gn-radius-number').text(val);
            });
        }
    });

    //More filters
    $(document).on('change', '.gn-more-filter-dropdown input[type="checkbox"],.gn-delivery-filter-dropdown input[type="checkbox"],.gn-type-filter-dropdown input[type="checkbox"],.gn-ratings-filter-dropdown input[type="radio"],.gn-amount-earned-filter-dropdown input[type="radio"],.gn-order-completed-filter-dropdown input[type="radio"],.gn-orders-completed-filter-dropdown input[type="radio"]', function (e) {
        e.preventDefault();
        if (window.gnClearingFilters) return;
        let _this = $(this);
        _this.parents('form').submit();
    });

    //Clear filter
    $(document).on('click', '.gn-archive-filters .gn-clear-filter', function (e) {
        e.preventDefault();
        let _this = $(this);
        let dropdown = _this.parents('.gn-filter-dropdown-container');
        let body = dropdown.find('.gn-filter-dropdown .gn-body');

        window.gnClearingFilters = true;

        body.find('select').val('').trigger('change');
        body.find('input[type="checkbox"]').prop('checked', false);
        body.find('input[type="radio"]').prop('checked', false);
        body.find('.gn-price-range-slider')[0]?.noUiSlider.reset();

        window.gnClearingFilters = false;

        _this.parents('form').submit();
        dropdown.removeClass('gn-active');
    });

    //Clear all Filters
    $(document).on('click', '.gn-archive-filters .gn-clear-filters', function (e) {
        e.preventDefault();
        let _this = $(this);
        let form = _this.parents('#gn-archive-filters-form');

        window.gnClearingFilters = true;

        form.find('.gn-price-range-slider')[0]?.noUiSlider?.reset();
        form.find('select').val('').trigger('change');
        form.find('input[type="text"], input[type="search"], input[type="hidden"], input[type="number"]').val('');
        form.find('input[type="checkbox"]').prop('checked', false);
        form.find('input[type="radio"]').prop('checked', false);

        window.gnClearingFilters = false;

        form.submit();
    });

    /* ===================================
       Service Detail
    ====================================== */

    //Media slider
    if ($('.gn-service-media-slider').length) {
        $('.gn-service-media-slider').slick({
            dots: true,
            arrows: true,
            infinite: false,
            speed: 300,
            slidesToShow: 1,
            slidesToScroll: 1,
            rtl: $('html').attr('dir') === 'rtl'
        });
    }

    //Plan change
    $(document).on('change', '.gn-service-pricing-tabs input[name="plan"]', function (e) {
        e.preventDefault();
        let _this = $(this);
        let value = _this.val();
        let tab_content = $('.gn-service-pricing-tabs-content');
        tab_content.find('.gn-service-pricing-tab-content').removeClass('gn-active');
        tab_content.find(`#gn-service-pricing-tab-content-plan-${value}`).addClass('gn-active');
    });

    //Location change
    $(document).on('change', '.gn-service-location input[name="location_key"]', function (e) {
        e.preventDefault();
        let _this = $(this);
        let location_id = _this.val();
        let wrapper = $('.gn-service-location-wrapper');
        let parent = _this.parents('.gn-service-location');
        let delivery_type = $('input[name="delivery_type"]:checked').val();
        wrapper.find('.gn-location-details').addClass('gn-hide');
        wrapper.find('.gn-service-location .gn-required-field').addClass('gn-not-required-field').removeClass('gn-required-field');
        parent.find('.gn-location-details .gn-not-required-field').addClass('gn-required-field').removeClass('gn-not-required-field')
        parent.find('.gn-location-details').removeClass('gn-hide');
        if ('visit_me' === delivery_type) {
            parent.find('#gn-map-address-' + location_id).removeClass('gn-required-field');
            parent.find('#gn-hire-address-' + location_id).removeClass('gn-required-field');
        } else {
            parent.find('#gn-map-address-' + location_id).addClass('gn-required-field');
            parent.find('#gn-hire-address-' + location_id).addClass('gn-required-field');
        }
    });

    //Delivery type change
    $(document).on('change', '.gn-service-delivery-type input[name="delivery_type"]', function (e) {
        e.preventDefault();
        let _this = $(this);
        let wrapper = $(_this.parents('.gn-service-delivery-type'));
        let value = _this.val();
        let map_location_field = $('.gn-service-delivery-type .gn-map-location-field');
        let map_address_field = $('.gn-service-delivery-type .gn-location-address-field');
        map_location_field.find('input').val('').trigger('change');

        if ('visit_me' === value) {
            map_location_field.addClass('gn-hide');
            wrapper.find('.gn-max-radius').addClass('gn-hide');
            map_location_field.find('.gn-required-field').addClass('gn-not-required-field').removeClass('gn-required-field');
            map_address_field.addClass('gn-hide');
            map_address_field.find('.gn-required-field').addClass('gn-not-required-field').removeClass('gn-required-field');
        } else {
            map_location_field.removeClass('gn-hide');
            wrapper.find('.gn-max-radius').removeClass('gn-hide');
            map_location_field.find('.gn-not-required-field').addClass('gn-required-field').removeClass('gn-not-required-field');
            map_address_field.removeClass('gn-hide');
            map_address_field.find('.gn-not-required-field').addClass('gn-required-field').removeClass('gn-not-required-field');
        }

    });


    //Service order process
    $(document).on('submit', '#gn-service-single-pricing-form', function (e) {
        e.preventDefault();
        let _this = $(this);
        let form_data = new FormData(_this[0]);
        form_data.append('action', 'gigneo_service_order_process');
        form_data.append('security', GigneoCommon.security);

        let proceed = window.GigneoRequiredFormFields.init(_this, true);

        if (proceed) {
            _this.find('button[type="submit"]').addClass("gn-loading").attr('disabled', true);
            $.ajax({
                url: GigneoCommon.ajax_url,
                method: 'POST',
                data: form_data,
                contentType: false,
                processData: false,
                success: function (response) {
                    _this.find('button[type="submit"]').removeClass("gn-loading").attr('disabled', false);
                    if (response.success && response.data.redirect_url) {
                        window.location.href = response.data.redirect_url;
                    }
                },

                error: function (xhr, status, error) {
                    _this.find('button[type="submit"]').removeClass("gn-loading").attr('disabled', false);
                    let error_message = xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong;
                    GigneoAlert.toast({
                        icon: 'error',
                        text: error_message
                    });
                },
            });
        }

    });

    /* ===================================
        Hire
    ====================================== */

    if ($('.gn-hire').length) {
        // Intake Attachments
        const intakeFormAttachments = {};
        const proposalAttachments = {};

        //Initialize PlUploader
        $('.gn-hire .gn-plupload-container').each((i, container) => {
            let index = $(container).data('gn-index');
            initIntakeFormPluploadInit(index);
        });

        // Initialize Proposal Attachments (Plupload)
        const proposalPlupload = window.GigneoPlupload.init({
            browseButtonId: 'gn-proposal-attachment-uploader',
            containerId: 'gn-proposal-attachment-container',
            dropElementId: 'gn-proposal-attachment-drop-area',
            attachmentListId: 'gn-proposal-attachment-list',
            allowedExtensions: GigneoCommon.job_order_extensions || ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'mp4'],
            maxFiles: parseInt(GigneoCommon.job_order_limit) || 1,
            maxSizeMb: parseInt(GigneoCommon.job_order_max_size) || 1,
        });

        if (proposalPlupload) {
            proposalAttachments.files = proposalPlupload.files;
            proposalAttachments.uploader = proposalPlupload.uploader;

            // Handle existing proposal attachment removal
            $('#gn-proposal-attachment-list .gn-existing').on('click', '.gn-attachment-remove', function (e) {
                let _this = $(this);
                let attachmentId = _this.data('attachment-id');
                let postId = _this.data('post-id');

                if (attachmentId && !_this.data('file-id')) { // Only handle database attachments here
                    _this.addClass('gn-loading');
                    $.ajax({
                        url: GigneoCommon.ajax_url,
                        type: 'POST',
                        data: {
                            action: 'gigneo_remove_attachment',
                            attachment_id: attachmentId,
                            post_id: postId,
                            security: GigneoCommon.security
                        },
                        success: function (response) {
                            _this.removeClass('gn-loading');
                            if (response.success) {
                                _this.closest(`.gn-attachment-item`).fadeOut(100, function () {
                                    $(this).remove();
                                });
                            } else {
                                GigneoAlert.toast({
                                    icon: 'error',
                                    text: response.data.message || 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
                            });
                        }
                    });
                }
            });
        }

        function initIntakeFormPluploadInit(index) {

            if (typeof plupload !== 'object') {
                return;
            }

            // Unique IDs for this uploader
            const containerId = `gn-intake-form-attachment-container-${index}`;
            const browseButtonId = `gn-intake-form-attachment-uploader-${index}`;
            const dropAreaId = `gn-intake-form-attachment-drop-area-${index}`;
            const attachmentListId = `gn-intake-form-attachment-list-${index}`;

            // Initialize file array for this uploader
            intakeFormAttachments[index] = { files: [], uploader: null };

            // Get settings from GigneoCommon or defaults
            const extensions = GigneoCommon.intake_form_extensions || ['jpg', 'jpeg', 'png', 'doc'];
            const maxFiles = parseInt(GigneoCommon.intake_form_max_files) || 3;
            const maxSize = parseInt(GigneoCommon.intake_form_max_size) || 1;

            // Initialize Plupload
            let uploader = new plupload.Uploader({
                browse_button: browseButtonId,
                container: containerId,
                drop_element: dropAreaId,
                filters: {
                    mime_types: [{ title: 'Files', extensions: extensions.join(',') }],
                    // max_file_count: maxFiles,
                    // max_file_size: `${maxSize}mb`
                }
            });

            uploader.init();
            intakeFormAttachments[index].uploader = uploader;

            uploader.bind('Error', (up, err) => {
                let errorText = err.message || 'An error occurred during file upload.';
                if (err.code === plupload.FILE_EXTENSION_ERROR) {
                    errorText = GigneoCommon.invalid_extension_notice || 'Invalid file type.';
                } else if (err.code === plupload.FILE_SIZE_ERROR) {
                    errorText = GigneoCommon.intake_form_max_size_notice || `File size exceeds ${maxSize}MB.`;
                }
                GigneoAlert.toast({
                    icon: 'error',
                    title: GigneoCommon.error || 'Error',
                    text: errorText
                });
            });

            // Handle FilesAdded
            uploader.bind('FilesAdded', (up, files) => {
                const $attachmentList = $(`#${attachmentListId}`);
                // Check total file count
                if (intakeFormAttachments[index].files.length + files.length > maxFiles) {
                    GigneoAlert.toast({
                        icon: 'error',
                        title: GigneoCommon.error || 'Error',
                        text: GigneoCommon.intake_form_max_files_notice || `Maximum ${maxFiles} files allowed.`
                    });
                    files.forEach(f => up.removeFile(f));
                    return;
                }

                // Validate each file
                files.forEach(file => {
                    const ext = file.name.split('.').pop().toLowerCase();

                    // Check extension
                    if (!extensions.includes(ext)) {
                        GigneoAlert.toast({
                            icon: 'error',
                            title: GigneoCommon.error || 'Error',
                            text: GigneoCommon.invalid_extension_notice || 'Invalid file type.'
                        });
                        up.removeFile(file);
                        return;
                    }

                    // Check file size
                    if (file.size > maxSize * 1024 * 1024) {
                        GigneoAlert.toast({
                            icon: 'error',
                            title: GigneoCommon.error || 'Error',
                            text: GigneoCommon.intake_form_max_size_notice || `File size exceeds ${maxSize}MB.`
                        });
                        up.removeFile(file);
                        return;
                    }

                    // Add to file list and UI
                    intakeFormAttachments[index].files.push(file);
                    $attachmentList.append(
                        `<div id="${file.id}" class="gn-attachment-item">${file.name}<button type="button" class="gn-attachment-remove" data-file-id="${file.id}" data-uploader-index="${index}"><i class="hi hi-trash" aria-hidden="true"></i></button></div>`
                    );
                });

                up.refresh();
            });

            $(document).on('click', '.gn-hire .gn-attachment-remove', function (e) {
                e.preventDefault();
                const $this = $(this);
                const fileId = $this.data('file-id');
                const uploaderIndex = $this.data('uploader-index');

                if (uploader) {
                    const file = uploader.getFile(fileId);
                    if (file) {
                        uploader.removeFile(file);
                        intakeFormAttachments[uploaderIndex].files = intakeFormAttachments[uploaderIndex].files.filter(f => f.id !== fileId);
                        $this.closest(`#${fileId}`).fadeOut(100, function () {
                            $(this).remove();
                        });
                    }
                }
            });

        }


        //Service hire form submit
        $(document).on('submit', '#gn-hire-service-form', function (e) {
            e.preventDefault();

            let _this = $(this);

            let form_data = new FormData(_this[0]);

            // validate before proceeding
            let proceed = window.GigneoRequiredFormFields.init(_this, true);

            $('.gn-hire .gn-plupload-container').each((i, container) => {
                let index = $(container).data('gn-index');
                let required = $(container).data('gn-required');
                let attachment_files = intakeFormAttachments[index].files || [];

                if (required && attachment_files.length === 0) {
                    GigneoAlert.toast({
                        icon: 'error',
                        title: GigneoCommon.error,
                        text: GigneoCommon.required_fields
                    });
                    proceed = false;
                }
            });

            if (!proceed) return;

            let submit_btn = _this.find('button[type="submit"]');

            form_data.append('action', 'gigneo_service_order_place');
            form_data.append('security', GigneoCommon.security);

            // Append files from each uploader
            if (intakeFormAttachments) {
                Object.keys(intakeFormAttachments).forEach(index => {
                    intakeFormAttachments[index].files.forEach(file => {
                        form_data.append(`intake_form_attachments[${index}][]`, file.getNative(), file.name);
                    });
                });
            }

            let url = new URL(window.location.href);
            let params = new URLSearchParams(url.search);

            params.forEach((value, key) => {
                if (key !== 'addons') {
                    form_data.append(key, value);
                }
            });

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

            $.ajax({
                url: GigneoCommon.ajax_url,
                method: 'POST',
                data: form_data,
                contentType: false,
                processData: false,
                success: function (response) {

                    submit_btn.removeClass('gn-loading').attr('disabled', false);

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

                    if (response.data.redirect) {
                        window.location.href = response.data.redirect;
                    }
                },
                error: function (response) {
                    submit_btn.removeClass('gn-loading').attr('disabled', false);
                    GigneoAlert.toast({
                        icon: 'error',
                        title: GigneoCommon.error,
                        text: response.responseJSON && response.responseJSON.data && response.responseJSON.data.message ? response.responseJSON.data.message : ''
                    });
                },
            });

        });

        // Job proposal hire form submit
        $(document).on('submit', '#gn-hire-job-form', function (e) {
            e.preventDefault();

            let _this = $(this);
            let form_data = new FormData(_this[0]);

            // validate before proceeding
            let proceed = window.GigneoRequiredFormFields.init(_this, true);

            $('.gn-hire .gn-plupload-container').each((i, container) => {
                let index = $(container).data('gn-index');
                let required = $(container).data('gn-required');
                let attachment_files = intakeFormAttachments[index].files || [];

                if (required && attachment_files.length === 0) {
                    GigneoAlert.toast({
                        icon: 'error',
                        title: GigneoCommon.error,
                        text: GigneoCommon.required_fields
                    });
                    proceed = false;
                }
            });

            if (!proceed) return;
            // Force TinyMCE editors to save content to textarea before sending
            if (typeof tinyMCE !== 'undefined') {
                tinyMCE.triggerSave();
            }


            let submit_btn = _this.find('button[type="submit"]');

            if (!proceed) return;
            submit_btn.addClass('gn-loading').attr('disabled', true);

            form_data.append('action', 'gigneo_submit_job_proposal');
            form_data.append('security', GigneoCommon.security);

            // Append files from each uploader
            if (intakeFormAttachments) {
                Object.keys(intakeFormAttachments).forEach(index => {
                    intakeFormAttachments[index].files.forEach(file => {
                        form_data.append(`intake_form_attachments[${index}][]`, file.getNative(), file.name);
                    });
                });
            }

            // Append proposal attachments
            if (proposalAttachments && proposalAttachments.files.length > 0) {
                proposalAttachments.files.forEach(file => {
                    form_data.append('proposal_attachments[]', file.getNative(), file.name);
                });
            }


            let url = new URL(window.location.href);
            let params = new URLSearchParams(url.search);

            params.forEach((value, key) => {
                if (key !== 'addons') {
                    form_data.append(key, value);
                }
            });

            $.ajax({
                url: GigneoCommon.ajax_url,
                method: 'POST',
                data: form_data,
                contentType: false,
                processData: false,
                success: function (response) {
                    submit_btn.removeClass('gn-loading').attr('disabled', false);

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

                    if (response.data && response.data.redirect) {
                        window.location.href = response.data.redirect;
                    }
                },
                error: function (response) {
                    submit_btn.removeClass('gn-loading').attr('disabled', false);
                    GigneoAlert.toast({
                        icon: 'error',
                        title: GigneoCommon.error,
                        text: response.responseJSON && response.responseJSON.data && response.responseJSON.data.message ? response.responseJSON.data.message : GigneoCommon.went_wrong
                    });
                },
            });
        });
    }

    /* ===================================
        Archive listing
    ====================================== */

    let $archive_wrapper = $('.gn-archive-wrapper');

    if ($archive_wrapper.length) {

        let archive_ajax_request = null;
        let archive_map_id = $archive_wrapper.data('map-id') || '';
        let archive_ajax_action = $archive_wrapper.data('ajax-action') || '';
        let archive_type = $archive_wrapper.data('archive-type') || '';
        let archive_card_class = '.gn-' + archive_type + '-archive-card';
        let archive_markers = null;

        //params
        function get_archive_form_params() {
            let params = {};

            $('#gn-archive-filters-form')
                .serializeArray()
                .forEach(function (field) {
                    if (!field.value) return;

                    let name = field.name;
                    let isArray = name.endsWith('[]');
                    if (isArray) {
                        name = name.slice(0, -2);
                    }

                    if (isArray) {
                        params[name] = params[name] || [];
                        params[name].push(field.value);
                    } else {
                        params[name] = field.value;
                    }
                });

            return params;
        }

        //Build params
        function build_url_from_params(params) {
            let url_params = new URLSearchParams();

            $.each(params, function (key, val) {
                if (Array.isArray(val)) {
                    let arg_key = key.endsWith('[]') ? key : key + '[]';
                    val.forEach(function (v) {
                        url_params.append(arg_key, v);
                    });
                } else {
                    url_params.append(key, val);
                }
            });

            let qs = url_params.toString();
            return window.location.pathname + (qs ? '?' + qs : '');
        }

        //Ajax
        function handle_archive_response($main, response, scroll) {
            $main.removeClass('gn-loading');
            archive_ajax_request = null;

            if (!response.success) return;

            let data = response.data;

            let $inner = $archive_wrapper.find('.gn-archive-content-inner');
            if ($inner.length) {
                $main.html(data.cards);
                let $content = $archive_wrapper.find('.gn-archive-content');
                let $pagination = $content.find('> .gn-pagination-wrap');
                if ($pagination.length) {
                    if (data.pagination) {
                        $pagination.replaceWith(data.pagination);
                    } else {
                        $pagination.remove();
                    }
                } else if (data.pagination) {
                    $content.append(data.pagination);
                }
            } else {
                $main.html(data.cards + data.pagination);
            }

            if (data.pills !== undefined) {
                let $pillsContainer = $archive_wrapper.find('.gn-active-filters-pills');
                if ($pillsContainer.length) {
                    if (data.pills) {
                        $pillsContainer.replaceWith(data.pills);
                    } else {
                        $pillsContainer.remove();
                    }
                } else if (data.pills) {
                    $archive_wrapper.find('.gn-archive-sort-wrapper').before(data.pills);
                }
            }

            init_archive_sliders();
            bind_pagination_ajax();

            $archive_wrapper.find('.gn-result-count').html(
                (GigneoCommon.result_count_text || '{{count}} Results found')
                    .replace('{{count}}', data.result_count)
            );

            $(document).trigger('gigneo_archive_ajax_response', [data, archive_map_id]);
        }

        //Error handling
        function handle_archive_error($main, xhr , expired_nonce) {
            $main.removeClass('gn-loading');
            archive_ajax_request = null;

            let message = expired_nonce
                ? (GigneoCommon.session_expired_msg || 'Your session has expired. Please reload the page and try again.')
                :
                (xhr?.responseJSON?.data?.message || GigneoCommon.went_wrong);

            GigneoAlert.toast({
                icon: "error",
                title: GigneoCommon.error,
                text: message
            });
        }

        function is_archive_nonce_failure(xhr, response) {
            if (xhr && xhr.status === 403) {
                return true;
            }

            let message = response?.data?.message || '';
            return message.toLowerCase().indexOf('security verification failed') !== -1;
        }

        // Send ajax request (nonce comes from page-localized GigneoCommon.security; no AJAX mint).
        function archive_send_request(params, scroll) {
            let $main = $archive_wrapper.find('.gn-archive-main');
            $main.addClass('gn-loading');

            if (archive_ajax_request) {
                archive_ajax_request.abort();
            }

            let shortcode_options = $archive_wrapper.data('shortcode-options') || {};

            archive_ajax_request = $.ajax({
                url: GigneoCommon.ajax_url,
                method: 'POST',
                data: {
                    action: archive_ajax_action,
                    security: GigneoCommon.security,
                    params: params,
                    shortcode_options: shortcode_options
                },
                success: function (response) {
                    if (!response.success) {
                        handle_archive_error(
                            $main,
                            { responseJSON: response },
                            is_archive_nonce_failure(null, response)
                        );
                        return;
                    }
                    handle_archive_response($main, response, scroll);
                },
                error: function (xhr) {
                    handle_archive_error($main, xhr, is_archive_nonce_failure(xhr));
                }
            });
        }

        //Filter ajax
        function archive_ajax_filter(extra_params, replace = false) {
            let params = replace ? (extra_params || {}) : get_archive_form_params();

            if (!replace && extra_params) {
                $.extend(params, extra_params);
            }

            // auto-insert radius when needed
            if (params.map_location && !params.radius) {
                let slider_val = $('#gn-radius-slider').val();
                if (slider_val) {
                    params.radius = slider_val;
                    $('#gn-map-radius').val(slider_val);
                }
            }

            // update URL
            let new_url = build_url_from_params(params);
            window.history.pushState({ gnArchive: true }, '', new_url);

            archive_send_request(params, true);
            $('.gn-filter-dropdown-container').removeClass('gn-active');
        }

        window.gnArchiveAjaxFilter = archive_ajax_filter;

        //Filter form submit ajax
        $('#gn-archive-filters-form').on('submit', function (e) {
            e.preventDefault();
            archive_ajax_filter();
        });

        //Pagination ajax
        function bind_pagination_ajax() {
            $archive_wrapper
                .off('click.gnPagination')
                .on('click.gnPagination', '.gn-pagination a', function (e) {

                    e.preventDefault();
                    let href = $(this).attr('href');
                    let obj = new URL(href, window.location.origin);

                    let paged =
                        obj.searchParams.get('step') ||
                        obj.searchParams.get('paged') ||
                        '1';

                    archive_ajax_filter({ step: paged });
                });
        }

        bind_pagination_ajax();

        //Pills ajax
        function bind_active_pills_ajax() {
            $archive_wrapper
                .off('click.gnActivePills')
                .on('click.gnActivePills', '.gn-filter-pill', function (e) {
                    e.preventDefault();
                    let href = $(this).attr('href');
                    let obj = new URL(href, window.location.origin);
                    let params = {};

                    // 1. Robustly parse the pill's URL into a nested structure (handles key[] and key[0])
                    obj.searchParams.forEach(function (val, key) {
                        let cleanKey = key.replace(/\[\d*\]$/, '');
                        let isArray = key !== cleanKey;

                        if (isArray) {
                            params[cleanKey] = params[cleanKey] || [];
                            params[cleanKey].push(val);
                        } else {
                            params[cleanKey] = val;
                        }
                    });

                    // 2. Clear ALL form elements first to avoid stale state
                    let $form = $archive_wrapper.find('#gn-archive-filters-form');
                    if ($form.length) {
                        $form[0].reset();
                        // Reset Select2 and other specialized fields
                        $form.find('select').val('').trigger('change.select2');

                        // 3. Re-populate the form using the pill's cleaned params
                        $.each(params, function (key, value) {
                            if (Array.isArray(value)) {
                                value.forEach(v => {
                                    // Try both plural and singular names for safety
                                    $form.find(`[name="${key}[]"][value="${v}"], [name="${key}"][value="${v}"]`).prop('checked', true);
                                });
                            } else {
                                let $input = $form.find(`[name="${key}"]`);
                                if ($input.is(':checkbox, :radio')) {
                                    $form.find(`[name="${key}"][value="${value}"]`).prop('checked', true);
                                } else {
                                    $input.val(value).trigger('change.select2');
                                }
                            }
                        });
                    }

                    // 4. Trigger AJAX after a short delay for UI state to settle
                    setTimeout(function () {
                        archive_ajax_filter(params, true);
                    }, 10);
                });
        }

        bind_active_pills_ajax();

        //Sort ajax
        $(document).on('change', '#gn-sort', function () {
            if (window.gnClearingFilters) return;
            archive_ajax_filter({ step: '1' });
        });

        //Browser Back Button (popstate)
        window.history.replaceState({ gnArchive: true }, '', window.location.href);

        $(window).on('popstate', function (e) {

            if (!e.originalEvent.state || !e.originalEvent.state.gnArchive) {
                return;
            }

            let url_params = new URLSearchParams(window.location.search);
            let params = {};

            url_params.forEach(function (val, key) {
                params[key] = val;
            });

            archive_send_request(params, false);
            init_archive_sliders();
        });

        //Init media slider
        function init_archive_sliders() {
            $('.gn-service-media-slider')
                .not('.slick-initialized')
                .slick({
                    dots: true,
                    arrows: true,
                    infinite: false,
                    speed: 300,
                    slidesToShow: 1,
                    slidesToScroll: 1,
                    rtl: $('html').attr('dir') === 'rtl'
                });
        }

        init_archive_sliders();
    }


})(jQuery);