<template>
    <div class="relative">
        <label
            :for="id"
            class="block mb-2 text-sm"
            :class="userInputValid ? 'font-medium text-gray-900' : 'font-bold text-red'">{{ label }}</label>
        <input
            type="text"
            :id="id"
            class="border border-gray-500 text-gray-900 text-sm rounded-lg block w-full p-2.5"
            :class="[
                  userInputValid
                    ? 'bg-slate-50 focus:ring-blue focus:border-blue'
                    : 'border-red bg-rose-50 ring-1 ring-red ring-inset focus:ring-red focus:border-red focus:ring-inset',
                  dropdownShown ? 'rounded-b-none border-b-0 mb-px' : 'rounded-lg'
                ]"
            :value="value"
            @keydown="handleKeydown"
            @input="onInput"
            :maxlength="maxLength"
            :ref="id"
            :placeholder="placeholder"
            :required="required">

        <div
            v-if="dropdownShown"
            :style="{ width: $refs[id].offsetWidth + 2 + 'px' }"
            class="absolute -ml-px w-full max-h-[150px] overflow-y-auto border-2 border-blue border-t border-t-slate-200 text-gray-900 text-sm rounded-lg z-50"
            :class="{'rounded-t-none': dropdownShown}">
            <div
                v-if="filteredOptions.length === 0"
                class="p-2 text-xs text-grey italic bg-white">
                {{ noResultsText }}
            </div>
            <div
                v-for="(option, index) in filteredOptions"
                :key="option"
                @click="selectOption(option)"
                class="p-2 cursor-pointer"
                @mouseenter="highlightOption(index)"
                :class="{ 'even:bg-[#e1ebff] odd:bg-[#e1ebff]': this.highlightedIndex === index,
                 'even:bg-slate-50 odd:bg-white': this.highlightedIndex !== index}">
                {{ option }}
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: 'AutoCompleteDropdown',
    emits: ['update:value'],
    props: {
        id: {
            type: String,
            default: '',
            required: true
        },
        label: {
            type: String,
            default: ''
        },
        noResultsText: {
            type: String,
            default: 'No results found'
        },
        value: {
            type: String,
            default: ''
        },
        maxLength: {
            type: Number,
            default: null
        },
        placeholder: {
            type: String,
            default: ''
        },
        options: {
            type: Array,
            default: () => []
        },
        required: {
            type: Boolean,
            default: false
        },
        userInputValid: {
            type: Boolean,
            default: true
        }
    },
    data() {
        return {
            searchTerm: '',
            dropdownShown: false,
            highlightedIndex: -1,
        };
    },
    computed: {
        filteredOptions() {
            const lowerCaseSearchTerm = this.searchTerm.toLowerCase();
            return this.options.filter((option) =>
                option.toLowerCase().includes(lowerCaseSearchTerm)
            );
        },
    },
    methods: {
        onInput(event) {
            this.searchTerm = event.target.value;
            if (!this.dropdownShown) this.showDropdown();
            this.highlightOption(-1);
            this.$emit('update:value', this.searchTerm);
        },
        selectOption(option) {
            this.searchTerm = option;
            this.dropdownShown = false;
            this.$emit('update:value', this.searchTerm);
        },
        showDropdown() {
            this.dropdownShown = true;
            document.addEventListener('click', this.handleOutsideClick);
        },
        hideDropdown() {
            this.dropdownShown = false;
            this.highlightOption(-1);
            document.removeEventListener('click', this.handleOutsideClick);
        },
        handleOutsideClick(event) {
            if (!this.$refs[this.id].contains(event.target)) {
                this.hideDropdown();
            }
        },
        handleKeydown(event) {
            if (!this.dropdownShown) this.showDropdown();
            if (event.key === 'ArrowDown') {
                this.highlightOption((this.highlightedIndex + 1) % this.filteredOptions.length);
                return event.preventDefault();
            }
            if (event.key === 'ArrowUp') {
                this.highlightOption((this.highlightedIndex - 1 + this.filteredOptions.length) % this.filteredOptions.length);
                return event.preventDefault();
            }
            if (event.key === 'Enter' && this.highlightedIndex !== -1) {
                return this.selectOption(this.filteredOptions[this.highlightedIndex]);
            }
            if (event.key === 'Enter' || event.key === 'TAB') {
                this.hideDropdown();
            }
        },
        highlightOption(index) {
            this.highlightedIndex = index;
        },
    },
};
</script>
