<template>
    <select
        ref="selectElement"
        class="form-control"
        :disabled="props.options.length === 0 && props.disableOnFetch"
    >
        <option disabled></option>
    </select>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';

interface Option {
    id: string | number;
    text: string;
}

interface Props {
    options: Option[];
    modelValue?: string | number | null;
    disableOnFetch?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
    modelValue: null,
    disableOnFetch: false
});

const emit = defineEmits(['update:modelValue', 'change']);

const selectElement = ref<HTMLSelectElement | null>(null);
let isMounting = false;

onMounted(async () => {
    if (!selectElement.value) return;

    isMounting = true;
    window.$(selectElement.value).select2({
        data: props.options,
        minimumResultsForSearch: 6,
        theme: 'bootstrap',
        containerCssClass: 'form-control',
    })
    .on('change', function (this: any) {
        if (isMounting) return;
        emit('update:modelValue', this.value);
        emit('change', this.value);
    })
    .on('select2:open', () => {
        window.$('.select2-results__options').scrollbar().addClass('scrollbar-macosx');
    });

    // Apply value after next tick to ensure select2 is fully initialized
    await nextTick();
    if (props.modelValue !== null && props.modelValue !== undefined) {
        window.$(selectElement.value).val(props.modelValue).trigger('change');
    }

    isMounting = false;
});

watch(() => props.modelValue, (newValue) => {
    if (selectElement.value && newValue !== null && newValue !== undefined) {
        window.$(selectElement.value).val(newValue).trigger('change');
    }
});

watch(() => props.options, (newOptions) => {
    if (selectElement.value) {
        isMounting = true;
        window.$(selectElement.value).off('change').empty().append('<option disabled selected></option>').select2({
            data: newOptions,
            minimumResultsForSearch: 6,
            theme: 'bootstrap',
            containerCssClass: 'form-control'
        }).on('change', function (this: any) {
            if (isMounting) return;
            emit('update:modelValue', this.value);
            emit('change', this.value);
        });

        if (props.modelValue !== null && props.modelValue !== undefined) {
            window.$(selectElement.value).val(props.modelValue).trigger('change');
        }
        isMounting = false;
    }
}, { deep: true });

onUnmounted(() => {
    if (selectElement.value) {
        window.$(selectElement.value).off().select2('destroy');
    }
});
</script>

<style>
.select2-results__options {
    position: relative;
    max-height: 200px;
}
</style>

