<template>
    <PullRefresh class="app-pull-refresh" v-model="refreshing" @refresh="onRefresh">
        <slot name="header"></slot>
        <List ref="listRef" v-model:loading="showLoading" v-model:error="showError" :finished="finished" @load="onLoad">
            <slot></slot>
            <template #finished>
                <span>{{ finishedText }}</span>
            </template>
            <template #error>
                <span>{{ errorText }}</span>
            </template>
        </List>
        <slot name="footer"></slot>
    </PullRefresh>
</template>

<script lang="ts" setup>
import { shallowRef, computed, nextTick, watch } from 'vue'
import { List, PullRefresh, ListInstance } from 'vant'

const props = defineProps({
    loading: {
        type: Boolean,
        default: false,
    },
    pageIndex: {
        type: Number,
        default: 1,
    },
    pageCount: {
        type: Number,
        default: 1,
    },
    error: {
        type: Boolean,
        default: false,
    },
    finishedText: {
        type: String,
        default: '没有更多了',
    },
    errorText: {
        type: String,
        default: '请求失败，点击重新加载',
    }
})

const emit = defineEmits(['update:loading', 'update:pageIndex', 'update:error', 'refresh'])
const listRef = shallowRef<ListInstance>()
const refreshing = shallowRef(false) // 是否处于下拉加载状态
const finished = shallowRef(false) // 是否已加载完成所有数据

const showLoading = computed({
    get: () => props.loading,
    set: (val) => emit('update:loading', val)
})

const showError = computed({
    get: () => props.error,
    set: (val) => emit('update:error', val)
})

const currentPage = computed({
    get: () => props.pageIndex,
    set: (val) => emit('update:pageIndex', val)
})

// 上拉加载
const onLoad = () => {
    if (refreshing.value) {
        currentPage.value = 1
    }
    nextTick(() => {
        if (currentPage.value <= props.pageCount) {
            emit('refresh')
        } else {
            refreshing.value = false
            finished.value = true
        }
    })
}

// 下拉刷新
const onRefresh = () => {
    // 下拉刷新过程中，可能会触发上拉加载，导致发送两次请求，所以先将 finished 设为 true，完成后再设为 false
    finished.value = true
    onLoad()
}

watch(showLoading, (status) => {
    if (!status) {
        finished.value = false
        if (refreshing.value) {
            refreshing.value = false
        }
        if (!showError.value) {
            currentPage.value++
        }
    }
})

// 暴露组件属性给父组件调用
defineExpose({
    refresh: () => {
        currentPage.value = 1
        onRefresh()
    },
})
</script>