<script lang="ts" setup>
import { PropType, reactive, Ref, ref, toRefs } from 'vue';
import type { UploadFile } from 'element-plus/es/components/upload/src/upload';
import { IUploadConfig } from '@/model/base-interface';
import $http from '@/utils/http-service';
import { genFileId } from 'element-plus';

const props = defineProps({
  data: {
    type: Object as PropType<IUploadConfig>,
    required: true,
    default: () => {
      return {};
    }
  },
  fileList: {
    type: Array,
    default: () => {
      return [];
    }
  },
  disabled: {
    type: Boolean,
    default: () => false
  }
});

const { data, fileList } = toRefs(props);
const uploadConfig = reactive(data.value);
interface RawFile {
  name: string;
  url: string;
}
const fileItem: Ref<UploadFile | null> = ref(null);
const upload = ref();
const isError = ref(false);
const errorMsg = ref('');
const handleSuccess = (response: any, file: UploadFile, list: UploadFile[]) => {
  if (uploadConfig.onSuccess) {
    uploadConfig.onSuccess(response, file, list);
  }
};
const handleError = (error: any, file: UploadFile, list: UploadFile[]) => {
  isError.value = true;
  if (uploadConfig.onError) {
    uploadConfig.onError(error, file, list);
  }
};

const handleChange = (file: UploadFile, list: UploadFile[]) => {
  if (file.status === 'ready' && uploadConfig.onAddItem) {
    fileItem.value = file;
    isError.value = false;
    errorMsg.value = '';
    isError.value = !uploadConfig.onAddItem(file, list, errorMsg, upload.value);
    if (isError.value) {
    } else {
      if (uploadConfig.onAddItemSuccess) {
        uploadConfig.onAddItemSuccess(file);
      }
    }
  }
};
const handleExceed = (files: UploadFile[]) => {
  if (uploadConfig.onExceed) {
    upload.value!.clearFiles();
    const file = files[0] as UploadRawFile;
    file.uid = genFileId();
    upload.value!.handleStart(file);
    uploadConfig.onExceed(files);
  }
};
const handleRemove = (file: UploadFile, list: UploadFile[]) => {
  if (uploadConfig.limit === 1) {
    isError.value = false;
    errorMsg.value = '';
  }
  if (uploadConfig.onRemove) {
    uploadConfig.onRemove(file, list);
  }
};
const handleBeforeUpload = (file: UploadFile) => {
  if (uploadConfig.onBeforeUpload) {
    const result = Boolean(uploadConfig.onBeforeUpload(file)) || false;
    return !result;
  }
  return true;
};
const handleBeforeRemove = (file: UploadFile, list: UploadFile[]) => {
  if (uploadConfig.onBeforeRemove) {
    uploadConfig.onBeforeRemove(file, list);
  }
};

const handleRequest = (param: UploadFile) => {
  if (uploadConfig.onHttpRequest) {
    uploadConfig.onHttpRequest(param);
  }
};
const customUpload = (options: any): Promise<any> => {
  return new Promise((resolve, reject) => {
    let header = {
      headers: {}
    };
    header.headers = uploadConfig.headers;
    const url = uploadConfig.action as string;
    const param = options.formData;
    if (uploadConfig.isCustomUpload) {
      $http
        .post(url, param, header)
        .then(res => {
          resolve(res);
        })
        .catch(error => {
          reject(error);
        });
    } else {
      reject(new Error('failed'));
    }
  });
};
defineExpose({
  clear: () => {
    if (fileItem.value !== null) {
      upload.value.handleRemove(fileItem.value);
    }
  },
  setError: (msg: string) => {
    isError.value = true;
    errorMsg.value = msg;
  },
  clearError: () => {
    isError.value = false;
    errorMsg.value = '';
  },
  customUpload
});
</script>

<template>
  <div class="multi-file-upload">
    <el-upload
      :id="uploadConfig.id || 'fileUpload'"
      ref="upload"
      :multiple="uploadConfig.multiple"
      :limit="uploadConfig.limit"
      :show-file-list="uploadConfig.showFileList || true"
      :disabled="disabled"
      :action="uploadConfig.action"
      :name="uploadConfig.name"
      :file-list="fileList"
      :auto-upload="uploadConfig.isAutoUpload"
      :accept="uploadConfig.accept"
      :on-success="handleSuccess"
      :on-exceed="handleExceed"
      :on-error="handleError"
      :on-remove="handleRemove"
      :on-change="handleChange"
      :before-upload="handleBeforeUpload"
      :before-remove="handleBeforeRemove"
      :http-request="handleRequest"
    >
      <div class="upload-button" :class="{ disabled: disabled }" :disabled="disabled">
        {{ $t('ADD_FILE_BTN') }}
      </div>
      <template #tip>
        <div class="el-upload__tip">{{ uploadConfig.tip }}</div>
      </template>
    </el-upload>
    <span v-if="isError && errorMsg" :id="uploadConfig.errorMsgId" class="error-text">
      {{ errorMsg }}
    </span>
  </div>
</template>

<style lang="scss" scoped>
.upload-button {
  color: var(--o-color-primary);
  &.disabled {
    color: var(--o-text-color-tertiary);
  }
}
.error-text {
  color: var(--o-color-danger);
}
:deep(.el-upload-list__item.is-success .el-upload-list__item-status-label) {
  top: 0;
}
.el-upload-list__item :hover {
  background-color: #fdfeff;
}
</style>