(function () {
    'use strict';

    function resolveParentValue(el) {
        var parentName = el.getAttribute('data-lookup-parent');
        if (!parentName) {
            return null;
        }

        var parentEl = document.querySelector('[name="' + parentName + '"]');
        if (!parentEl) {
            return null;
        }

        var parentValue = '';
        if (parentEl._erpChoices && typeof parentEl._erpChoices.getValue === 'function') {
            parentValue = parentEl._erpChoices.getValue(true) || '';
        }
        if (!parentValue) {
            parentValue = parentEl.value || '';
        }

        return parentValue || null;
    }

    function appendParentParam(el, params) {
        var parentValue = resolveParentValue(el);
        if (parentValue) {
            params.set('parent', parentValue);
        }
    }

    if (window.erpSearchSelect) {
        window.erpSearchSelect.resolveParentValue = resolveParentValue;
        window.erpSearchSelect.appendParentParam = appendParentParam;
    }

    function refreshSelect(el) {
        if (!el._erpChoices || typeof window.erpSearchSelect === 'undefined') {
            return;
        }

        var instance = el._erpChoices;
        var selectedValue = instance.getValue(true) || '';
        var type = el.getAttribute('data-lookup-type');
        var url = el.getAttribute('data-lookup-url');

        if (!type || !url) {
            return;
        }

        var params = new URLSearchParams({
            type: type,
            q: '',
            limit: '30',
        });

        if (selectedValue) {
            params.set('selected', selectedValue);
        }

        if (window.erpSearchSelect.appendParentParam) {
            window.erpSearchSelect.appendParentParam(el, params);
        }

        fetch(url + '?' + params.toString(), {
            headers: {
                Accept: 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
            },
            credentials: 'same-origin',
        })
            .then(function (res) {
                return res.ok ? res.json() : null;
            })
            .then(function (data) {
                if (!data || !Array.isArray(data.results)) {
                    return;
                }

                instance.setChoices(data.results, 'value', 'label', true);

                if (selectedValue && data.results.some(function (row) {
                    return row.value === selectedValue;
                })) {
                    instance.setChoiceByValue(selectedValue);
                } else {
                    instance.removeActiveItems();
                }
            })
            .catch(function () {
                // ignore lookup errors during cascade refresh
            });
    }

    function clearDescendants(parentName, root) {
        root.querySelectorAll('[data-lookup-parent="' + parentName + '"]').forEach(function (child) {
            if (child._erpChoices) {
                child._erpChoices.removeActiveItems();
                child._erpChoices.clearChoices();
            } else {
                child.value = '';
            }

            clearDescendants(child.getAttribute('name'), root);
            refreshSelect(child);
        });
    }

    function bindCascade(root) {
        root.querySelectorAll('[data-lookup-type][name]').forEach(function (el) {
            if (el.dataset.geoCascadeBound === '1') {
                return;
            }

            el.dataset.geoCascadeBound = '1';
            el.addEventListener('change', function () {
                var name = el.getAttribute('name');
                if (!name) {
                    return;
                }

                clearDescendants(name, root);
            });
        });

        // Plain selects (e.g. department_id) that parent lookup fields.
        var parentNames = {};
        root.querySelectorAll('[data-lookup-parent]').forEach(function (child) {
            var parentName = child.getAttribute('data-lookup-parent');
            if (parentName) {
                parentNames[parentName] = true;
            }
        });

        Object.keys(parentNames).forEach(function (parentName) {
            var parentEl = root.querySelector('[name="' + parentName + '"]');
            if (!parentEl || parentEl.dataset.geoCascadeBound === '1') {
                return;
            }

            parentEl.dataset.geoCascadeBound = '1';
            parentEl.addEventListener('change', function () {
                clearDescendants(parentName, root);
            });
        });
    }

    function boot() {
        document.querySelectorAll('[data-geo-cascade]').forEach(bindCascade);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', boot);
    } else {
        boot();
    }

    window.erpGeoCascade = {
        refresh: refreshSelect,
        bind: bindCascade,
    };
})();
