<script setup>
import { filterInputClass } from '@/Components/Supervisor/ui.js';
import { onMounted, onUnmounted, ref, watch } from 'vue';

const props = defineProps({
    address: {
        type: String,
        default: '',
    },
    city: {
        type: String,
        default: '',
    },
    zipCode: {
        type: String,
        default: '',
    },
    required: {
        type: Boolean,
        default: false,
    },
});

const emit = defineEmits(['update:address', 'update:city', 'update:zipCode']);

const root = ref(null);
const query = ref(props.address ?? '');
const suggestions = ref([]);
const isOpen = ref(false);
const isLoading = ref(false);
const activeIndex = ref(-1);

let debounceTimer = null;

watch(
    () => props.address,
    (value) => {
        if (value !== query.value) {
            query.value = value ?? '';
        }
    },
);

const closeSuggestions = () => {
    isOpen.value = false;
    activeIndex.value = -1;
};

const searchAddresses = async () => {
    if (query.value.trim().length < 3) {
        suggestions.value = [];
        closeSuggestions();
        return;
    }

    isLoading.value = true;

    try {
        const response = await window.axios.get(route('supervisor.organizations.addresses.search'), {
            params: { q: query.value.trim() },
        });

        suggestions.value = response.data ?? [];
        isOpen.value = suggestions.value.length > 0;
        activeIndex.value = -1;
    } catch {
        suggestions.value = [];
        closeSuggestions();
    } finally {
        isLoading.value = false;
    }
};

const onInput = () => {
    emit('update:address', query.value);
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(searchAddresses, 300);
};

const selectSuggestion = (suggestion) => {
    query.value = suggestion.address;
    emit('update:address', suggestion.address);
    emit('update:city', suggestion.city ?? '');
    emit('update:zipCode', suggestion.zip_code ?? '');
    closeSuggestions();
};

const onKeydown = (event) => {
    if (!isOpen.value || suggestions.value.length === 0) {
        return;
    }

    if (event.key === 'ArrowDown') {
        event.preventDefault();
        activeIndex.value = (activeIndex.value + 1) % suggestions.value.length;
    } else if (event.key === 'ArrowUp') {
        event.preventDefault();
        activeIndex.value = activeIndex.value <= 0
            ? suggestions.value.length - 1
            : activeIndex.value - 1;
    } else if (event.key === 'Enter' && activeIndex.value >= 0) {
        event.preventDefault();
        selectSuggestion(suggestions.value[activeIndex.value]);
    } else if (event.key === 'Escape') {
        closeSuggestions();
    }
};

const onClickOutside = (event) => {
    if (root.value && !root.value.contains(event.target)) {
        closeSuggestions();
    }
};

onMounted(() => document.addEventListener('click', onClickOutside));
onUnmounted(() => {
    document.removeEventListener('click', onClickOutside);
    clearTimeout(debounceTimer);
});
</script>

<template>
    <div ref="root" class="relative">
        <input
            v-model="query"
            type="text"
            autocomplete="off"
            placeholder="Rechercher une adresse…"
            :required="required"
            :class="filterInputClass"
            @input="onInput"
            @focus="searchAddresses"
            @keydown="onKeydown"
        />

        <p v-if="isLoading" class="mt-1 text-xs text-slate-400">
            Recherche en cours…
        </p>

        <ul
            v-if="isOpen && suggestions.length > 0"
            class="absolute z-20 mt-1 max-h-56 w-full overflow-y-auto rounded-xl border border-slate-200 bg-white py-1 shadow-lg"
        >
            <li
                v-for="(suggestion, index) in suggestions"
                :key="`${suggestion.label}-${index}`"
            >
                <button
                    type="button"
                    class="block w-full px-3 py-2 text-left text-sm transition hover:bg-indigo-50"
                    :class="index === activeIndex ? 'bg-indigo-50 text-indigo-700' : 'text-slate-700'"
                    @mousedown.prevent="selectSuggestion(suggestion)"
                >
                    <span class="block font-medium">{{ suggestion.address }}</span>
                    <span class="block text-xs text-slate-400">
                        {{ [suggestion.zip_code, suggestion.city].filter(Boolean).join(' ') }}
                    </span>
                </button>
            </li>
        </ul>
    </div>
</template>
