<template>
  <div class="resource-upload">
    <div class="resource-upload__wrapper">
      <el-button type="primary" class="relative !text-white">
        选择文件
        <input
          ref="inputRef"
          class="absolute top-0 left-0 cursor-pointer opacity-0"
          type="file"
          multiple
          accept="image/*,video/*"
          @change="onFilesChange"
        />
      </el-button>
    </div>

    <div v-if="fileList.length" class="image-list">
      <div v-for="item in fileList" :key="item.id" class="image-item">
        <img
          v-if="item.fileType === 'image'"
          :src="item.url"
          class="image-item-media"
          alt="preview"
          @click="handlePictureCardPreview(item)"
        />
        <video
          v-else
          :src="item.url"
          class="image-item-media"
          @click="handlePictureCardPreview(item)"
        />
        <div class="meta">
          <span class="name" :title="item.name">{{ item.name }}</span>
          <el-button link type="danger" size="small" @click="remove(item.id)">移除</el-button>
        </div>
      </div>
    </div>
    <el-dialog v-model="showReviewImgDialog" @close="onDialogClose">
      <img w-full v-if="reviewImg.fileType === 'image'" :src="reviewImg.url" alt="Preview Image" />
      <video v-else ref="reviewVideoRef" :src="reviewImg.url" autoplay />
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
interface PreviewItem {
  id: number
  name: string
  url: string
  fileType: 'image' | 'video'
}

const emit = defineEmits<{
  (e: 'change', files: File[]): void
}>()

const inputRef = ref<HTMLInputElement | null>(null)
const fileList = ref<PreviewItem[]>([])

const formData = ref([])

const onFilesChange = (e: Event) => {
  const input = e.target as HTMLInputElement
  const files = Array.from(input.files || [])
  if (!files.length) return
  files.forEach((file: any) => {
    const url = URL.createObjectURL(file)
    formData.value.push(file)
    const fileType: 'image' | 'video' = file.type.startsWith('image') ? 'image' : 'video'
    fileList.value.push({ id: Math.random(), name: file.name, url, fileType })
  })
  // reset input so selecting the same files again will still trigger change
  if (inputRef.value) inputRef.value.value = ''
  emit('change', files)
}

const remove = (id: number) => {
  const idx = fileList.value.findIndex((x) => x.id === id)
  if (idx === -1) return
  const [removed] = fileList.value.splice(idx, 1)
  formData.value.splice(idx, 1)
  if (removed?.url && objectUrls.has(removed.url)) {
    URL.revokeObjectURL(removed.url)
  }
}

const showReviewImgDialog = ref(false)
const reviewImg = ref({ url: '', fileType: '' })
const handlePictureCardPreview = (item: { url: string; fileType: 'image' | 'video' }) => {
  reviewImg.value = item
  showReviewImgDialog.value = true
}

const reviewVideoRef = ref<HTMLVideoElement | null>(null)
const onDialogClose = () => {
  const video = reviewVideoRef.value
  if (video) {
    try {
      video.pause()
      video.currentTime = 0
    } catch (e) {
      console.error(e)
    }
  }
}
</script>

<style scoped lang="scss">
.resource-upload {
  .image-list {
    margin-top: 12px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 12px;
  }

  .image-item {
    border: 1px solid #ebeef5;
    border-radius: 6px;
    background: #fff;
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;

    .image-item-media {
      width: 100%;
      aspect-ratio: 16 / 9;
      object-fit: cover;
      border-radius: 4px;
      background: #f5f7fa;
    }

    .meta {
      display: flex;
      align-items: center;
      gap: 8px;
      .name {
        flex: 1;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 12px;
        color: #606266;
      }
    }
  }
}
</style>
