<template>
  <scroll-view 
    class="virtual-list"
    :scroll-y="true"
    :show-scrollbar="false"
    :scroll-top="scrollTopValue"
    :lower-threshold="lowerThreshold"
    :upper-threshold="upperThreshold"
    @scroll="handleScroll"
    @scrolltolower="handleScrollToLower"
    @scrolltoupper="handleScrollToUpper"
    :style="{ height: containerHeight }"
  >
    <!-- 占位容器，撑开总高度 -->
    <view :style="{ height: totalHeight + 'px', position: 'relative' }">
      <!-- 可见区域容器 -->
      <view 
        class="visible-items"
        :style="{ 
          transform: `translateY(${offsetY}px)`,
          position: 'absolute',
          top: 0,
          left: 0,
          right: 0
        }"
      >
        <slot 
          v-for="item in visibleItems" 
          :key="getItemKey(item)"
          :item="item"
          :index="item.__index"
        ></slot>
      </view>
    </view>
  </scroll-view>
</template>

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

const props = defineProps({
  // 数据列表
  items: {
    type: Array,
    required: true,
    default: () => []
  },
  // 每项的高度（rpx）
  itemHeight: {
    type: Number,
    required: true
  },
  // 容器高度
  containerHeight: {
    type: String,
    default: '100%'
  },
  // 缓冲区项数（上下各渲染多少额外项）
  bufferSize: {
    type: Number,
    default: 3
  },
  // 获取项的唯一key
  keyField: {
    type: String,
    default: 'id'
  },
  // 滚动节流时间（ms）
  throttleTime: {
    type: Number,
    default: 16 // 约60fps
  }
})

const emit = defineEmits(['scroll', 'scrolltolower', 'scrolltoupper'])

// 滚动位置
const scrollTop = ref(0)
const scrollTopValue = ref(0)

// 节流控制
const lastScrollTime = ref(0)
const scrollTimer = ref(null)

// 初始化状态
const isInitialized = ref(false)

// 阈值设置（使用 px 单位）
const lowerThreshold = ref(100)
const upperThreshold = ref(100)

// 优化：缓存系统信息，避免重复调用 getSystemInfoSync()
const systemInfo = ref(null)
const rpxToPxRatio = ref(1)

// 初始化系统信息（只调用一次）
const initSystemInfo = () => {
  if (!systemInfo.value) {
    systemInfo.value = uni.getSystemInfoSync()
    rpxToPxRatio.value = systemInfo.value.windowWidth / 750
  }
}

// 转换rpx到px（使用缓存的比例）
const rpxToPx = (rpx) => {
  return rpx * rpxToPxRatio.value
}

// 项高度（px）- 使用缓存的转换比例
const itemHeightPx = ref(0)

// 总高度（px）
const totalHeight = computed(() => {
  return props.items.length * itemHeightPx.value
})

// 可视区域高度（px）
const viewportHeight = ref(0)

// 优化：修复初始化时序
onMounted(() => {
  nextTick(() => {
    // 初始化系统信息（只调用一次 getSystemInfoSync）
    initSystemInfo()
    
    // 计算项高度（只计算一次）
    itemHeightPx.value = rpxToPx(props.itemHeight)
    
    // 设置阈值（转换为px）
    lowerThreshold.value = rpxToPx(200)
    upperThreshold.value = rpxToPx(200)
    
    // 先使用默认值并标记初始化完成，避免阻塞渲染
    viewportHeight.value = systemInfo.value.windowHeight * 0.8
    isInitialized.value = true
    
    // 异步获取实际容器高度（不阻塞初始化）
    nextTick(() => {
      const query = uni.createSelectorQuery()
      query.select('.virtual-list').boundingClientRect((rect) => {
        if (rect && rect.height > 0) {
          viewportHeight.value = rect.height
        }
      }).exec()
    })
  })
})

// 可见项的起始索引
const startIndex = computed(() => {
  if (!isInitialized.value || itemHeightPx.value === 0) return 0
  
  const index = Math.floor(scrollTop.value / itemHeightPx.value) - props.bufferSize
  return Math.max(0, index)
})

// 可见项的结束索引
const endIndex = computed(() => {
  if (!isInitialized.value || itemHeightPx.value === 0) {
    // 初始化时只渲染前几项
    return Math.min(props.items.length, 10)
  }
  
  const visibleCount = Math.ceil(viewportHeight.value / itemHeightPx.value)
  const index = startIndex.value + visibleCount + props.bufferSize * 2
  return Math.min(props.items.length, index)
})

// 可见项列表
const visibleItems = computed(() => {
  return props.items
    .slice(startIndex.value, endIndex.value)
    .map((item, index) => ({
      ...item,
      __index: startIndex.value + index
    }))
})

// 偏移量
const offsetY = computed(() => {
  if (itemHeightPx.value === 0) return 0
  return startIndex.value * itemHeightPx.value
})

// 优化：添加滚动节流
const handleScroll = (e) => {
  const now = Date.now()
  
  // 节流控制
  if (now - lastScrollTime.value < props.throttleTime) {
    // 清除之前的定时器
    if (scrollTimer.value) {
      clearTimeout(scrollTimer.value)
    }
    
    // 设置新的定时器，确保最后一次滚动事件被处理
    scrollTimer.value = setTimeout(() => {
      updateScrollPosition(e.detail.scrollTop)
      emit('scroll', e)
      scrollTimer.value = null
    }, props.throttleTime)
    
    return
  }
  
  lastScrollTime.value = now
  updateScrollPosition(e.detail.scrollTop)
  emit('scroll', e)
}

// 更新滚动位置
const updateScrollPosition = (newScrollTop) => {
  scrollTop.value = newScrollTop
}

// 使用 provide 向子组件提供 scrollTop
import { provide } from 'vue'
provide('virtualListScrollTop', scrollTop)

// 暴露 scrollTop 给父组件使用
defineExpose({
  scrollTop
})

// 优化：使用 scrolltolower 事件替代高频滚动检测
const handleScrollToLower = (e) => {
  emit('scrolltolower', e)
}

// 优化：使用 scrolltoupper 事件替代高频滚动检测
const handleScrollToUpper = (e) => {
  emit('scrolltoupper', e)
}

// 获取项的key
const getItemKey = (item) => {
  return item[props.keyField] || item.__index
}

// 监听数据变化，重置滚动位置
watch(() => props.items, () => {
  scrollTop.value = 0
  scrollTopValue.value = 0
}, { deep: false })

// 清理定时器
const cleanup = () => {
  if (scrollTimer.value) {
    clearTimeout(scrollTimer.value)
    scrollTimer.value = null
  }
}

// 组件卸载时清理
import { onUnmounted } from 'vue'
onUnmounted(() => {
  cleanup()
})
</script>

<style scoped>
.virtual-list {
  width: 100%;
  overflow: hidden;
}

.visible-items {
  width: 100%;
}
</style>
