(function () {
    const DEBOUNCE_MS = 300;

    function debounce(fn, delay) {
        let timer;
        return function (...args) {
            clearTimeout(timer);
            timer = setTimeout(() => fn.apply(this, args), delay);
        };
    }

    function buildUrl(form) {
        const params = new URLSearchParams();
        new FormData(form).forEach((value, key) => {
            if (value) {
                params.append(key, value);
            }
        });
        const action = form.getAttribute('action') || window.location.pathname;
        const query = params.toString();
        return query ? action + '?' + query : action;
    }

    function runSearch(form) {
        const target = document.querySelector(form.dataset.liveTarget);
        if (!target) {
            return;
        }
        const url = buildUrl(form);
        fetch(url, {
            headers: { 'X-Requested-With': 'XMLHttpRequest' },
        })
            .then((response) => {
                if (!response.ok) {
                    throw new Error('search failed');
                }
                return response.text();
            })
            .then((html) => {
                target.innerHTML = html;
                history.replaceState(null, '', url);
            })
            .catch(() => {});
    }

    document.addEventListener('DOMContentLoaded', function () {
        document.querySelectorAll('form[data-live-search]').forEach(function (form) {
            const search = debounce(function () {
                runSearch(form);
            }, DEBOUNCE_MS);

            form.querySelectorAll('input, select').forEach(function (field) {
                field.addEventListener('input', search);
                field.addEventListener('change', search);
            });

            form.addEventListener('submit', function (event) {
                event.preventDefault();
                runSearch(form);
            });
        });
    });
})();
