<template>
    <div
        ref="pullContainer"
        class="pull-refresh-container"
        @touchstart="handleTouchStart"
        @touchmove="handleTouchMove"
        @touchend="handleTouchEnd"
    >
        <!-- 下拉刷新区域 -->
        <div
            ref="pullHeader"
            class="pull-header"
            :style="{ transform: `translateY(${pullDistance}px)` }"
        >
            <div class="pull-text">
                <template v-if="refreshStatus === 'pull'">
                    {{ pullText }}
                </template>
                <template v-else-if="refreshStatus === 'release'">
                    {{ releaseText }}
                </template>
                <template v-else-if="refreshStatus === 'refreshing'"> <span class="spinner"></span> {{ refreshingText }} </template>
            </div>
        </div>

        <!-- 内容区域 -->
        <div class="content">
            <slot />
        </div>
    </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue';

import { useBodyClass } from '@/hooks/useBodyClass';

useBodyClass('body-overflow-hidden');

// ==================== Props ====================
const props = defineProps({
    pullThreshold: {
        type: Number,
        default: 80,
    },
    pullText: {
        type: String,
        default: '下拉刷新',
    },
    releaseText: {
        type: String,
        default: '释放刷新',
    },
    refreshingText: {
        type: String,
        default: '刷新中...',
    },
    onRefresh: {
        type: Function,
        required: true,
    },
});

// ==================== Refs ====================
const pullContainer = ref(null);
const pullHeader = ref(null);

// ==================== State ====================
const pullDistance = ref(0);
const startY = ref(0);
const isDragging = ref(false);
const refreshStatus = ref('idle');

// ==================== Computed ====================
const isPulling = computed(() => pullDistance.value > 0);

// ==================== Methods ====================
const handleTouchStart = (e) => {
    startY.value = e.touches[0].clientY;
    isDragging.value = true;
    pullDistance.value = 0;
};

const handleTouchMove = (e) => {
    if (!isDragging.value) return;

    const currentY = e.touches[0].clientY;
    const deltaY = currentY - startY.value;

    // 只允许向下拉
    if (deltaY <= 0) {
        pullDistance.value = 0;
        return;
    }

    // 限制最大下拉距离（可选）
    const maxPull = props.pullThreshold * 1.5;
    pullDistance.value = Math.min(deltaY, maxPull);

    // 更新状态
    if (pullDistance.value >= props.pullThreshold) {
        refreshStatus.value = 'release';
    } else {
        refreshStatus.value = 'pull';
    }

    // 手动控制内容区域的 transform，模拟弹性滚动
    const content = pullContainer.value.querySelector('.content');
    if (content) {
        content.style.transform = `translateY(${pullDistance.value}px)`;
        content.style.transition = 'none';
    }
};

const handleTouchEnd = async () => {
    // debugger
    if (!isDragging.value) return;
    isDragging.value = false;

    if (pullDistance.value >= props.pullThreshold) {
        // 触发刷新
        refreshStatus.value = 'refreshing';

        // 保持在阈值位置，不回弹
        const targetDistance = props.pullThreshold;
        // pullDistance.value = targetDistance
        pullDistance.value = 60;
        const content = pullContainer.value.querySelector('.content');
        if (content) {
            content.style.transition = 'transform 0s ease-out';
            content.style.transform = 'translateY(60px)';
        }

        try {
            await props.onRefresh();
        } catch (error) {
            console.error('刷新失败:', error);
        } finally {
            // 刷新完成，才开始回弹
            pullDistance.value = 0;
            refreshStatus.value = 'idle';

            const content = pullContainer.value.querySelector('.content');
            if (content) {
                content.style.transition = 'transform 0.3s ease-out';
                content.style.transform = 'translateY(0px)';
            }
        }
    } else {
        // 未达到阈值，直接回弹到顶部
        pullDistance.value = 0;
        refreshStatus.value = 'idle';

        const content = pullContainer.value.querySelector('.content');
        if (content) {
            content.style.transition = 'transform 0.3s ease-out';
            content.style.transform = 'translateY(0px)';
        }
    }
};

// ==================== Lifecycle ====================
onMounted(() => {
    const header = pullHeader.value;
    if (header) {
        header.style.height = `${header.clientHeight}px`;
    }
});

onUnmounted(() => {
    // 清理事件监听（Vue 3 中通常不需要手动清除，但安全起见）
});
</script>

<style scoped>
.pull-refresh-container {
    position: relative;
    height: 100vh;
    overflow: hidden;
    touch-action: none;
    margin-top: -60px !important;
}

.pull-header {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #f5f5f5;
    z-index: 10;
    will-change: transform;
}

.pull-text {
    font-size: 14px;
    color: #999;
    text-align: center;
}

.spinner {
    display: inline-block;
    width: 16px;
    height: 16px;
    border: 2px solid #ccc;
    border-top-color: #007aff;
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin-right: 6px;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

.content {
    padding-top: 60px;
    height: 100vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    will-change: transform;
    transition: transform 0.3s ease-out;
}
</style>
