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

const props = defineProps({
  src: { type: String, required: true },
  alt: { type: String, default: '长图' },
  chunkHeight: { type: Number, default: 1500 }
})

const imageList = ref([])

// 预览层
const showViewer = ref(false)
const currentIndex = ref(0)
const viewImg = ref('')

// 缩放
const scale = ref(1)
const startScale = ref(1)
const startDistance = ref(0)

// 滑动
const startX = ref(0)

// 打开预览
const openView = (idx) => {
  currentIndex.value = idx
  viewImg.value = imageList.value[idx]
  showViewer.value = true
  scale.value = 1
  document.body.style.overflow = 'hidden'
}

// 关闭预览
const closeView = () => {
  showViewer.value = false
  document.body.style.overflow = ''
}

// 上一张
const prevImg = () => {
  if (currentIndex.value > 0) {
    currentIndex.value--
    viewImg.value = imageList.value[currentIndex.value]
    scale.value = 1
  }
}

// 下一张
const nextImg = () => {
  if (currentIndex.value < imageList.value.length - 1) {
    currentIndex.value++
    viewImg.value = imageList.value[currentIndex.value]
    scale.value = 1
  }
}

// 触摸开始
const onTouchStart = (e) => {
  if (e.touches.length === 1) {
    startX.value = e.touches[0].clientX
  }
  if (e.touches.length === 2) {
    startDistance.value = getDistance(e.touches[0], e.touches[1])
    startScale.value = scale.value
  }
}

// 触摸移动
const onTouchMove = (e) => {
  e.preventDefault()
  if (e.touches.length === 2) {
    const dist = getDistance(e.touches[0], e.touches[1])
    scale.value = Math.min(5, Math.max(1, startScale.value * (dist / startDistance.value)))
  }
}

// 触摸结束
const onTouchEnd = (e) => {
  if (e.changedTouches.length === 1) {
    const diff = e.changedTouches[0].clientX - startX.value
    if (Math.abs(diff) > 60) {
      diff > 0 ? prevImg() : nextImg()
    }
  }
}

// 计算双指距离
const getDistance = (p1, p2) => {
  return Math.hypot(p2.clientX - p1.clientX, p2.clientY - p1.clientY)
}

// 切割长图
const sliceImage = () => {
  const img = new Image()
  img.crossOrigin = 'anonymous'
  img.onload = () => {
    const { width, height } = img
    const num = Math.ceil(height / props.chunkHeight)
    const slices = []
    for (let i = 0; i < num; i++) {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      const h = Math.min(props.chunkHeight, height - i * props.chunkHeight)
      canvas.width = width
      canvas.height = h
      ctx.drawImage(img, 0, i * props.chunkHeight, width, h, 0, 0, width, h)
      slices.push(canvas.toDataURL('image/jpeg', 1.0))
    }
    imageList.value = slices
  }
  img.src = props.src
}

onMounted(() => {
  sliceImage()
})
</script>

<template>
  <div class="long-pic-slice">
    <img
        v-for="(data, idx) in imageList"
        :key="idx"
        :src="data"
        :alt="`${alt}-${idx}`"
        class="slice-img"
        loading="eager"
        @click="openView(idx)"
    />

    <!-- 全屏预览层 -->
    <div v-if="showViewer" class="viewer" @click="closeView">
      <!-- 左箭头 -->
      <div
          class="arrow arrow-left"
          @click.stop="prevImg"
          :class="{ disabled: currentIndex <= 0 }"
      >
        ‹
      </div>

      <!-- 图片 -->
      <img
          :src="viewImg"
          class="viewer-img"
          :style="{ transform: `scale(${scale})` }"
          @click.stop
          @touchstart.prevent="onTouchStart"
          @touchmove.prevent="onTouchMove"
          @touchend.prevent="onTouchEnd"
      />

      <!-- 右箭头 -->
      <div
          class="arrow arrow-right"
          @click.stop="nextImg"
          :class="{ disabled: currentIndex >= imageList.length - 1 }"
      >
        ›
      </div>

      <!-- 底部指示器 -->
      <div class="indicator">
        {{ currentIndex + 1 }} / {{ imageList.length }}
      </div>
    </div>
  </div>
</template>

<style scoped>
.long-pic-slice {
  width: 100%;
  max-width: 100%;
  overflow: hidden;
  margin: 12px 0;
}
.slice-img {
  display: block;
  width: 100%;
  height: auto;
  cursor: pointer;
}

/* 全屏预览 */
.viewer {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.97);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 999999;
}

.viewer-img {
  max-width: 90%;
  max-height: 90vh;
  object-fit: contain;
  transition: transform 0.2s ease;
  user-select: none;
}

/* 箭头 */
.arrow {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  width: 50px;
  height: 50px;
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
  font-size: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 10;
  user-select: none;
}
.arrow-left {
  left: 20px;
}
.arrow-right {
  right: 20px;
}
.arrow.disabled {
  opacity: 0.3;
  pointer-events: none;
}

/* 指示器 */
.indicator {
  position: fixed;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
  color: #fff;
  font-size: 16px;
  background: rgba(0, 0, 0, 0.4);
  padding: 6px 14px;
  border-radius: 20px;
  z-index: 10;
}
</style>
