(function () {
    var VERSION = 'p4_5';

    var COUNTRY_CODE_MAP = {
        chile: 'cl', argentina: 'ar', peru: 'pe', 'perú': 'pe', uruguay: 'uy', brasil: 'br', brazil: 'br',
        colombia: 'co', ecuador: 'ec', mexico: 'mx', 'méxico': 'mx', paraguay: 'py', bolivia: 'bo',
        'estados unidos': 'us', usa: 'us', eeuu: 'us', 'united states': 'us', espana: 'es', 'españa': 'es',
        otro: '', other: '', global: ''
    };

    function isLocationInput(target) {
        if (!target || target.nodeType !== 1) return null;
        if (target.matches && target.matches('[data-location-autocomplete="true"]')) return target;
        return null;
    }

    function closestForm(el) {
        return el ? el.closest('form') : null;
    }

    function byName(form, name) {
        return form ? form.querySelector('[name="' + name + '"]') : null;
    }

    function ensureWrap(input) {
        var wrap = input.closest('.location-autocomplete-wrap');
        if (!wrap) wrap = input.parentNode;
        if (wrap && window.getComputedStyle(wrap).position === 'static') {
            wrap.style.position = 'relative';
        }
        return wrap || input.parentNode;
    }

    function ensureMenu(input) {
        var wrap = ensureWrap(input);
        var existing = wrap.querySelector('.location-suggest-menu');
        if (existing) return existing;

        var menu = document.createElement('div');
        menu.className = 'location-suggest-menu';
        menu.setAttribute('data-location-menu', 'true');
        wrap.appendChild(menu);
        return menu;
    }

    function closeMenus(except) {
        document.querySelectorAll('.location-suggest-menu.is-open').forEach(function (menu) {
            if (menu !== except) menu.classList.remove('is-open');
        });
    }

    function setValue(form, name, value) {
        var field = byName(form, name);
        if (!field) return;
        var normalizedValue = value == null ? '' : String(value);
        if (field.tagName === 'SELECT' && normalizedValue !== '') {
            var found = Array.prototype.some.call(field.options, function (option) { return option.value === normalizedValue; });
            if (!found) {
                var option = document.createElement('option');
                option.value = normalizedValue;
                option.textContent = normalizedValue;
                option.dataset.countryCode = '';
                option.dataset.phonePrefix = '';
                field.appendChild(option);
            }
        }
        field.value = normalizedValue;
        field.dispatchEvent(new Event('input', { bubbles: true }));
        field.dispatchEvent(new Event('change', { bubbles: true }));
    }

    function normalizeCountryKey(value) {
        return String(value || '')
            .toLowerCase()
            .normalize('NFD')
            .replace(/[\u0300-\u036f]/g, '')
            .trim();
    }

    function getCountrySelect(form) {
        return form ? form.querySelector('[data-location-country="true"], [name="country"]') : null;
    }

    function getCountryCode(form) {
        var field = getCountrySelect(form);
        if (!field) return 'cl';

        if (field.tagName === 'SELECT') {
            var option = field.options[field.selectedIndex];
            if (option && typeof option.dataset.countryCode !== 'undefined') {
                return option.dataset.countryCode || '';
            }
        }

        var value = field.value || 'Chile';
        if (/^[a-z]{2}$/i.test(value)) return value.toLowerCase();
        return Object.prototype.hasOwnProperty.call(COUNTRY_CODE_MAP, normalizeCountryKey(value))
            ? COUNTRY_CODE_MAP[normalizeCountryKey(value)]
            : 'cl';
    }

    function setManualGeo(input, value) {
        var form = closestForm(input);
        if (!form) return;
        setValue(form, 'geocode_status', value.length > 0 ? 'manual' : 'pending');
        setValue(form, 'geocode_source', value.length > 0 ? 'manual' : '');
        setValue(form, 'geocode_query', value);
        if (value.length > 0) {
            setValue(form, 'latitude', '');
            setValue(form, 'longitude', '');
        }
    }

    function applyPlace(input, place) {
        var form = closestForm(input);
        if (!form || !place) return;

        setValue(form, 'address', place.address || place.formatted_address || '');
        setValue(form, 'district', place.district || '');
        setValue(form, 'city', place.city || '');
        setValue(form, 'region', place.region || '');
        setValue(form, 'country', place.country || 'Chile');
        setValue(form, 'latitude', place.latitude || '');
        setValue(form, 'longitude', place.longitude || '');
        setValue(form, 'geocode_status', place.geocode_status || 'ok');
        setValue(form, 'geocode_source', place.geocode_source || 'google_maps');
        setValue(form, 'geocode_query', place.geocode_query || place.formatted_address || '');

        input.value = place.formatted_address || place.address || input.value;
    }

    function renderMessage(input, text) {
        var menu = ensureMenu(input);
        menu.innerHTML = '';

        var item = document.createElement('div');
        item.className = 'location-suggest-item is-muted';
        item.textContent = text;
        menu.appendChild(item);
        menu.classList.add('is-open');
    }

    function escapeHtml(value) {
        return String(value == null ? '' : value)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }

    function normalizeRows(data) {
        if (!data) return [];
        if (Array.isArray(data.results)) return data.results;
        if (Array.isArray(data.suggestions)) return data.suggestions;
        if (data.data && Array.isArray(data.data.results)) return data.data.results;
        return [];
    }

    function renderMenu(input, rows, query) {
        var currentValue = input.value.trim();
        if (query && currentValue !== query) return;

        var menu = ensureMenu(input);
        menu.innerHTML = '';

        if (!rows || rows.length === 0) {
            renderMessage(input, 'Sin sugerencias de ubicación para el país seleccionado. Puedes guardar la dirección manualmente.');
            return;
        }

        rows.forEach(function (row) {
            var btn = document.createElement('button');
            btn.type = 'button';
            btn.className = 'location-suggest-item';
            btn.setAttribute('data-place-id', row.place_id || '');

            var main = row.main_text || row.description || '';
            var secondary = row.secondary_text || '';
            btn.innerHTML = '<strong>' + escapeHtml(main) + '</strong><span>' + escapeHtml(secondary) + '</span>';

            btn.addEventListener('click', function (event) {
                event.preventDefault();
                event.stopPropagation();

                if (!row.place_id) {
                    input.value = row.description || input.value;
                    setManualGeo(input, input.value.trim());
                    menu.classList.remove('is-open');
                    return;
                }

                menu.innerHTML = '<div class="location-suggest-item is-muted">Cargando ubicación...</div>';
                menu.classList.add('is-open');

                fetch('/api/geo/maps_place.php?place_id=' + encodeURIComponent(row.place_id) + '&_=' + Date.now(), {
                    credentials: 'same-origin',
                    cache: 'no-store',
                    headers: { 'Accept': 'application/json' }
                })
                    .then(function (r) { return r.json(); })
                    .then(function (data) {
                        if (data && data.success && data.place) {
                            applyPlace(input, data.place);
                        } else {
                            input.value = row.description || input.value;
                            setManualGeo(input, input.value.trim());
                        }
                        menu.classList.remove('is-open');
                    })
                    .catch(function () {
                        input.value = row.description || input.value;
                        setManualGeo(input, input.value.trim());
                        menu.classList.remove('is-open');
                    });
            });

            menu.appendChild(btn);
        });

        menu.classList.add('is-open');
    }

    function getState(input) {
        if (!input.__icyLocationState) {
            input.__icyLocationState = { timer: null, seq: 0, abort: null, lastQuery: '', lastCountry: '' };
        }
        return input.__icyLocationState;
    }

    function abortPrevious(state) {
        if (state.abort && typeof state.abort.abort === 'function') {
            try { state.abort.abort(); } catch (e) {}
        }
        state.abort = null;
    }

    function search(input) {
        var state = getState(input);
        var form = closestForm(input);
        var query = input.value.trim();
        var countryCode = getCountryCode(form);

        abortPrevious(state);

        if (query.length < 3) {
            closeMenus();
            return;
        }

        var seq = ++state.seq;
        state.lastQuery = query;
        state.lastCountry = countryCode;

        var menu = ensureMenu(input);
        menu.innerHTML = '<div class="location-suggest-item is-muted">Buscando en Maps...</div>';
        menu.classList.add('is-open');

        var options = {
            credentials: 'same-origin',
            cache: 'no-store',
            headers: { 'Accept': 'application/json' }
        };

        if (typeof AbortController !== 'undefined') {
            state.abort = new AbortController();
            options.signal = state.abort.signal;
        }

        var url = '/api/geo/maps_suggest.php?q=' + encodeURIComponent(query) + '&country=' + encodeURIComponent(countryCode) + '&_=' + Date.now();
        fetch(url, options)
            .then(function (r) {
                if (!r.ok) throw new Error('HTTP ' + r.status);
                return r.json();
            })
            .then(function (data) {
                if (seq !== state.seq) return;
                if (input.value.trim() !== query) return;
                if (getCountryCode(form) !== countryCode) return;

                if (!data || data.configured === false) {
                    renderMessage(input, 'Maps no configurado. Se guardará como dirección manual.');
                    return;
                }

                if (data.success === false) {
                    renderMessage(input, data.message || 'No fue posible consultar Maps.');
                    return;
                }

                renderMenu(input, normalizeRows(data), query);
            })
            .catch(function (error) {
                if (error && error.name === 'AbortError') return;
                if (seq !== state.seq) return;
                renderMessage(input, 'No fue posible consultar Maps.');
            });
    }

    function handleInput(input) {
        input.autocomplete = 'off';
        var state = getState(input);
        var value = input.value.trim();
        setManualGeo(input, value);

        if (state.timer) clearTimeout(state.timer);

        if (value.length < 3) {
            abortPrevious(state);
            closeMenus();
            return;
        }

        state.timer = setTimeout(function () { search(input); }, 220);
    }

    function updatePhonePrefixFromCountry(select) {
        if (!select || select.tagName !== 'SELECT') return;
        var form = closestForm(select);
        if (!form) return;
        var option = select.options[select.selectedIndex];
        var prefix = option ? (option.dataset.phonePrefix || '') : '';
        if (!prefix) return;
        var prefixSelect = form.querySelector('[data-phone-prefix-select="true"]');
        if (prefixSelect && prefixSelect.value !== prefix) {
            prefixSelect.value = prefix;
            prefixSelect.dispatchEvent(new Event('change', { bubbles: true }));
        }
    }

    function onInputCapture(event) {
        var input = isLocationInput(event.target);
        if (!input) return;
        event.stopImmediatePropagation();
        handleInput(input);
    }

    function onFocusCapture(event) {
        var input = isLocationInput(event.target);
        if (!input) return;
        input.autocomplete = 'off';
        ensureMenu(input);
    }

    function onCountryChange(event) {
        var select = event.target && event.target.closest ? event.target.closest('[data-location-country="true"]') : null;
        if (!select) return;
        updatePhonePrefixFromCountry(select);
        var form = closestForm(select);
        var input = form ? form.querySelector('[data-location-autocomplete="true"]') : null;
        if (input) {
            setValue(form, 'latitude', '');
            setValue(form, 'longitude', '');
            setValue(form, 'geocode_status', input.value.trim() ? 'manual' : 'pending');
            if (input.value.trim().length >= 3) handleInput(input);
        }
    }

    function init(container) {
        container = container || document;
        container.querySelectorAll('[data-location-autocomplete="true"]').forEach(function (input) {
            input.autocomplete = 'off';
            input.dataset.locationAutocompleteVersion = VERSION;
            ensureMenu(input);
        });
        container.querySelectorAll('[data-location-country="true"]').forEach(function (select) {
            updatePhonePrefixFromCountry(select);
        });
    }

    if (!window.__ICY_CUSTOMER_LOCATION_DELEGATED_P4_5) {
        window.__ICY_CUSTOMER_LOCATION_DELEGATED_P4_5 = true;
        document.addEventListener('input', onInputCapture, true);
        document.addEventListener('focus', onFocusCapture, true);
        document.addEventListener('change', onCountryChange, true);
        document.addEventListener('click', function (event) {
            if (!event.target.closest('.location-autocomplete-wrap')) closeMenus();
        });
        document.addEventListener('DOMContentLoaded', function () { init(document); });
        document.addEventListener('icy:spa-render', function (event) {
            init(event.detail && event.detail.main ? event.detail.main : document);
        });
    }

    window.ICY_CUSTOMER_LOCATION = { version: VERSION, init: init, applyPlace: applyPlace, search: search, countryCode: getCountryCode };
    init(document);
})();
