<template>
    <div class="app-select" @click="show = true">
        <slot :value="inputValue">
            <input class="app-select__input" v-model="inputValue" :placeholder="placeholder" readonly />
        </slot>
        <Popup v-model:show="show" position="bottom" teleport="body">
            <Picker :columns="columns" @cancel="onCancel" @confirm="onConfirm" />
        </Popup>
    </div>
</template>

<script lang="ts" setup>
import { shallowRef, computed, PropType, watch } from 'vue'
import { Popup, Picker, PickerOption, FieldInstance } from 'vant'

const props = defineProps({
    modelValue: {
        type: [Number, String]
    },
    options: {
        type: Array,
        default: () => ([])
    },
    optionProps: {
        type: Object as PropType<{ label?: string; value?: string; }>,
        default: () => ({
            label: 'label',
            value: 'value'
        })
    },
    placeholder: {
        type: String,
        default: '请选择'
    },
})

const emit = defineEmits(['update:show', 'update:modelValue', 'confirm', 'cancel'])
const fieldRef = shallowRef<FieldInstance>()
const show = shallowRef(false) // 是否弹出选择器
const selectedIndex = shallowRef(-1)

const columns = computed(() => {
    if (props.options) {
        return props.options.map((e) => e[props.optionProps.label])
    }
    return []
})

// 当前输入框的值
const inputValue = computed(() => {
    const item = props.options[selectedIndex.value]
    if (item) {
        return item[props.optionProps.label] ?? ''
    }
    return ''
})

const onCancel = (currentValue: PickerOption, currentIndex: number) => {
    show.value = false
    emit('cancel', props.modelValue, currentIndex)
}

const onConfirm = (currentValue: PickerOption, currentIndex: number) => {
    show.value = false
    if (selectedIndex.value !== currentIndex) {
        // 更新当前选中的值
        const item = props.options[currentIndex]
        if (item) {
            const value = item[props.optionProps.value]
            selectedIndex.value = currentIndex
            fieldRef.value?.validate()

            emit('update:modelValue', value)
            emit('confirm', value, currentIndex)
        }
    }
}

watch(() => [props.modelValue, props.options], ([value, items]) => {
    selectedIndex.value = items.findIndex((e) => e[props.optionProps.value]?.toString() === value?.toString())
}, {
    immediate: true
})
</script>

<style lang="less" scoped>
@import './index.less';
</style>