<template>
  <!-- 预览放大（带缩放/拖拽/旋转/工具栏） -->
  <Teleport to="body">
    <div
      v-if="previewVisible"
      class="image-preview"
      @click.self="closePreview"
      @wheel.prevent="onWheel"
    >
      <div class="image-preview__toolbar">
        <button @click.stop="zoomOut">－</button>
        <button @click.stop="zoomIn">＋</button>
        <button @click.stop="resetTransform">{{ lang.ssReset }}</button>
        <button @click.stop="rotateLeft">⟲</button>
        <button @click.stop="rotateRight">⟳</button>
        <button @click.stop="toggleFit">
          {{ fitMode ? lang.ssActualSize : lang.ssFitScreen }}
        </button>
        <button @click.stop="closePreview">{{ lang.ssClose }}</button>
      </div>
      <div
        class="image-preview__stage"
        @mousedown="onDragStart"
        @mousemove="onDragMove"
        @mouseup="onDragEnd"
        @mouseleave="onDragEnd"
        @dblclick.stop="toggleZoom"
      >
        <!-- 预览中的 Loading 状态 -->
        <div v-if="previewImageLoading" class="preview-loading">
          <div class="loading-spinner"></div>
          <div class="loading-text">{{ lang.ssImgLoading }}</div>
        </div>

        <img
          v-show="!previewImageLoading"
          :src="imageUrl"
          alt="预览"
          class="image-preview__img"
          :style="imgStyle"
          draggable="false"
          @load="onPreviewImageLoad"
          @error="onPreviewImageError"
        />
      </div>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
import { ref, watch, computed, defineExpose } from 'vue'
import { lang } from '@/main'
const imageUrl = ref<string>('')
// Loading 状态
const imageLoading = ref(false)
const previewImageLoading = ref(false)

const previewImage = (url: string) => {
  imageUrl.value = url
  previewVisible.value = true
}

// 监听图片URL变化，重置loading状态
watch(imageUrl, (newUrl) => {
  if (newUrl) {
    imageLoading.value = true
    previewImageLoading.value = true
  }
})

const previewVisible = ref(false)
const scale = ref(1)
const rotate = ref(0)
const offsetX = ref(0)
const offsetY = ref(0)
const dragging = ref(false)
const lastX = ref(0)
const lastY = ref(0)
const fitMode = ref(true)

const imgStyle = computed(() => {
  const t = `translate(${offsetX.value}px, ${offsetY.value}px) rotate(${rotate.value}deg) scale(${scale.value})`
  return {
    transform: t,
  }
})

// 图片加载事件处理
const onImageLoad = () => {
  imageLoading.value = false
}

const onImageError = () => {
  imageLoading.value = false
  console.error('图片加载失败')
}

const onPreviewImageLoad = () => {
  previewImageLoading.value = false
}

const onPreviewImageError = () => {
  previewImageLoading.value = false
  console.error('预览图片加载失败')
}

const openPreview = () => {
  if (imageLoading.value) return // 如果主图片还在加载，不允许打开预览
  previewVisible.value = true
  previewImageLoading.value = true // 预览时重新显示loading
  nextTickFit()
}

const closePreview = () => {
  previewVisible.value = false
}

const zoomStep = 0.2
const minScale = 0.2
const maxScale = 6

const zoomIn = () => {
  fitMode.value = false
  scale.value = Math.min(maxScale, +(scale.value + zoomStep).toFixed(2))
}
const zoomOut = () => {
  fitMode.value = false
  scale.value = Math.max(minScale, +(scale.value - zoomStep).toFixed(2))
}
const resetTransform = () => {
  scale.value = 1
  rotate.value = 0
  offsetX.value = 0
  offsetY.value = 0
  fitMode.value = true
  nextTickFit()
}
const rotateLeft = () => {
  rotate.value = (rotate.value - 90) % 360
}
const rotateRight = () => {
  rotate.value = (rotate.value + 90) % 360
}

const toggleZoom = () => {
  fitMode.value = false
  scale.value = scale.value >= 1.8 ? 1 : 2
}

const toggleFit = () => {
  fitMode.value = !fitMode.value
  nextTickFit()
}

const nextTickFit = () => {
  // 适应屏幕时复位位置与缩放
  if (fitMode.value) {
    scale.value = 1
    offsetX.value = 0
    offsetY.value = 0
  }
}

const onWheel = (e: WheelEvent) => {
  if (e.deltaY > 0) zoomOut()
  else zoomIn()
}

const onDragStart = (e: MouseEvent) => {
  dragging.value = true
  lastX.value = e.clientX
  lastY.value = e.clientY
}
const onDragMove = (e: MouseEvent) => {
  if (!dragging.value) return
  const dx = e.clientX - lastX.value
  const dy = e.clientY - lastY.value
  lastX.value = e.clientX
  lastY.value = e.clientY
  offsetX.value += dx
  offsetY.value += dy
}
const onDragEnd = () => {
  dragging.value = false
}

defineExpose({
  previewImage,
})
</script>

<style lang="scss" scoped></style>
