<template>
  <view class="class-bullet-container">
    <!-- 第一行（可拖动 + 自动滚动） -->
    <view class="scroll-row first-row">
      <scroll-view
        class="ab-scroll mb-22rpx"
        scroll-x
        show-scrollbar="false"
        id="sv-1"
        style="--ab-scroll-timeout: 50s"
        :scroll-left="scrollLeft1"
        @touchstart="onTouchStart1"
        @touchend="onTouchEnd1"
        @touchcancel="onTouchEnd1"
        @scroll="onScroll1"
      >
        <view id="sv-inner-1" :class="['sv-inner', { 'paused': isDragging1 }]">
          <!-- 一份内容 -->
          <view
            v-for="(item, idx) in categories"
            :key="item.id + '-a-' + idx"
            class="category-item"
            @click="handleItemClick(item)"
          >
            <image v-if="item.categoryImage || item.logoUrl" :src="item.categoryImage || item.logoUrl" class="category-icon" mode="aspectFit" />
            <text class="category-text">{{ item.categoryName || item.name }}</text>
          </view>
          <!-- 第二份重复内容（用于无缝循环） -->
          <view
            v-for="(item, idx) in categories"
            :key="item.id + '-b-' + idx"
            class="category-item"
            @click="handleItemClick(item)"
          >
            <image v-if="item.categoryImage || item.logoUrl" :src="item.categoryImage || item.logoUrl" class="category-icon" mode="aspectFit" />
            <text class="category-text">{{ item.categoryName || item.name }}</text>
          </view>
        </view>
      </scroll-view>
    </view>

    <!-- 第二行（可拖动 + 自动滚动，速度不同） -->
    <view class="scroll-row">
      <scroll-view
        class="ab-scroll"
        scroll-x
        show-scrollbar="false"
        id="sv-2"
        style="--ab-scroll-timeout: 70s"
        :scroll-left="scrollLeft2"
        @touchstart="onTouchStart2"
        @touchend="onTouchEnd2"
        @touchcancel="onTouchEnd2"
        @scroll="onScroll2"
      >
        <view id="sv-inner-2" :class="['sv-inner', { 'paused': isDragging2 }]">
          <view
            v-for="(item, idx) in categoriesReversed"
            :key="item.id + '-c-' + idx"
            class="category-item"
            @click="handleItemClick(item)"
          >
            <image v-if="item.categoryImage || item.logoUrl" :src="item.categoryImage || item.logoUrl" class="category-icon" mode="aspectFit" />
            <text class="category-text">{{ item.categoryName || item.name }}</text>
          </view>
          <view
            v-for="(item, idx) in categoriesReversed"
            :key="item.id + '-d-' + idx"
            class="category-item"
            @click="handleItemClick(item)"
          >
            <image v-if="item.categoryImage || item.logoUrl" :src="item.categoryImage || item.logoUrl" class="category-icon" mode="aspectFit" />
            <text class="category-text">{{ item.categoryName || item.name }}</text>
          </view>
        </view>
      </scroll-view>
    </view>
  </view>
  
</template>

<script setup lang="ts">
import { computed, ref, onMounted, nextTick, getCurrentInstance } from 'vue'

// 定义分类项接口（与模板字段一致）
interface CategoryItem {
  id: number
  categoryImage?: string
  logoUrl?: string
  name?: string
  categoryName: string
}

// 定义组件属性
interface Props {
  /** 分类数据数组 */
  categories?: CategoryItem[]
}

const props = withDefaults(defineProps<Props>(), {
  categories: () => []
})

// 定义事件
const emit = defineEmits<{
  /** 点击分类项事件 */
  'itemClick': [item: CategoryItem]
}>()

// 模拟数据
const mockCategories: CategoryItem[] = [
  { id: 1, logoUrl: '/src/static/images/ls/6.png', name: '外卖点餐' },
  { id: 2, logoUrl: '/src/static/images/ls/7.png', name: '净菜商城' },
  { id: 3, logoUrl: '/src/static/images/ls/8.png', name: '生鲜冷链' },
  { id: 4, logoUrl: '/src/static/images/ls/9.png', name: '肉类' },
  { id: 5, logoUrl: '/src/static/images/ls/10.png', name: '调料' },
  { id: 6, logoUrl: '/src/static/images/ls/11.png', name: '零食' },
  { id: 7, logoUrl: '/src/static/images/ls/12.png', name: '海鲜' }
]

// 使用传入的数据或默认数据
const categories = computed(() => {
  return props.categories.length > 0 ? props.categories : mockCategories
})
// 第二行使用反向顺序以形成与第一行相反的视觉效果
const categoriesReversed = computed(() => {
  const list = categories.value || []
  return list.slice().reverse()
})

// 自动滚动（CSS 动画）+ 手动拖动时暂停
const isDragging1 = ref(false)
const isDragging2 = ref(false)
const RESUME_DELAY_MS = 1200
let resumeTimer1: any
let resumeTimer2: any

// 中心定位与边界重置，避免滚动到底卡住
const scrollLeft1 = ref(0)
const scrollLeft2 = ref(0)
const copyWidth1Px = ref(0)
const copyWidth2Px = ref(0)
const viewportWidth1Px = ref(0)
const viewportWidth2Px = ref(0)

function measureAndInit() {
  const ins = getCurrentInstance()
  const q = uni.createSelectorQuery().in(ins?.proxy as any)
  q.select('#sv-1').boundingClientRect()
    .select('#sv-inner-1').boundingClientRect()
    .select('#sv-2').boundingClientRect()
    .select('#sv-inner-2').boundingClientRect()
    .exec((res) => {
      const sv1 = res?.[0]
      const inner1 = res?.[1]
      const sv2 = res?.[2]
      const inner2 = res?.[3]
      if (sv1?.width) viewportWidth1Px.value = sv1.width
      if (inner1?.width) copyWidth1Px.value = inner1.width / 2
      if (sv2?.width) viewportWidth2Px.value = sv2.width
      if (inner2?.width) copyWidth2Px.value = inner2.width / 2
      // 初始化到中间位置
      if (copyWidth1Px.value) scrollLeft1.value = copyWidth1Px.value
      if (copyWidth2Px.value) scrollLeft2.value = copyWidth2Px.value
    })
}

function recenter1(currentLeft?: number) {
  const cw = copyWidth1Px.value
  const vw = viewportWidth1Px.value
  if (!cw || !vw) return
  const left = currentLeft ?? scrollLeft1.value
  const mod = left % cw
  scrollLeft1.value = cw + mod
}

function recenter2(currentLeft?: number) {
  const cw = copyWidth2Px.value
  const vw = viewportWidth2Px.value
  if (!cw || !vw) return
  const left = currentLeft ?? scrollLeft2.value
  const mod = left % cw
  scrollLeft2.value = cw + mod
}

function onTouchStart1() {
  isDragging1.value = true
  if (resumeTimer1) clearTimeout(resumeTimer1)
}
function onTouchEnd1() {
  // 手指松开后，若在边界附近，立即重置到中间位置，保持无缝
  recenter1(scrollLeft1.value)
  resumeTimer1 = setTimeout(() => {
    isDragging1.value = false
  }, RESUME_DELAY_MS)
}
function onScroll1(e: any) {
  isDragging1.value = true
  if (resumeTimer1) clearTimeout(resumeTimer1)
  const left = e?.detail?.scrollLeft ?? 0
  const cw = copyWidth1Px.value
  const vw = viewportWidth1Px.value
  if (cw && vw) {
    const total = cw * 2
    // 临界阈值，靠近起点或终点时重置
    const threshold = 10
    if (left <= threshold || left >= total - vw - threshold) {
      recenter1(left)
    }
  }
  resumeTimer1 = setTimeout(() => {
    isDragging1.value = false
  }, RESUME_DELAY_MS)
}
function onTouchStart2() {
  isDragging2.value = true
  if (resumeTimer2) clearTimeout(resumeTimer2)
}
function onTouchEnd2() {
  recenter2(scrollLeft2.value)
  resumeTimer2 = setTimeout(() => {
    isDragging2.value = false
  }, RESUME_DELAY_MS)
}
function onScroll2(e: any) {
  isDragging2.value = true
  if (resumeTimer2) clearTimeout(resumeTimer2)
  const left = e?.detail?.scrollLeft ?? 0
  const cw = copyWidth2Px.value
  const vw = viewportWidth2Px.value
  if (cw && vw) {
    const total = cw * 2
    const threshold = 10
    if (left <= threshold || left >= total - vw - threshold) {
      recenter2(left)
    }
  }
  resumeTimer2 = setTimeout(() => {
    isDragging2.value = false
  }, RESUME_DELAY_MS)
}

// 点击处理
const handleItemClick = (item: CategoryItem) => {
  emit('itemClick', item)
  navigateTo('/pages-store/pages/list/index?id=' + item.id)
}

function navigateTo(url: string) {
  uni.navigateTo({ url })
}

onMounted(() => {
  nextTick(() => {
    measureAndInit()
  })
})
</script>

<style lang="scss" scoped>
.class-bullet-container {
  width: 100%;
  overflow: hidden;

  .scroll-row {
    margin-bottom: 20rpx;
    overflow: hidden;

    &:last-child {
      margin-bottom: 0;
    }
  }

  .ab-scroll {
    width: 100%;
    overflow: hidden;
  }

  .sv-inner {
    display: flex;
    flex-direction: row;
    gap: 20rpx;
    animation: ab-move-marquee var(--ab-scroll-timeout) linear infinite;
    will-change: transform;
  }

  .category-item {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 120rpx;
    height: 60rpx;
    padding: 0 20rpx;
    border: 1px solid #C8C8C8;
    border-radius: 30rpx;
    cursor: pointer;
    transition: all 0.2s ease;
    flex-shrink: 0;

    &:active {
      transform: translateY(0) scale(0.95);
    }

    .category-icon {
      width: 32rpx;
      height: 32rpx;
      margin-right: 8rpx;
      flex-shrink: 0;
    }

    .category-text {
      font-size: 28rpx;
      color: #333;
      white-space: nowrap;
    }
  }
}

// GPU 动画，无缝循环（两份内容）
@keyframes ab-move-marquee {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-50%);
  }
}

.paused {
  animation-play-state: paused;
}
</style>
