<template>
    <div class="list-container">
        <view id="mylisttop" ref="listTopRef" />
        <scroll-view class="scroll-view" scroll-y :refresher-enabled="pullDown" :refresher-triggered="inRefresh"
            :style="{ height: height + 'px' }" :triggered="true" @refresherrefresh="pullToRefresh"
            :scroll-into-view="scrollIntoView" :lower-threshold="300" :scroll-with-animation="true"
            @scrolltolower="loadThePage">
            <view id="header" class="list-header">
                <slot />
            </view>
            <view v-if="empty" style="margin-top: 200rpx;">
                <up-empty :mode="mode" />
            </view>
            <view id="bottom" />
            <view v-if="safety" class="safety" />
        </scroll-view>
    </div>
</template>

<script setup>
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue'

const props = defineProps({
    getlist: Function,
    empty: Boolean,
    safety: {
        type: Boolean,
        default: true
    },
    mode: {
        type: String,
        default: "data"
    },
    pullDown: {
        type: Boolean,
        default: true
    },
    occupyHeight: {
        type: Number,
        default: 50
    }
})

const emit = defineEmits(['getlist'])

const inRefresh = ref(false)
const height = ref(0)
const scrollIntoView = ref("")
const listTopRef = ref(null)

// 获取当前组件实例
const instance = getCurrentInstance()

/* 下拉刷新 */
const pullToRefresh = () => {
    inRefresh.value = true
    emit("getlist", true)
}

/* 刷新完成 */
const refreshToComplete = () => {
    setTimeout(() => {
        inRefresh.value = false
    }, 500)
}

/* 加载分页 */
const loadThePage = () => {
    emit("getlist", false)
}

/* 修复元素查询方法 */
const getHeight = (selector, calculate = true) => {
    return new Promise((resolve, reject) => {
        // 使用 nextTick 确保 DOM 更新完成
        nextTick(() => {
            if (calculate) {
                uni.getSystemInfo({
                    success(s) {
                        uni.createSelectorQuery()
                            .in(instance) // 使用当前组件实例
                            .select(selector)
                            .boundingClientRect()
                            .exec(res => {
                                if (!res[0]) {
                                    console.warn(`元素查询失败: ${selector}`)
                                    reject('没有查询到元素')
                                } else {
                                    resolve(s.windowHeight - res[0].bottom)
                                }
                            })
                    }
                })
            } else {
                uni.createSelectorQuery()
                    .in(instance)
                    .select(selector)
                    .boundingClientRect()
                    .exec(res => {
                        if (!res[0]) {
                            console.warn(`元素查询失败: ${selector}`)
                            reject('没有查询到元素')
                        } else {
                            resolve(res[0])
                        }
                    })
            }
        })
    })
}

/* 设置组件高度 */
const setHeight = (mode, num) => {
    return new Promise((resolve) => {
        getHeight("#mylisttop", true).then(res => {
            let newHeight = res;
            switch (mode) {
                case 'add':
                    newHeight = res + num;
                    break;
                case 'minus':
                    newHeight = res - num;
                    break;
            }
            if (height.value !== newHeight) height.value = newHeight;
            resolve(newHeight)
        }).catch(err => {
            console.error(err)
            // 提供默认高度作为备选
            height.value = 500
            resolve(500)
        })
    })
}
// 初始化高度
onMounted(() => {
    // 添加延迟确保元素已渲染
    setTimeout(() => {
        setHeight()
    }, 100)
})

// 使用 defineExpose 暴露方法给父组件
defineExpose({
    refreshToComplete,
    setHeight
})
</script>

<style lang="scss" scoped>
.scroll-view {
    position: relative;
}

.safety {
    height: constant(safe-area-inset-bottom);
    height: env(safe-area-inset-bottom);
    width: 100%;
}
</style>