<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, Loading } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'
import { uploadApi } from '@/api/upload'

const model = defineModel<string>({ default: '' })

const props = withDefaults(defineProps<{
  width?: number
  height?: number
  shape?: 'square' | 'circle'
  label?: string
}>(), {
  width: 80,
  height: 80,
  shape: 'square',
  label: '点击上传',
})

const uploading = ref(false)
const previewVisible = ref(false)

const customUpload: UploadProps['httpRequest'] = async (options) => {
  const file = options.file as File
  uploading.value = true
  try {
    const result = await uploadApi.uploadImage(file)
    model.value = result.url
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || '上传失败')
  } finally {
    uploading.value = false
  }
}

function removeImage() {
  model.value = ''
}

function onImgError() {
  console.warn('Image failed to load:', model.value)
}
</script>

<template>
  <div class="img-upload">
    <el-upload
      class="img-uploader"
      :show-file-list="false"
      :http-request="customUpload"
      accept="image/*"
    >
      <div v-if="model" class="img-preview-wrap" :style="{ width: width + 'px', height: height + 'px', borderRadius: shape === 'circle' ? '50%' : '8px' }">
        <img :src="model" class="img-preview-img" @click.stop="previewVisible = true" @error="onImgError" />
        <div class="img-overlay">
          <span @click.stop="previewVisible = true">预览</span>
          <span @click.stop="removeImage">删除</span>
        </div>
      </div>
      <div v-else class="img-placeholder" :style="{ width: width + 'px', height: height + 'px', borderRadius: shape === 'circle' ? '50%' : '8px' }">
        <el-icon v-if="!uploading" :size="20"><Plus /></el-icon>
        <el-icon v-else :size="20" class="is-loading"><Loading /></el-icon>
        <span class="img-placeholder-text">{{ uploading ? '上传中' : label }}</span>
      </div>
    </el-upload>

    <el-image-viewer v-if="previewVisible" :url-list="[model]" @close="previewVisible = false" />
  </div>
</template>

<style scoped>
.img-upload {
  display: inline-block;
}

.img-uploader {
  display: inline-block;
}

.img-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  border: 1px dashed #d9d9d9;
  background: #fafafa;
  color: #a8abb2;
  cursor: pointer;
  transition: border-color 0.2s;
  overflow: hidden;
}

.img-placeholder:hover {
  border-color: var(--brand-color, #ff6800);
  color: var(--brand-color, #ff6800);
}

.img-placeholder-text {
  font-size: 12px;
}

.img-preview-wrap {
  position: relative;
  overflow: hidden;
  cursor: pointer;
}

.img-preview-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.img-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  opacity: 0;
  transition: opacity 0.2s;
}

.img-preview-wrap:hover .img-overlay {
  opacity: 1;
}

.img-overlay span {
  color: #fff;
  font-size: 13px;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.15);
}

.img-overlay span:hover {
  background: rgba(255, 255, 255, 0.3);
}

.is-loading {
  animation: rotating 1.5s linear infinite;
}

@keyframes rotating {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
</style>
