(function () {
    'use strict';

    var gate = document.getElementById('locationGate');
    if (!gate) {
        return;
    }

    var token = gate.getAttribute('data-token');
    var linkLocationUrl = gate.getAttribute('data-link-location-url') || (window.karviPath ? window.karviPath('/api/link-location') : '/api/link-location');
    if (!token) {
        return;
    }

    var i18n = window.KARVI_I18N || {};
    var messageEl = document.getElementById('locationGateMessage');
    var spinnerEl = document.getElementById('locationGateSpinner');
    var retryBtn = document.getElementById('locationGateRetry');

    function deviceMeta() {
        var timezone = '';
        try {
            timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || '';
        } catch (e) {
            timezone = '';
        }

        return {
            timezone: timezone,
            user_agent: navigator.userAgent || '',
            screen_resolution:
                (window.screen && window.screen.width ? window.screen.width : 0) +
                'x' +
                (window.screen && window.screen.height ? window.screen.height : 0),
        };
    }

    function setLoading(message) {
        if (messageEl) {
            messageEl.textContent = message || i18n.reg_location_loading || 'Detecting your location…';
        }
        if (spinnerEl) {
            spinnerEl.classList.remove('hidden');
        }
        if (retryBtn) {
            retryBtn.classList.add('hidden');
        }
    }

    function showError(message) {
        if (messageEl) {
            messageEl.textContent = message;
        }
        if (spinnerEl) {
            spinnerEl.classList.add('hidden');
        }
        if (retryBtn) {
            retryBtn.classList.remove('hidden');
        }
    }

    function unlockContent() {
        document.body.classList.remove('reg-location-pending');
        document.body.classList.add('reg-location-ready');

        document.querySelectorAll('.reg-gated').forEach(function (el) {
            el.classList.remove('hidden');
        });

        gate.classList.add('hidden');
        gate.setAttribute('aria-hidden', 'true');

        document.dispatchEvent(new CustomEvent('karvi:location-ready'));
    }

    function postLocation(payload) {
        var formData = new FormData();
        formData.set('token', token);

        Object.keys(payload).forEach(function (key) {
            if (payload[key] !== null && payload[key] !== undefined) {
                formData.set(key, String(payload[key]));
            }
        });

        return fetch(linkLocationUrl, {
            method: 'POST',
            body: formData,
            credentials: 'same-origin',
        }).then(function (response) {
            return response.json().catch(function () {
                return { success: false };
            });
        });
    }

    function saveAndUnlock(payload) {
        return postLocation(payload).then(function (result) {
            if (!result || !result.success) {
                throw new Error('save_failed');
            }
            unlockContent();
        });
    }

    function errorMessageForStatus(status) {
        if (status === 'denied') {
            return i18n.reg_location_denied || 'Location access is required to continue. Please allow location and try again.';
        }
        if (status === 'timeout') {
            return i18n.reg_location_timeout || 'Location detection timed out. Please try again.';
        }
        if (status === 'insecure_context') {
            return i18n.reg_location_insecure || 'Location is only available on a secure connection (HTTPS).';
        }
        if (status === 'unavailable') {
            return i18n.reg_location_unavailable || 'Location is not available on this device.';
        }
        return i18n.reg_location_error || 'Could not detect your location. Please try again.';
    }

    function requestLocation() {
        setLoading(i18n.reg_location_loading || 'Detecting your location…');

        if (!window.isSecureContext) {
            showError(errorMessageForStatus('insecure_context'));
            postLocation(Object.assign({ geo_status: 'insecure_context' }, deviceMeta())).catch(function () {});
            return;
        }

        if (!navigator.geolocation) {
            showError(errorMessageForStatus('unavailable'));
            postLocation(Object.assign({ geo_status: 'unavailable' }, deviceMeta())).catch(function () {});
            return;
        }

        navigator.geolocation.getCurrentPosition(
            function (position) {
                var lat = position.coords.latitude;
                var lng = position.coords.longitude;
                var accuracy = position.coords.accuracy;
                var payload = Object.assign(
                    {
                        latitude: lat,
                        longitude: lng,
                        accuracy_meters: accuracy,
                        geo_status: 'granted',
                    },
                    deviceMeta()
                );

                setLoading(i18n.reg_location_saving || 'Saving location…');

                fetch(
                    'https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=' +
                        encodeURIComponent(lat) +
                        '&lon=' +
                        encodeURIComponent(lng),
                    {
                        headers: {
                            Accept: 'application/json',
                            'Accept-Language': document.documentElement.lang || 'en',
                        },
                    }
                )
                    .then(function (response) {
                        return response.ok ? response.json() : null;
                    })
                    .then(function (data) {
                        if (data && data.display_name) {
                            payload.full_address = data.display_name;
                        }
                        return saveAndUnlock(payload);
                    })
                    .catch(function () {
                        return saveAndUnlock(payload);
                    })
                    .catch(function () {
                        showError(i18n.reg_location_error || 'Could not save your location. Please try again.');
                    });
            },
            function (error) {
                var status = 'error';
                if (error && error.code === 1) {
                    status = 'denied';
                } else if (error && error.code === 3) {
                    status = 'timeout';
                }

                showError(errorMessageForStatus(status));
                postLocation(Object.assign({ geo_status: status }, deviceMeta())).catch(function () {});
            },
            {
                enableHighAccuracy: true,
                timeout: 20000,
                maximumAge: 0,
            }
        );
    }

    if (retryBtn) {
        retryBtn.addEventListener('click', requestLocation);
    }

    requestLocation();
})();
