<template>
  <div class="image-upload-container">
    <div
      class="upload-box relative flex items-center justify-center overflow-hidden rounded-lg border border-dashed border-[var(--el-border-color)] bg-[var(--el-fill-color-lighter)] transition-all hover:border-[var(--el-color-primary)]"
      :style="{ width: boxWidth, height: boxHeight }"
    >
      <!-- 1. 已有图片展示 -->
      <template v-if="modelValue">
        <ElImage
          :src="modelValue"
          fit="cover"
          class="h-full w-full"
          :preview-src-list="[modelValue]"
          preview-teleported
        />
        <!-- 遮罩操作层 -->
        <div
          class="action-mask absolute inset-0 flex items-center justify-center bg-black/40 opacity-0 transition-opacity hover:opacity-100"
        >
          <div class="flex gap-3">
            <ElButton circle type="primary" :icon="Edit" @click="handleTriggerUpload" />
            <ElButton circle type="danger" :icon="Delete" @click="handleRemove" />
          </div>
        </div>
      </template>

      <!-- 2. 未上传状态 -->
      <div
        v-else
        class="flex cursor-pointer flex-col items-center justify-center gap-2 p-4 text-[var(--el-text-color-secondary)] hover:text-[var(--el-color-primary)]"
        @click="handleTriggerUpload"
      >
        <ElIcon :size="24" v-loading="isUploading">
          <Plus v-if="!isUploading" />
        </ElIcon>
        <span class="text-xs">{{ placeholder || t('common.uploadImage') }}</span>
      </div>
    </div>

    <!-- 3. 提示信息 -->
    <div v-if="tip" class="mt-2 text-xs text-[var(--el-text-color-placeholder)]">
      {{ tip }}
    </div>

    <!-- 隐藏的原始 Input -->
    <input
      ref="fileInputRef"
      type="file"
      class="hidden"
      :accept="accept"
      @change="handleFileChange"
    />
  </div>
</template>

<script setup lang="ts">
  import { ref } from 'vue'
  import { useI18n } from 'vue-i18n'
  import { ElImage, ElButton, ElIcon, ElMessage } from 'element-plus'
  import { Plus, Edit, Delete } from '@element-plus/icons-vue'
  import { fetchUploadFile } from '@/api/files'

  defineOptions({ name: 'ImageUpload' })

  // 1. 定义 Props
  interface Props {
    modelValue?: string // 图片 URL
    uploadType?: Api.Files.UploadFileType // 后端要求的文件分类
    accept?: string // 接受的文件类型
    boxWidth?: string // 容器宽度
    boxHeight?: string // 容器高度
    placeholder?: string // 未上传时的占位文字
    tip?: string // 下方的提示文字
    maxSize?: number // 最大体积 (MB)，默认 2MB
  }

  const props = withDefaults(defineProps<Props>(), {
    modelValue: '',
    uploadType: 'other',
    accept: 'image/jpeg,image/png,image/webp',
    boxWidth: '120px',
    boxHeight: '120px',
    maxSize: 2
  })

  // 2. 定义 Emits
  const emit = defineEmits<{
    (e: 'update:modelValue', value: string): void
    (e: 'success', value: Api.Files.FileUploadResponse): void
    (e: 'change', value: string): void
  }>()

  const { t } = useI18n()

  // 3. 内部状态
  const fileInputRef = ref<HTMLInputElement | null>(null)
  const isUploading = ref(false)

  /** 触发文件选择 */
  const handleTriggerUpload = () => {
    if (isUploading.value) return
    fileInputRef.value?.click()
  }

  /** 处理文件选择变更 */
  const handleFileChange = async (event: Event) => {
    const target = event.target as HTMLInputElement
    const file = target.files?.[0]
    if (!file) return

    // 1. 基础校验 (大小)
    if (file.size > props.maxSize * 1024 * 1024) {
      ElMessage.warning(t('common.fileTooLarge', { size: props.maxSize }))
      target.value = ''
      return
    }

    // 2. 上传流程
    isUploading.value = true
    try {
      const res = await fetchUploadFile(file, props.uploadType)
      if (res.url) {
        emit('update:modelValue', res.url)
        emit('success', res)
        emit('change', res.url)
      }
    } catch (error) {
      console.error('Image Upload Error:', error)
    } finally {
      isUploading.value = false
      target.value = '' // 清空 input 以便下次选择同一张图
    }
  }

  /** 移除图片 */
  const handleRemove = () => {
    emit('update:modelValue', '')
    emit('change', '')
  }
</script>

<style lang="scss" scoped>
  .image-upload-container {
    display: inline-block;
    vertical-align: top;
  }
</style>
