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

<script lang="ts" setup>
import { shallowRef, computed, PropType, watch } from 'vue'
import { Popup, Picker, PickerConfirmEventParams, 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'
        })
    },
    readonly: {
        type: Boolean,
        default: false
    },
    placeholder: {
        type: String,
        default: '请选择'
    },
})

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

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

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

const onClick = () => {
    if (!props.readonly) {
        show.value = true
    }
}

const onCancel = () => {
    show.value = false
}

const onConfirm = ({ selectedIndexes: [index], selectedValues: [value] }: PickerConfirmEventParams) => {
    show.value = false
    if (selectedIndex.value !== index) {
        // 更新当前选中的值
        selectedIndex.value = index
        fieldRef.value?.validate()

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

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>