<template>
  <div class="file-uploader">
    <el-upload
      class="file-uploader__upload"
      :http-request="customUploadRequest"
      :on-success="handleUploadSuccess"
      :on-remove="handleRemove"
      :file-list="fileList"
      list-type="picture-card"
      :limit="limit"
      :show-file-list="true"
      :auto-upload="true"
      :disabled="readonly"
      :accept="accept"
      @preview="handlePreview"
    >
      <el-icon v-if="fileList.length < limit"><Plus /></el-icon>
    </el-upload>
    <el-image-viewer v-if="previewShow" :url-list="previewList" :initial-index="previewIndex" @close="previewShow = false" />
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { CommonUpload } from '@/apis/index';

// 1. props & emit
const props = defineProps({
  modelValue: { type: [Array, String], default: () => [] },
  ossUrl: { type: String, default: 'http://gov-cloud.oss-cn-chengdu.aliyuncs.com/' },
  limit: { type: Number, default: 5 },
  accept: { type: String, default: 'image/*' },
  readonly: { type: Boolean, default: false },
});
const emit = defineEmits(['update:modelValue']);

// 2. 中间层 computed：统一成数组，写时根据 limit 决定发出数组还是字符串
const selectedFiles = computed({
  get() {
    // 回显：如果父传字符串且 limit===1，就把它当成长度 1 数组
    if (props.limit === 1 && typeof props.modelValue === 'string' && props.modelValue) {
      return [props.modelValue];
    }
    // 其他情况，确保数组
    return Array.isArray(props.modelValue) ? props.modelValue : [];
  },
  set(val) {
    // 内部操作后：如果单文件场景，传字符串；多文件场景，传数组
    if (props.limit === 1) {
      emit('update:modelValue', val.length ? val[0] : '');
    } else {
      emit('update:modelValue', val);
    }
  },
});

// 3. fileList & previewList 都基于 selectedFiles
const fileList = computed(() =>
  selectedFiles.value.map((path, idx) => ({
    name: `file_${idx}`,
    url: props.ossUrl + path,
    uid: `${idx}`,
  }))
);
const previewShow = ref(false);
const previewIndex = ref(0);
const previewList = computed(() => fileList.value.map((f) => f.url));

// 4. 上传 & 移除
const customUploadRequest = async ({ file, onSuccess, onError }) => {
  const formData = new FormData();
  formData.append('file', file);
  try {
    const res = await CommonUpload(formData);
    onSuccess(res, file);
  } catch (err) {
    onError(err);
  }
};
function handleUploadSuccess(res) {
  const relative = res.data?.url;
  if (!relative) return;
  // 推入中间层
  selectedFiles.value = [...selectedFiles.value, relative];
}
function handleRemove(file) {
  const rel = file.url.replace(props.ossUrl, '');
  selectedFiles.value = selectedFiles.value.filter((p) => p !== rel);
}

// 5. 预览
function handlePreview(file) {
  const idx = fileList.value.findIndex((item) => item.uid === file.uid);
  if (idx >= 0) {
    previewIndex.value = idx;
    previewShow.value = true;
  }
}
</script>

<style scoped>
.file-uploader {
  display: flex;
  flex-wrap: wrap;
}
.file-uploader__upload {
  margin-right: 16px;
}
</style>
