<template>
  <div class="file-list">
    <div class="file-grid">
      <div v-for="file in files" :key="file.id" class="file-item">
        <div class="file-info">
          <div v-if="isImageType(file.name)">
            <img :src="file.url" class="file-thumb" />
          </div>
          <div v-else class="file-icon-wrapper" :class="getFileTypeClass(file.name)">
            <a-icon :type="getFileIcon(file.name)" class="file-icon" />
          </div>
          <div class="file-content">
            <div class="file-header">
              <span class="file-name">{{ file.real_name ? file.real_name : file.name }}</span>
              <span class="file-type">{{ getFileType(file.name) }}</span>
            </div>
            <div class="file-footer">
              <span class="file-size" v-if="file.size">{{ formatFileSize(file.size) }}</span>
              <span class="file-time" v-if="file.upload_time">{{ file.upload_time }}</span>
            </div>
            <div class="file-audio-progress" v-if="isAudioFile(file)">
              <a-slider
                :min="0"
                :max="audioDurations[file.id] || 0"
                :step="0.1"
                :tip-formatter="formatDuration"
                :value="audioCurrentTimes[file.id] || 0"
                @change="handleAudioSeek(file.id, $event)"
              />
              <div class="file-audio-progress-text">
                <span>{{ formatDuration(audioCurrentTimes[file.id]) }}</span>
                <span class="sep">/</span>
                <span>{{ formatDuration(audioDurations[file.id]) }}</span>
              </div>
            </div>
          </div>
        </div>
        <div class="file-actions">
          <a-tooltip :title="isAudioFile(file) ? (isPlaying(file.id) ? '暂停' : '播放') : '预览文件'">
            <a-button type="link" class="action-btn preview-btn" @click="handlePreview(file)">
              <a-icon :type="isAudioFile(file) ? (isPlaying(file.id) ? 'pause-circle' : 'play-circle') : 'eye'" />
            </a-button>
          </a-tooltip>
          <a-tooltip v-if="downloadable" title="下载文件">
            <a-button type="link" class="action-btn download-btn" @click="download(file)">
              <a-icon type="download" />
            </a-button>
          </a-tooltip>
        </div>
        <!-- 隐藏的 audio 元素用于播放音频 -->
        <audio
          v-if="isAudioFile(file)"
          :ref="`audio-${file.id}`"
          :src="file.url"
          style="display: none;"
          @loadedmetadata="handleAudioLoadedMetadata(file.id)"
          @timeupdate="handleAudioTimeUpdate(file.id)"
          @ended="handleAudioEnded(file.id)"
        />
      </div>
    </div>
    <!-- 文件预览弹窗 -->
    <a-modal
      v-model="previewVisible"
      :footer="null"
      :dialog-style="{ top: '20px' }"
      width="85%"
      :z-index="1001"
      title="文件预览"
      @cancel="handlePreviewClose"
    >
      <file-preview :path="previewPath" />
    </a-modal>
  </div>
</template>

<script>
import FilePreview from '@vue2-client/components/FilePreview'

export default {
  name: 'FileImageItem',
  components: {
    FilePreview
  },
  props: {
    files: {
      type: Array,
      required: true
    },
    downloadable: {
      type: Boolean,
      required: false,
      default: true
    }
  },
  data () {
    return {
      previewVisible: false,
      previewPath: '',
      playingAudios: {}, // 记录正在播放的音频文件ID
      audioDurations: {}, // 秒：录音时长
      audioCurrentTimes: {} // 秒：当前播放进度
    }
  },
  methods: {
    handlePreview (file) {
      // 如果是音频文件（f_type === 'VIDEO' 或文件名后缀是 m4a），处理播放/暂停
      if (this.isAudioFile(file)) {
        this.toggleAudioPlay(file)
        return
      }
      // 其他类型文件，正常预览
      this.previewPath = file.url
      this.previewVisible = true
    },
    isAudioFile (file) {
      // 判断是否是音频文件：f_type === 'VIDEO' 或文件名后缀是 m4a
      if (file.f_type === 'VIDEO') {
        return true
      }
      // 如果没有 f_type 字段，判断文件名后缀
      if (!file.f_type && file.name) {
        const ext = file.name.split('.').pop().toLowerCase()
        return ext === 'm4a'
      }
      return false
    },
    toggleAudioPlay (file) {
      const audioRef = this.$refs[`audio-${file.id}`]
      // 处理 ref 可能是数组或单个元素的情况
      const audio = Array.isArray(audioRef) ? audioRef[0] : audioRef
      if (!audio) return

      const isCurrentlyPlaying = this.playingAudios[file.id]

      if (isCurrentlyPlaying) {
        // 暂停播放
        audio.pause()
        this.$set(this.playingAudios, file.id, false)
      } else {
        // 停止其他正在播放的音频
        Object.keys(this.playingAudios).forEach(id => {
          if (this.playingAudios[id] && id !== file.id) {
            const otherAudioRef = this.$refs[`audio-${id}`]
            const otherAudio = Array.isArray(otherAudioRef) ? otherAudioRef[0] : otherAudioRef
            if (otherAudio) {
              otherAudio.pause()
              this.$set(this.playingAudios, id, false)
            }
          }
        })
        // 开始播放
        audio.play()
        this.$set(this.playingAudios, file.id, true)
      }
    },
    handleAudioEnded (fileId) {
      this.$set(this.playingAudios, fileId, false)
      this.$set(this.audioCurrentTimes, fileId, 0)
    },
    handleAudioLoadedMetadata (fileId) {
      const audioRef = this.$refs[`audio-${fileId}`]
      const audio = Array.isArray(audioRef) ? audioRef[0] : audioRef
      if (!audio) return
      const duration = Number.isFinite(audio.duration) ? audio.duration : 0
      this.$set(this.audioDurations, fileId, duration)
    },
    handleAudioTimeUpdate (fileId) {
      const audioRef = this.$refs[`audio-${fileId}`]
      const audio = Array.isArray(audioRef) ? audioRef[0] : audioRef
      if (!audio) return
      this.$set(this.audioCurrentTimes, fileId, audio.currentTime || 0)
    },
    handleAudioSeek (fileId, nextTime) {
      const audioRef = this.$refs[`audio-${fileId}`]
      const audio = Array.isArray(audioRef) ? audioRef[0] : audioRef
      if (!audio) return
      const safeTime = typeof nextTime === 'number' ? nextTime : 0
      audio.currentTime = safeTime
      this.$set(this.audioCurrentTimes, fileId, safeTime)
    },
    isPlaying (fileId) {
      return !!this.playingAudios[fileId]
    },
    handlePreviewClose () {
      this.previewVisible = false
      this.previewPath = ''
    },
    download (file) {
      const a = document.createElement('a')
      a.href = file.url
      a.download = file.name
      a.click()
    },
    formatFileSize (size) {
      if (!size) return ''
      // 如果小于1M，转换为KB显示
      if (size < 1) {
        const kbSize = size * 1024
        return `${kbSize.toFixed(1)} KB`
      }
      // 大于等于1M，保持M为单位
      return `${size.toFixed(1)} MB`
    },
    formatDuration (seconds) {
      const safeSeconds = Number.isFinite(seconds) ? seconds : 0
      const totalSeconds = Math.max(0, Math.floor(safeSeconds))
      const mm = String(Math.floor(totalSeconds / 60)).padStart(2, '0')
      const ss = String(totalSeconds % 60).padStart(2, '0')
      return `${mm}:${ss}`
    },
    getFileType (filename) {
      const ext = filename.split('.').pop().toLowerCase()
      const typeMap = {
        pdf: 'PDF文档',
        doc: 'Word文档',
        docx: 'Word文档',
        xls: 'Excel表格',
        xlsx: 'Excel表格',
        ppt: 'PPT演示',
        pptx: 'PPT演示',
        jpg: '图片',
        jpeg: '图片',
        png: '图片',
        gif: '图片',
        txt: '文本文件',
        zip: '压缩文件',
        rar: '压缩文件'
      }
      return typeMap[ext] || '文件'
    },
    getFileIcon (filename) {
      const ext = filename.split('.').pop().toLowerCase()
      const iconMap = {
        pdf: 'file-pdf',
        doc: 'file-word',
        docx: 'file-word',
        xls: 'file-excel',
        xlsx: 'file-excel',
        ppt: 'file-ppt',
        pptx: 'file-ppt',
        jpg: 'file-image',
        jpeg: 'file-image',
        png: 'file-image',
        gif: 'file-image',
        txt: 'file-text',
        zip: 'file-zip',
        rar: 'file-zip',
        m4a: 'right-circle',
      }
      return iconMap[ext] || 'file'
    },
    getFileTypeClass (filename) {
      const ext = filename.split('.').pop().toLowerCase()
      return `file-type-${ext}`
    },
    isImageType (filename) {
      const ext = filename.split('.').pop().toLowerCase()
      return ['jpg', 'jpeg', 'png', 'gif'].includes(ext)
    }
  }
}
</script>

<style lang="less" scoped>
.file-list {
  .file-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
    gap: 16px;
  }

  .file-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px;
    background: #fff;
    border-radius: 12px;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    border: 1px solid rgba(0, 0, 0, 0.06);

    &:hover {
      transform: translateY(-2px);
      border-color: @primary-2;
      background: rgba(24, 144, 255, 0.02);
    }

    .file-info {
      display: flex;
      align-items: center;
      flex: 1;
      min-width: 0;

      .file-icon-wrapper {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 48px;
        height: 48px;
        margin-right: 16px;
        border-radius: 12px;
        transition: all 0.3s;

        &.file-type-pdf {
          background: linear-gradient(135deg, #ff4d4f, #ff7875);
        }
        &.file-type-doc, &.file-type-docx {
          background: linear-gradient(135deg, #1890ff, #69c0ff);
        }
        &.file-type-xls, &.file-type-xlsx {
          background: linear-gradient(135deg, #52c41a, #95de64);
        }
        &.file-type-ppt, &.file-type-pptx {
          background: linear-gradient(135deg, #fa8c16, #ffc069);
        }
        &.file-type-jpg, &.file-type-jpeg, &.file-type-png, &.file-type-gif {
          background: linear-gradient(135deg, #722ed1, #b37feb);
        }
        &.file-type-txt, &.file-type-m4a {
          background: linear-gradient(135deg, #13c2c2, #5cdbd3);
        }
        &.file-type-zip, &.file-type-rar {
          background: linear-gradient(135deg, #eb2f96, #ff85c0);
        }

        .file-icon {
          font-size: 24px;
          color: #fff;
        }
      }

      .file-content {
        display: flex;
        flex-direction: column;
        min-width: 0;
        flex: 1;

        .file-header {
          display: flex;
          align-items: center;
          margin-bottom: 4px;

          .file-name {
            color: rgba(0, 0, 0, 0.85);
            font-size: 15px;
            font-weight: 500;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            margin-right: 8px;
            width: 0;
            flex: 1;
          }

          .file-type {
            color: rgba(0, 0, 0, 0.45);
            font-size: 12px;
            padding: 2px 6px;
            background: rgba(0, 0, 0, 0.04);
            border-radius: 4px;
          }
        }

        .file-footer {
          display: flex;
          align-items: center;
          color: rgba(0, 0, 0, 0.45);
          font-size: 12px;

          .file-size {
            margin-right: 12px;
          }

          .file-time {
            position: relative;
            padding-left: 6px;

            &::before {
              content: '';
              position: absolute;
              left: 0;
              top: 50%;
              transform: translateY(-50%);
              width: 4px;
              height: 4px;
              background: rgba(0, 0, 0, 0.25);
              border-radius: 50%;
            }
          }
        }

        .file-audio-progress {
          margin-top: 8px;

          :deep(.ant-slider) {
            margin: 0;
          }

          .file-audio-progress-text {
            margin-top: 4px;
            display: flex;
            align-items: center;
            justify-content: flex-end;
            color: rgba(0, 0, 0, 0.45);
            font-size: 12px;

            .sep {
              margin: 0 6px;
            }
          }
        }
      }
    }

    .file-actions {
      display: flex;
      align-items: center;
      margin-left: 6px;

      .action-btn {
        width: 36px;
        height: 36px;
        padding: 0;
        margin-left: 8px;
        border-radius: 8px;
        color: rgba(0, 0, 0, 0.45);
        background: transparent;
        transition: all 0.3s;

        &:hover {
          color: #fff;
          background: @primary-color;
          transform: scale(1.05);
        }

        .anticon {
          font-size: 16px;
        }
      }
    }
  }
}
.file-thumb {
  width: 48px;
  height: 48px;
  object-fit: cover;
  margin-right: 16px;
  border-radius: 12px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}
</style>
