<template>
  <div class="image-upload">
    <!-- 上传区域 -->
    <div class="upload-area">
      <!-- 已有图片时显示预览 -->
      <div v-if="modelValue" class="image-preview-wrapper">
        <el-image
          ref="imageRef"
          :src="modelValue"
          fit="cover"
          class="preview-image"
          :preview-src-list="[modelValue]"
          preview-teleported
        >
          <template #error>
            <div class="image-error">
              <el-icon><Picture /></el-icon>
              <span>加载失败</span>
            </div>
          </template>
        </el-image>
        <div class="image-actions">
          <el-icon class="action-icon" @click="handlePreview"><ZoomIn /></el-icon>
          <el-icon class="action-icon" @click="handleRemove"><Delete /></el-icon>
        </div>
      </div>

      <!-- 无图片时显示上传框 -->
      <el-upload
        v-else
        ref="uploadRef"
        class="uploader"
        :action="uploadAction"
        :show-file-list="false"
        :before-upload="handleBeforeUpload"
        :http-request="handleUpload"
        :accept="acceptTypes"
        :disabled="disabled || uploading"
        drag
      >
        <div class="upload-content">
          <el-icon v-if="!uploading" class="upload-icon"><Plus /></el-icon>
          <el-progress
            v-else
            type="circle"
            :percentage="uploadProgress"
            :width="50"
          />
          <div class="upload-text">
            {{ uploading ? '上传中...' : placeholder }}
          </div>
        </div>
      </el-upload>
    </div>

    <!-- 错误提示 -->
    <div v-if="errorMessage" class="upload-error-message">
      <el-icon><WarningFilled /></el-icon>
      <span>{{ errorMessage }}</span>
    </div>

    <!-- URL输入框（可选显示） -->
    <div v-if="showUrlInput" class="url-input-wrapper">
      <el-input
        v-model="urlInputValue"
        :placeholder="urlPlaceholder"
        :disabled="disabled"
        clearable
        @blur="handleUrlBlur"
        @keyup.enter="handleUrlConfirm"
      >
        <template #append>
          <el-button :disabled="!urlInputValue" @click="handleUrlConfirm">
            确定
          </el-button>
        </template>
      </el-input>
    </div>

    <!-- 提示信息 -->
    <div v-if="tip" class="upload-tip">{{ tip }}</div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ElMessage, type UploadRequestOptions } from 'element-plus'
import { Plus, Delete, ZoomIn, Picture, WarningFilled } from '@element-plus/icons-vue'
import { uploadFile } from '@/api/upload'

// 允许的图片格式
const ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp']
const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']

interface Props {
  /** 图片URL (v-model) */
  modelValue?: string
  /** 是否禁用 */
  disabled?: boolean
  /** 占位文字 */
  placeholder?: string
  /** URL输入框占位文字 */
  urlPlaceholder?: string
  /** 是否显示URL输入框 */
  showUrlInput?: boolean
  /** 接受的文件类型 */
  accept?: string
  /** 最大文件大小(MB) */
  maxSize?: number
  /** 提示文字 */
  tip?: string
  /** 上传接口地址（如果不使用默认接口） */
  uploadAction?: string
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  disabled: false,
  placeholder: '点击或拖拽上传',
  urlPlaceholder: '或输入图片URL',
  showUrlInput: true,
  accept: 'image/jpeg,image/png,image/gif,image/webp',
  maxSize: 10, // 默认10MB，与后端保持一致
  tip: '',
  uploadAction: '#'
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
  (e: 'change', value: string): void
  (e: 'upload-success', response: any): void
  (e: 'upload-error', error: any): void
}>()

// 状态
const uploading = ref(false)
const uploadProgress = ref(0)
const urlInputValue = ref('')
const errorMessage = ref('')
const imageRef = ref<InstanceType<typeof import('element-plus')['ElImage']>>()

// 计算属性
const acceptTypes = computed(() => props.accept)

// 监听外部值变化，同步到URL输入框
watch(() => props.modelValue, (val) => {
  if (val !== urlInputValue.value) {
    urlInputValue.value = val || ''
  }
  // 有值时清除错误信息
  if (val) {
    errorMessage.value = ''
  }
}, { immediate: true })

/**
 * 获取文件扩展名
 */
const getFileExtension = (filename: string): string => {
  const lastDot = filename.lastIndexOf('.')
  if (lastDot === -1) return ''
  return filename.substring(lastDot + 1).toLowerCase()
}

/**
 * 验证文件类型
 */
const validateFileType = (file: File): { valid: boolean; message: string } => {
  const extension = getFileExtension(file.name)
  const mimeType = file.type.toLowerCase()
  
  // 检查扩展名
  const isValidExtension = ALLOWED_EXTENSIONS.includes(extension)
  // 检查MIME类型
  const isValidMimeType = ALLOWED_MIME_TYPES.includes(mimeType)
  
  if (!isValidExtension && !isValidMimeType) {
    return {
      valid: false,
      message: `只支持 ${ALLOWED_EXTENSIONS.join('、')} 格式的图片`
    }
  }
  
  return { valid: true, message: '' }
}

/**
 * 验证文件大小
 */
const validateFileSize = (file: File): { valid: boolean; message: string } => {
  const fileSizeMB = file.size / 1024 / 1024
  
  if (fileSizeMB > props.maxSize) {
    return {
      valid: false,
      message: `文件大小不能超过 ${props.maxSize}MB，当前文件大小为 ${fileSizeMB.toFixed(2)}MB`
    }
  }
  
  return { valid: true, message: '' }
}

/**
 * 清除错误信息
 */
const clearError = () => {
  errorMessage.value = ''
}

// 上传前校验
const handleBeforeUpload = (file: File): boolean => {
  clearError()
  
  // 验证文件类型
  const typeValidation = validateFileType(file)
  if (!typeValidation.valid) {
    errorMessage.value = typeValidation.message
    ElMessage.error(typeValidation.message)
    return false
  }

  // 验证文件大小
  const sizeValidation = validateFileSize(file)
  if (!sizeValidation.valid) {
    errorMessage.value = sizeValidation.message
    ElMessage.error(sizeValidation.message)
    return false
  }

  return true
}

// 自定义上传
const handleUpload = async (options: UploadRequestOptions) => {
  const file = options.file as File
  uploading.value = true
  uploadProgress.value = 0
  clearError()

  try {
    const res = await uploadFile(file, (percent) => {
      uploadProgress.value = percent
    })

    if (res.code === 0 && res.data?.url) {
      const url = res.data.url
      emit('update:modelValue', url)
      emit('change', url)
      emit('upload-success', res.data)
      urlInputValue.value = url
      ElMessage.success('上传成功')
    } else {
      // 处理业务错误
      const errMsg = res.message || '上传失败，请重试'
      throw new Error(errMsg)
    }
  } catch (error: any) {
    console.error('上传失败:', error)
    
    // 解析错误信息
    let errMsg = '上传失败，请重试'
    if (error.response?.data?.message) {
      // 后端返回的错误信息
      errMsg = error.response.data.message
    } else if (error.message) {
      errMsg = error.message
    }
    
    // 特殊错误处理
    if (error.code === 'ECONNABORTED' || error.message?.includes('timeout')) {
      errMsg = '上传超时，请检查网络后重试'
    } else if (error.message?.includes('Network Error')) {
      errMsg = '网络错误，请检查网络连接'
    }
    
    errorMessage.value = errMsg
    emit('upload-error', error)
    ElMessage.error(errMsg)
  } finally {
    uploading.value = false
    uploadProgress.value = 0
  }
}

// 预览图片
const handlePreview = () => {
  // 手动触发 el-image 的预览功能
  imageRef.value?.$el?.querySelector('img')?.click()
}

// 删除图片
const handleRemove = () => {
  emit('update:modelValue', '')
  emit('change', '')
  urlInputValue.value = ''
  clearError()
}

// URL输入框失焦
const handleUrlBlur = () => {
  // 可以在这里做URL格式校验
}

// 确认URL输入
const handleUrlConfirm = () => {
  const url = urlInputValue.value.trim()
  if (url) {
    clearError()
    emit('update:modelValue', url)
    emit('change', url)
  }
}
</script>

<style scoped>
.image-upload {
  width: 100%;
}

.upload-area {
  width: 120px;
  height: 120px;
}

.image-preview-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  border: 1px solid var(--el-border-color);
  border-radius: 6px;
  overflow: hidden;
}

.preview-image {
  width: 100%;
  height: 100%;
}

.image-actions {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  background: rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity 0.3s;
}

.image-preview-wrapper:hover .image-actions {
  opacity: 1;
}

.action-icon {
  font-size: 20px;
  color: #fff;
  cursor: pointer;
  transition: transform 0.2s;
}

.action-icon:hover {
  transform: scale(1.2);
}

.image-error {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: var(--el-text-color-placeholder);
  background: var(--el-fill-color-light);
}

.image-error .el-icon {
  font-size: 28px;
  margin-bottom: 4px;
}

.image-error span {
  font-size: 12px;
}

.uploader {
  width: 100%;
  height: 100%;
}

:deep(.uploader .el-upload) {
  width: 100%;
  height: 100%;
}

:deep(.uploader .el-upload-dragger) {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0;
  border-radius: 6px;
}

.upload-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.upload-icon {
  font-size: 28px;
  color: var(--el-text-color-placeholder);
  margin-bottom: 8px;
}

.upload-text {
  font-size: 12px;
  color: var(--el-text-color-placeholder);
  text-align: center;
  line-height: 1.4;
}

.upload-error-message {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
  padding: 4px 8px;
  font-size: 12px;
  color: var(--el-color-danger);
  background-color: var(--el-color-danger-light-9);
  border-radius: 4px;
  max-width: 300px;
}

.upload-error-message .el-icon {
  flex-shrink: 0;
}

.url-input-wrapper {
  margin-top: 8px;
  width: 100%;
  max-width: 300px;
}

.upload-tip {
  margin-top: 4px;
  font-size: 12px;
  color: var(--el-text-color-placeholder);
}
</style>
