document.addEventListener('DOMContentLoaded', () => {
    const normalize = value => {
        const ascii = value
            .normalize('NFD')
            .replace(/[\u0300-\u036f]/g, '');

        return ascii
            .toLocaleUpperCase('fr-FR')
            .replace(/[^A-Z0-9]/g, '');
    };

    const nameInput = document.querySelector('input[name="nom"]');
    const firstNameInput = document.querySelector('input[name="prenom"]');
    const preview = document.getElementById('adherentCodePreview');

    const updateCode = () => {
        if (!nameInput || !firstNameInput || !preview) return;

        const lastName = normalize(nameInput.value).slice(0, 11);
        const firstName = normalize(firstNameInput.value);

        preview.textContent = (
            'C' +
            lastName +
            firstName.slice(0, Math.max(1, 12 - lastName.length))
        ).slice(0, 13) || 'C…';
    };

    nameInput?.addEventListener('input', updateCode);
    firstNameInput?.addEventListener('input', updateCode);
    updateCode();

    const address = document.querySelector('[data-address-autocomplete]');
    const postcode = document.querySelector('[data-postcode]');
    const city = document.querySelector('[data-city]');
    const suggestions = document.getElementById('addressSuggestions');

    if (!address || !suggestions) return;

    let timer;
    let controller;

    const hideSuggestions = () => {
        suggestions.innerHTML = '';
        suggestions.hidden = true;
    };

    address.addEventListener('input', () => {
        clearTimeout(timer);

        const query = address.value.trim();

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

        timer = setTimeout(async () => {
            if (controller) controller.abort();

            controller = new AbortController();

            const url = new URL(
                'https://data.geopf.fr/geocodage/completion/'
            );

            url.searchParams.set(
                'text',
                [
                    query,
                    postcode?.value,
                    city?.value
                ].filter(Boolean).join(' ')
            );

            url.searchParams.set('type', 'StreetAddress');
            url.searchParams.set('maximumResponses', '6');

            try {
                const response = await fetch(url, {
                    signal: controller.signal
                });

                const data = await response.json();
                const rows = data.results || [];

                suggestions.innerHTML = '';

                rows.forEach(row => {
                    const fullText =
                        row.fulltext ||
                        row.label ||
                        row.name ||
                        '';

                    const zipCode =
                        row.zipcode ||
                        row.postcode ||
                        '';

                    const town =
                        row.city ||
                        row.cityname ||
                        row.locality ||
                        '';

                    if (!fullText) return;

                    const button = document.createElement('button');
                    button.type = 'button';
                    button.className = 'address-suggestion';
                    button.textContent = fullText;

                    button.addEventListener('click', () => {
                        let addressLine = fullText;

                        if (zipCode && fullText.includes(zipCode)) {
                            addressLine = fullText
                                .split(zipCode)[0]
                                .replace(/,\s*$/, '')
                                .trim();
                        }

                        address.value = addressLine;

                        if (postcode && zipCode) {
                            postcode.value = zipCode;
                        }

                        if (city && town) {
                            city.value =
                                town.toLocaleUpperCase('fr-FR');
                        }

                        hideSuggestions();
                    });

                    suggestions.appendChild(button);
                });

                suggestions.hidden = !suggestions.children.length;
            } catch (error) {
                if (error.name !== 'AbortError') {
                    hideSuggestions();
                }
            }
        }, 350);
    });

    document.addEventListener('click', event => {
        if (
            !suggestions.contains(event.target) &&
            event.target !== address
        ) {
            hideSuggestions();
        }
    });
});
