<template>
    <template v-if="mode === 'picker'">
        <picker :range="options" range-key="name" @change="selectChange" :disabled="false">
            <slot></slot>
        </picker>
    </template>
    <template v-else-if="mode === 'custom'">
        <view @click="showModel = true" class="flex1">
            <slot></slot>
        </view>
        <root-portal>
            <up-popup v-model:show="showModel" mode="center" round="30rpx" :safeAreaInsetBottom="false" closeable @close="showModel = false">
                <view class="w-700">
                    <view class="pd-24">
                        <view class="f-s-32 c-#333 f-w-500">{{ title }}</view>
                    </view>
                    <scroll-view scroll-y style="max-height: 70vh">
                        <view class="pd3-10-24-24">
                            <ut-row gap="16rpx">
                                <template v-for="(item, index) in options" :key="index">
                                    <ut-col :span="item.span">
                                        <view @click="clickCol(item)" class="ut-custom-item-sheet p-rtv" :class="{ active: checkeds[item.value] }"
                                            >{{ item?.remark || item?.name }}
                                            <image v-if="checkeds[item.value]" class="w-40 h-40 checked-icon" src="https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-lm/price/checked1.png" mode="widthFix" />
                                        </view>
                                    </ut-col>
                                </template>
                            </ut-row>
                        </view>
                    </scroll-view>
                    <view v-if="multiple" class="d-flex j-c pd-24">
                        <up-button class="mr-20" @click="onCancel">取消</up-button>
                        <up-button type="primary" @click="onConfirm">确定</up-button>
                    </view>
                </view>
            </up-popup>
        </root-portal>
    </template>
</template>
<script setup lang="ts">
import { ref, watch, computed } from 'vue';

const props = defineProps({
    modelValue: {
        // 支持数组或字符串：多选时根据现有类型返回对应格式
        type: [Array, String],
        default: () => [],
    },

    title: {
        type: String,
        default: '系统提示',
    },
    showTitle: {
        type: Boolean,
        default: true,
    },
    tabs: {
        type: Array,
        default: () => [],
    },
    mode: {
        type: String,
        default: 'picker', // 原生 picker 模式 或自定义弹窗模式 custom
    },
    // 是否多选
    multiple: {
        type: Boolean,
        default: false, // 只有自定义弹窗模式下生效
    },
    valueType: {
        type: String,
        default: 'string', // 数组 array 或 字符串 string，只有多选时生效
    },
});
const options = computed(() => {
    return props.tabs.map((item: any) => {
        // 如果 elTagClass正则表达式匹配的是数字，则作为span使用，否则默认10，如果是个对象字符，取span属性值
        let span = 10;
        //     Unexpected end of JSON input
        // at JSON.parse (<anonymous>)
        if (item.elTagClass) {
            const num = Number(item.elTagClass);
            if (!isNaN(num)) {
                span = num;
            } else {
                try {
                    const obj = JSON.parse(item.elTagClass);
                    if (obj && obj.span) {
                        span = obj.span;
                    }
                } catch (e) {
                    // do nothing
                }
            }
        }
        return {
            name: item.label,
            value: item.value,
            span,
            remark: item.remark,
        };
    });
});
const showModel = ref(false);
const emit = defineEmits(['close', 'confirm', 'open', 'update:show', 'update:modelValue', 'change']);
const checkeds = ref<any>({});
// 未选择之前的
const initialCheckeds = ref<any>({});

const close = () => {
    showModel.value = false;
    // 如果有初始值，恢复初始值
    checkeds.value = { ...initialCheckeds.value };
    emit('update:show', false);
    emit('close');
};

// 获取当前已选中的值列表
const getSelectedValues = () => {
    return Object.keys(checkeds.value).filter((key) => checkeds.value[key]);
};

const clickCol = (item: any) => {
    // 判断是单选还是多选
    if (props.multiple) {
        // 多选
        if (checkeds.value[item.value]) {
            // 取消选择
            delete checkeds.value[item.value];
        } else {
            // 选择
            checkeds.value[item.value] = true;
        }
    } else {
        // 单选
        checkeds.value = {
            [item.value]: true,
        };
        emit('update:modelValue', item.value);
        emit('change', item.value);
        close();
    }
};

// 多选确认
const onConfirm = () => {
    const values = getSelectedValues();
    let out: any;
    if (Array.isArray(props.modelValue) || props.valueType === 'array') {
        out = values;
    } else {
        // 字符串场景下，用逗号拼接
        out = values.join(',');
    }
    emit('update:modelValue', out);
    emit('change', out);
    // 确认后更新初始选中值
    initialCheckeds.value = { ...checkeds.value };
    close();
};

// 多选取消
const onCancel = () => {
    close();
};
const selectChange = (item: any) => {
    const selectedValues = options.value[item.detail.value].value;
    emit('update:modelValue', selectedValues);
    emit('change', selectedValues);
    close();
};
watch(
    () => props.modelValue,
    (newVal: any) => {
        // 初始化已选择项
        let selected: any = {};
        if (props.multiple) {
            if (Array.isArray(newVal)) {
                newVal.forEach((val: any) => {
                    selected[val] = true;
                });
            } else if (typeof newVal === 'string' && newVal) {
                newVal
                    .split(/[，,]/)
                    .map((val: string) => val.trim())
                    .filter((val: string) => !!val)
                    .forEach((val: string) => {
                        selected[val] = true;
                    });
            }
        } else if (newVal != null) {
            selected = {
                [newVal as string]: true,
            };
        }
        checkeds.value = selected;
        initialCheckeds.value = { ...selected };
    },
    { immediate: true },
);
</script>
<script lang="ts">
export default {
    options: {
        // 微信小程序中 options 选项
        multipleSlots: true, //  在组件定义时的选项中启动多slot支持，默认启用
        styleIsolation: 'shared', //  启动样式隔离。当使用页面自定义组件，希望父组件影响子组件样式时可能需要配置。具体配置选项参见：微信小程序自定义组件的样式
        addGlobalClass: true, //  表示页面样式将影响到自定义组件，但自定义组件中指定的样式不会影响页面。这个选项等价于设置 styleIsolation: apply-shared
        virtualHost: true, //  将自定义节点设置成虚拟的，更加接近Vue组件的表现。我们不希望自定义组件的这个节点本身可以设置样式、响应 flex 布局等，而是希望自定义组件内部的第一层节点能够响应 flex 布局或者样式由自定义组件本身完全决定
    },
};
</script>
<style lang="scss" scoped>
.ut-custom-item-sheet {
    padding: 18rpx 6rpx;
    border: 1rpx solid #f7f7f7;
    background-color: #f7f7f7;
    border-radius: 10rpx;
    text-align: center;
    font-size: 30rpx;
    color: #333;

    &.active {
        border-color: #37a954;
        background-color: #e6f4f0;
        color: #37a954;
    }
}
.checked-icon {
    position: absolute;
    right: 0;
    bottom: 0;
}
</style>
