<template>
  <div class="image-viewer-container w-full h-full">

    <!-- 图片错误状态 -->
    <div v-if="hasError" class="image-error" :style="containerStyle">
      <div class="error-icon">⚠️</div>
      <span class="error-text">{{ errorText }}</span>
    </div>

    <!-- 缩略图 -->
    <div v-else @click="openViewer">
      <img :src="src" :alt="alt || '图片'" :style="{ ...containerStyle, cursor: preview ? 'pointer' : 'default' }"
        @load="handleLoad" @error="handleError" />
    </div>

    <!-- 预览模态框 -->
    <transition name="modal">
      <div v-if="isViewerOpen" class="viewer-overlay" @click="closeViewer">
        <div class="viewer-container" @click.stop>
          <!-- 关闭按钮 -->
          <button class="close-btn" @click="closeViewer" aria-label="关闭">×</button>

          <!-- 预览图片 -->
          <img :src="src" :alt="alt || '图片预览'" class="preview-image" :style="{ cursor: zoom ? 'grab' : 'default' }" />
        </div>
      </div>
    </transition>
  </div>
</template>

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

// Props定义
interface Props {
  src: string // 图片路径
  alt?: string // 图片描述
  width?: string | number // 图片宽度
  height?: string | number // 图片高度
  preview?: boolean // 是否启用预览功能
  zoom?: boolean // 是否允许缩放
  customClass?: string // 自定义CSS类名
  skeleton?: boolean // 是否显示骨架屏（懒加载）
  errorText?: string // 错误提示文本
  placeholder?: string // 占位图片
}

const props = withDefaults(defineProps<Props>(), {
  alt: '',
  width: 'auto',
  height: 'auto',
  preview: true,
  zoom: false,
  customClass: '',
  skeleton: false,
  errorText: '图片加载失败',
  placeholder: ''
})

// Emits定义
const emit = defineEmits<{
  load: []
  error: [error: Event]
  preview: []
  close: []
}>()

// 状态管理
const isViewerOpen = ref(false)
const isLoading = ref(true)
const hasError = ref(false)
const errorEvent = ref<Event | null>(null)

// 计算容器样式
const containerStyle = computed(() => {
  return {
    width: typeof props.width === 'number' ? `${props.width}px` : props.width,
    height: typeof props.height === 'number' ? `${props.height}px` : props.height
  }
})

// 处理图片加载完成
const handleLoad = (event: Event) => {
  isLoading.value = false
  hasError.value = false
  emit('load')
}

// 处理图片加载错误
const handleError = (event: Event) => {
  isLoading.value = false
  hasError.value = true
  errorEvent.value = event
  emit('error', event)
}

// 打开预览
const openViewer = () => {
  if (!props.preview) return

  isViewerOpen.value = true
  // 阻止背景滚动
  document.body.style.overflow = 'hidden'
  emit('preview')
}

// 关闭预览
const closeViewer = () => {
  isViewerOpen.value = false
  // 恢复背景滚动
  document.body.style.overflow = ''
  emit('close')
}
</script>

<style scoped>
/* 缩略图样式 */
.thumbnail {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  transition: transform 0.2s, opacity 0.3s;
  opacity: 1;
}

.thumbnail:hover {
  transform: scale(1.02);
}

.thumbnail.cursor-pointer {
  cursor: pointer;
}

/* 图片加载中状态 */
.image-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f0f0f0;
  border-radius: 4px;
}

.loading-spinner {
  width: 30px;
  height: 30px;
  border: 3px solid rgba(0, 0, 0, 0.1);
  border-top-color: #3b82f6;
  border-radius: 50%;
  animation: spin 1s ease-in-out infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* 图片错误状态 */
.image-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #f8f8f8;
  border: 1px dashed #e5e7eb;
  border-radius: 4px;
  color: #6b7280;
  padding: 20px;
  text-align: center;
}

.error-icon {
  font-size: 32px;
  margin-bottom: 8px;
}

.error-text {
  font-size: 14px;
  line-height: 1.5;
}

/* 模态框过渡动画 */
.modal-enter-active,
.modal-leave-active {
  transition: opacity 0.3s;
}

.modal-enter-from,
.modal-leave-to {
  opacity: 0;
}

/* 预览模态框样式 */
.viewer-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  animation: fadeIn 0.3s ease-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.viewer-container {
  position: relative;
  max-width: 95%;
  max-height: 95%;
  animation: zoomIn 0.3s ease-out;
}

@keyframes zoomIn {
  from {
    transform: scale(0.9);
    opacity: 0;
  }

  to {
    transform: scale(1);
    opacity: 1;
  }
}

.preview-image {
  max-width: 100%;
  max-height: 90vh;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}

.close-btn {
  position: absolute;
  top: -50px;
  right: -20px;
  width: 40px;
  height: 40px;
  border: none;
  background-color: rgba(255, 255, 255, 0.15);
  color: white;
  font-size: 28px;
  font-weight: 300;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
}

.close-btn:hover {
  background-color: rgba(255, 255, 255, 0.3);
  transform: scale(1.1);
}

.close-btn:active {
  transform: scale(0.95);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .viewer-container {
    max-width: 98%;
    max-height: 98%;
  }

  .preview-image {
    max-height: 85vh;
  }

  .close-btn {
    top: -40px;
    right: -10px;
    width: 36px;
    height: 36px;
    font-size: 24px;
  }
}
</style>