<template>
  <div v-loading="loading" class="oss-file-preview">
    <div v-if="imageFiles.length" class="oss-file-preview__images">
      <div v-for="(file, index) in imageFiles" :key="file.ossId || index" class="oss-file-preview__item">
        <el-image
          :src="file.url"
          fit="cover"
          :style="{ width: thumbSize, height: thumbSize }"
          :preview-src-list="imagePreviewList"
          :initial-index="index"
          preview-teleported
        >
          <template #error>
            <div class="oss-file-preview__error">
              <el-icon><picture-filled /></el-icon>
            </div>
          </template>
        </el-image>
        <span v-if="showFileName" class="oss-file-preview__name" :title="getDisplayName(file)">{{ getDisplayName(file) }}</span>
      </div>
    </div>

    <ul v-if="otherFiles.length && !imageOnly" class="oss-file-preview__files">
      <li v-for="file in otherFiles" :key="file.ossId" class="oss-file-preview__file-item">
        <el-icon><document /></el-icon>
        <el-link type="primary" :underline="false" @click="handleDownload(file)">{{ getDisplayName(file) }}</el-link>
      </li>
    </ul>

    <span v-if="!loading && !fileList.length" class="oss-file-preview__empty">{{ emptyText }}</span>
  </div>
</template>

<script setup lang="ts">
import { listByIds } from '@/api/system/oss';
import type { OssVO } from '@/api/system/oss/types';
import { isImageOssFile, parseOssIds } from '@/utils/ossPreview';
import { propTypes } from '@/utils/propTypes';

const props = defineProps({
  /** OSS 文件 ID，支持逗号分隔字符串、单个 ID 或 ID 数组 */
  ossIds: {
    type: [String, Number, Array],
    default: ''
  },
  /** 缩略图尺寸 */
  thumbSize: propTypes.string.def('80px'),
  /** 是否仅展示图片 */
  imageOnly: propTypes.bool.def(false),
  /** 是否显示文件名 */
  showFileName: propTypes.bool.def(false),
  /** 无附件时的提示文案 */
  emptyText: propTypes.string.def('暂无附件')
});

const { proxy } = getCurrentInstance() as ComponentInternalInstance;

const loading = ref(false);
const fileList = ref<OssVO[]>([]);

const imageFiles = computed(() => fileList.value.filter((file) => isImageOssFile(file)));
const otherFiles = computed(() => fileList.value.filter((file) => !isImageOssFile(file)));
const imagePreviewList = computed(() => imageFiles.value.map((file) => file.url));

const getDisplayName = (file: OssVO) => file.originalName || file.fileName || '未命名文件';

const loadFiles = async (value?: string | number | Array<string | number>) => {
  const ids = parseOssIds(value);
  if (!ids.length) {
    fileList.value = [];
    return;
  }
  loading.value = true;
  try {
    const res = await listByIds(ids.join(','));
    fileList.value = res.data || [];
  } catch (error) {
    console.error('加载附件预览失败:', error);
    fileList.value = [];
  } finally {
    loading.value = false;
  }
};

const handleDownload = (file: OssVO) => {
  if (file.ossId) {
    proxy?.$download.oss(file.ossId);
  }
};

watch(
  () => props.ossIds,
  (val) => {
    loadFiles(val);
  },
  { immediate: true }
);
</script>

<style lang="scss" scoped>
.oss-file-preview {
  min-height: 32px;
}

.oss-file-preview__images {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.oss-file-preview__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  max-width: 120px;
}

.oss-file-preview__name {
  width: 100%;
  font-size: 12px;
  color: #606266;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.oss-file-preview__error {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: #909399;
  font-size: 24px;
  background: #f5f7fa;
}

.oss-file-preview__files {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}

.oss-file-preview__file-item {
  display: flex;
  align-items: center;
  gap: 6px;
  line-height: 28px;
  color: #606266;
}

.oss-file-preview__empty {
  color: #909399;
  font-size: 13px;
}

:deep(.el-image) {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  cursor: pointer;
}
</style>
