<template>
  <Modal :visible="visible" :width="800" :closeButton="true" @update:visible="val => emit('update:visible', val)">
    <div class="shot-wrap">
      <div v-if="imageUrl" class="image-container">
        <!-- Loading 状态 -->
        <div v-if="imageLoading" class="image-loading">
          <div class="loading-spinner"></div>
          <div class="loading-text">{{ lang.ssLoading }}</div>
        </div>
        
        <!-- 图片 -->
        <img 
          v-show="!imageLoading"
          :src="imageUrl" 
          :alt="lang.ssShotWork" 
          class="shot-img" 
          @click="openPreview"
          @load="onImageLoad"
          @error="onImageError"
        />
      </div>
      <div v-else class="shot-empty">{{ lang.ssNoImage }}</div>
    </div>
  </Modal>

  <!-- 预览放大（带缩放/拖拽/旋转/工具栏） -->
  <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.ssLoading }}</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 lang="ts" setup>
import { computed, ref, watch } from 'vue'
import Modal from '@/components/Modal.vue'
import { lang } from '@/main'

const props = defineProps<{
  visible: boolean
  work: any
}>()

const emit = defineEmits<{
  (e: 'update:visible', v: boolean): void
}>()

const visible = computed({
  get: () => props.visible,
  set: (v: boolean) => emit('update:visible', v)
})

const imageUrl = computed(() => {
  const raw = props.work?.content
  if (!raw) return ''
  try {
    const obj = typeof raw === 'string' ? JSON.parse(raw) : raw
    return obj?.url || obj?.image || obj?.src || ''
  }
  catch {
    return String(raw)
  }
})

// Loading 状态
const imageLoading = ref(false)
const previewImageLoading = ref(false)

// 监听图片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 
}
</script>

<style scoped>
.shot-wrap {
  max-height: 70vh;
  overflow: auto;
}

.image-container {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 200px;
}

.shot-img {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: 6px;
  cursor: zoom-in;
}

.shot-empty {
  color: #999;
  font-size: 14px;
  text-align: center;
  padding: 40px 20px;
}

/* Loading 样式 */
.image-loading, .preview-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  color: #666;
  font-size: 14px;
}

.loading-spinner {
  width: 32px;
  height: 32px;
  border: 3px solid #f3f3f3;
  border-top: 3px solid #3a8bff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

.loading-text {
  font-size: 14px;
  color: #666;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.image-preview {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.85);
  display: flex;
  flex-direction: column;
  z-index: 6000;
}

.image-preview__toolbar {
  display: flex;
  gap: 8px;
  padding: 10px;
  justify-content: center;
  z-index: 9999;
}

.image-preview__toolbar button {
  padding: 8px 12px;
  border: none;
  background: linear-gradient(180deg, #3a8bff 0%, #2f80ed 100%);
  color: #fff;
  border-radius: 10px;
  cursor: pointer;
  transition: transform .15s ease, box-shadow .2s ease, background .2s ease;
  box-shadow: 0 2px 8px rgba(47,128,237,.3);
}

.image-preview__toolbar button:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(47,128,237,.35);
}

.image-preview__toolbar button:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(47,128,237,.28);
  background: linear-gradient(180deg, #2f80ed 0%, #1b6dde 100%);
}

.image-preview__toolbar button:focus-visible {
  outline: 2px solid rgba(47,128,237,.6);
  outline-offset: 2px;
}

.image-preview__stage {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  position: relative;
}

.image-preview__stage:active { 
  cursor: grabbing; 
}

.image-preview__img {
  max-width: 92vw;
  max-height: 92vh;
  border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0,0,0,.3);
  user-select: none;
  will-change: transform;
}

/* 预览中的 loading 样式 */
.preview-loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
}

.preview-loading .loading-spinner {
  width: 40px;
  height: 40px;
  border-width: 4px;
}

.preview-loading .loading-text {
  color: #fff;
  font-size: 16px;
}
</style>