<template>
    <view>
        <view class="cwg-dropdown" :style="customStyle" @click="click">
            <slot></slot>
        </view>
        <view class="cwg-dropdown-menu">
            <view class="cwg-dropdown-menu-container" :style="[layout]" @click.stop>

                <slot name="menu">
                    <view class="menu">
                        <slot name="btn"></slot>
                        <view class="menu-item" v-for="(item, idx) in menuList" :key="idx"
                            @click="menuClick(item, idx)">
                            <view>{{ item.label || item }}</view>
                        </view>
                    </view>
                </slot>
            </view>
        </view>
        <view class="cwg-dropdown-mask" :class="{ 'cwg-dropdown-mask-show': maskShow }" @click.stop="close" />
    </view>
</template>

<script setup>
import { ref, reactive, nextTick, onMounted } from 'vue'
import { queryElementRect } from '@/uni_modules/x-tools/tools/sugar.js'
import { str2px, commonProps } from '@/uni_modules/x-tools/tools/com.js'

// 合并 props
const props = defineProps({
    ...commonProps,
    menuList: {
        type: Object,
        default: () => ['菜单1', '菜单2', '菜单3']
    },
    menuStyle: {
        type: Object,
        default: () => ({})
    },
    interspace: {
        type: [String, Number],
        default: '10rpx'
    }
})

const emit = defineEmits(['open', 'close', 'change', 'menuClick'])

// 响应式数据
const maskShow = ref(false)
const windowInfo = reactive({
    width: 0,
    height: 0
})
const layout = reactive({})
const innerInterspace = ref(0)

// 获取系统信息
const getSystemInfo = () => {
    return new Promise((resolve) => {
        if (windowInfo.width > 0) {
            resolve(windowInfo)
        } else {
            uni.getSystemInfo({
                success: (res) => {
                    windowInfo.width = res.windowWidth
                    windowInfo.height = res.windowHeight
                    resolve(windowInfo)
                },
                fail: () => {
                    setTimeout(() => getSystemInfo().then(resolve), 100)
                }
            })
        }
    })
}

// 点击触发器
const click = async (e) => {
    e.stopPropagation()
    await getSystemInfo()
    const triggerRect = await queryElementRect('.cwg-dropdown')
    if (!triggerRect) return
    const tempStyle = {
        transform: 'scaleY(1)',
        visibility: 'hidden',
        top: '-9999px',
        left: '-9999px',
        transition: 'none'
    }
    Object.assign(layout, tempStyle)
    await nextTick()
    const menuRect = await queryElementRect('.cwg-dropdown-menu-container')
    if (!menuRect) {
        Object.keys(layout).forEach(key => delete layout[key])
        layout.transform = 'scaleY(0)'
        return
    }
    const { width: winWidth } = windowInfo
    const { left, right, bottom } = triggerRect
    const interspaceVal = innerInterspace.value
    const finalLayout = {
        transition: 'transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)',
        transform: 'scaleY(1)',
        top: `10px`
    }
    if (left + menuRect.width < winWidth) {
        finalLayout.left = `-110px`
    } else {
        const val = winWidth - right
        finalLayout.right = `${val > 0 ? val : 0}px`
    }
    Object.keys(layout).forEach(key => delete layout[key])
    Object.assign(layout, finalLayout)
    maskShow.value = true
    emit('open')
    emit('change', true)
}
const menuClick = (value, index) => {
    emit('menuClick', { value, index })
    close()
}
const close = () => {
    maskShow.value = false
    Object.keys(layout).forEach(key => delete layout[key])
    layout.transform = 'scaleY(0)'
    emit('close')
    emit('change', false)
}
onMounted(() => {
    getSystemInfo()
    innerInterspace.value = str2px(props.interspace)
})
// 暴露方法
defineExpose({
    close
})
</script>

<style lang="scss" scoped>
@import '@/uni.scss';

.cwg-dropdown {
    width: fit-content;
    position: relative;
    overflow: hidden;
}

.cwg-dropdown-menu {
    position: relative;
    z-index: 1000;
}

.cwg-dropdown-mask {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: 999;
    transition: all 0.3s;
    opacity: 0;
    pointer-events: none;
    background-color: rgba(0, 0, 0, 0);
}

.cwg-dropdown-mask-show {
    opacity: 1;
    pointer-events: auto;
}

.cwg-dropdown-menu-container {
    position: absolute;
    transform-origin: top;
    transform: scaleY(0);

    .menu {
        position: relative;
        --bs-bg-opacity: 1;
        background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
        box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.05);
        border: 1px solid var(--bs-border-color);
        border-radius: px2rpx(4);
        overflow: hidden;

        .menu-item {
            min-width: px2rpx(150);
            display: flex;
            align-items: center;
            padding: px2rpx(10) px2rpx(16);
            font-size: px2rpx(14);
            line-height: px2rpx(30);
            color: #fff;
            transition: background 0.2s;
            box-sizing: border-box;
            cursor: pointer;

            &:last-child {
                border-bottom: none;
            }

            text {
                flex: 1;
                line-height: 1.4;
            }

            &:hover {
                background-color: rgba(0, 0, 0, 0.05);
            }

            &:active {
                background-color: rgba(0, 0, 0, 0.05);
            }
        }
    }
}
</style>