document.addEventListener('DOMContentLoaded', function () {
    const sidebarToggle = document.querySelector('.sidebar-toggle');
    const sidebarOverlay = document.querySelector('.sidebar-overlay');
    const sidebarClose = document.querySelector('.sidebar-close');
    const modeToggles = document.querySelectorAll('.mode-toggle');
    const geolocateButtons = document.querySelectorAll('[data-geolocate-btn]');
    const body = document.body;

    const collapseKey = 'hk_nav_collapsed';
    const themeKey = 'hk_theme';

    const syncThemeToggleLabels = function (dark) {
        modeToggles.forEach(function (toggle) {
            const icon = toggle.querySelector('.theme-icon');
            const label = toggle.querySelector('.theme-label');
            const text = dark ? 'Light Mode' : 'Dark Mode';

            if (icon) {
                icon.textContent = dark ? '☀️' : '🌙';
            }

            if (label) {
                label.textContent = dark ? 'Light' : 'Dark';
            } else {
                toggle.textContent = text;
            }

            toggle.setAttribute('aria-label', dark ? 'Switch to light mode' : 'Switch to dark mode');
        });
    };

    const setCollapsed = function (collapsed) {
        body.classList.toggle('nav-collapsed', collapsed);
        localStorage.setItem(collapseKey, collapsed ? '1' : '0');
    };

    const setTheme = function (theme) {
        const dark = theme === 'dark';
        body.classList.toggle('theme-dark', dark);
        syncThemeToggleLabels(dark);
        localStorage.setItem(themeKey, dark ? 'dark' : 'light');
    };

    const savedTheme = localStorage.getItem(themeKey) || 'light';
    setTheme(savedTheme);

    if (window.innerWidth > 1024) {
        setCollapsed(localStorage.getItem(collapseKey) === '1');
    }

    if (modeToggles.length) {
        modeToggles.forEach(function (toggle) {
            toggle.addEventListener('click', function () {
                setTheme(body.classList.contains('theme-dark') ? 'light' : 'dark');
            });
        });
    }

    if (sidebarToggle) {
        sidebarToggle.addEventListener('click', function () {
            if (window.innerWidth <= 1024) {
                body.classList.toggle('sidebar-open');
                return;
            }
            setCollapsed(!body.classList.contains('nav-collapsed'));
        });
    }

    if (sidebarOverlay) {
        sidebarOverlay.addEventListener('click', function () {
            body.classList.remove('sidebar-open');
        });
    }

    if (sidebarClose) {
        sidebarClose.addEventListener('click', function () {
            body.classList.remove('sidebar-open');
        });
    }

    document.addEventListener('keydown', function (event) {
        if (event.key === 'Escape') {
            body.classList.remove('sidebar-open');
        }
    });

    const revealElements = document.querySelectorAll('.reveal');
    if (revealElements.length) {
        if ('IntersectionObserver' in window) {
            const observer = new IntersectionObserver(
                function (entries) {
                    entries.forEach(function (entry) {
                        if (entry.isIntersecting) {
                            entry.target.classList.add('is-visible');
                            observer.unobserve(entry.target);
                        }
                    });
                },
                {
                    threshold: 0.12,
                    rootMargin: '0px 0px -40px 0px',
                }
            );

            revealElements.forEach(function (element) {
                observer.observe(element);
            });
        } else {
            revealElements.forEach(function (element) {
                element.classList.add('is-visible');
            });
        }
    }

    const findLocationField = function (container, names) {
        for (let index = 0; index < names.length; index += 1) {
            const field = container.querySelector('[name="' + names[index] + '"]');
            if (field) {
                return field;
            }
        }
        return null;
    };

    const setStatus = function (container, type, message) {
        const statusNode = container.querySelector('[data-location-status]');
        if (!statusNode) {
            return;
        }
        statusNode.textContent = message;
        statusNode.classList.remove('is-success', 'is-error');
        if (type === 'success') {
            statusNode.classList.add('is-success');
        }
        if (type === 'error') {
            statusNode.classList.add('is-error');
        }
    };

    const setFieldValue = function (field, value, overwriteWhenFilled) {
        if (!field) {
            return;
        }
        if (!overwriteWhenFilled && field.value) {
            return;
        }
        field.value = value || '';
    };

    const buildAddressText = function (address) {
        const roadLine = [address.house_number, address.road].filter(Boolean).join(' ').trim();
        const areaLine = [
            address.suburb,
            address.neighbourhood,
            address.city || address.town || address.village || address.municipality,
            address.state,
            address.postcode,
            address.country,
        ]
            .filter(Boolean)
            .filter(function (value, index, values) {
                return values.indexOf(value) === index;
            })
            .join(', ')
            .trim();

        return [roadLine, areaLine].filter(Boolean).join('\n').trim();
    };

    const buildLocationLabel = function (address) {
        return [
            address.suburb || address.neighbourhood || address.hamlet,
            address.city || address.town || address.village || address.municipality,
            address.state,
        ]
            .filter(Boolean)
            .filter(function (value, index, values) {
                return values.indexOf(value) === index;
            })
            .join(', ')
            .trim();
    };

    const reverseGeocode = async function (latitude, longitude) {
        const url = 'https://nominatim.openstreetmap.org/reverse?format=jsonv2&addressdetails=1&lat=' + encodeURIComponent(latitude) + '&lon=' + encodeURIComponent(longitude);
        const response = await fetch(url, {
            headers: {
                Accept: 'application/json',
            },
        });

        if (!response.ok) {
            throw new Error('Reverse geocoding is temporarily unavailable.');
        }

        return response.json();
    };

    if (geolocateButtons.length) {
        geolocateButtons.forEach(function (button) {
            button.addEventListener('click', function () {
                const container = button.closest('[data-location-form]') || button.closest('form') || document;
                const latitudeField = findLocationField(container, ['latitude']);
                const longitudeField = findLocationField(container, ['longitude']);
                const accuracyField = findLocationField(container, ['location_accuracy_m']);
                const labelField = findLocationField(container, ['location_label']);
                const addressField = findLocationField(container, ['default_address', 'address']);

                if (!navigator.geolocation) {
                    setStatus(container, 'error', 'Your browser does not support GPS access. You can still enter your address manually.');
                    return;
                }

                button.disabled = true;
                setStatus(container, '', 'Requesting GPS access from your device…');

                navigator.geolocation.getCurrentPosition(
                    async function (position) {
                        const latitude = Number(position.coords.latitude).toFixed(6);
                        const longitude = Number(position.coords.longitude).toFixed(6);
                        const accuracy = Number(position.coords.accuracy || 0).toFixed(2);

                        if (latitudeField) {
                            latitudeField.value = latitude;
                        }
                        if (longitudeField) {
                            longitudeField.value = longitude;
                        }
                        if (accuracyField) {
                            accuracyField.value = accuracy;
                        }

                        try {
                            const payload = await reverseGeocode(latitude, longitude);
                            const address = payload.address || {};
                            const suggestedAddress = buildAddressText(address);
                            const locationLabel = buildLocationLabel(address);

                            setFieldValue(labelField, locationLabel, false);
                            setFieldValue(addressField, suggestedAddress || payload.display_name || '', false);
                            setStatus(
                                container,
                                'success',
                                'GPS captured successfully. Accuracy ±' + Math.round(Number(accuracy)) + ' meters. Please review the address before saving.'
                            );
                        } catch (error) {
                            setStatus(
                                container,
                                'success',
                                'GPS captured successfully. Exact coordinates were saved, but the address suggestion could not be loaded right now.'
                            );
                        } finally {
                            button.disabled = false;
                        }
                    },
                    function (error) {
                        let message = 'Unable to get your location. Please enter your address manually.';

                        if (error.code === error.PERMISSION_DENIED) {
                            message = 'Location permission was denied. You can still continue with a manual address.';
                        } else if (error.code === error.TIMEOUT) {
                            message = 'Location request timed out. Please retry or continue manually.';
                        }

                        setStatus(container, 'error', message);
                        button.disabled = false;
                    },
                    {
                        enableHighAccuracy: true,
                        timeout: 15000,
                        maximumAge: 0,
                    }
                );
            });
        });
    }
});
