<template>
  <div class="file-upload">
    <el-upload
      ref="uploadRef"
      :action="uploadUrl"
      :headers="headers"
      :data="uploadDataDict"
      :show-file-list="false"
      :auto-upload="autoUpload"
      :http-request="customRequest"
      :disabled="disabled"
      :before-upload="handleBeforeUpload"
      :accept="accept"
      :multiple="multiple"
      :on-exceed="handleExceededSize"
      @change="handleFileChange"
      @error="handleError"
      @success="handleSuccess"
    >
      <template #trigger>
        <el-button type="primary" :disabled="loading">{{ btnText }}</el-button>
        <!-- <el-button
          v-if="!autoUpload"
          type="primary"
          :loading="loading"
          :disabled="!canUpload"
          @click.stop="startUpload"
          >开始上传</el-button
        > -->
      </template>
    </el-upload>
  </div>
</template>

<script setup lang="ts">
  import { ref } from 'vue';
  import { fileMD5 } from '@/utils/md5';
  import { ElMessage } from 'element-plus';
  import type {
    UploadProps,
    UploadRequestOptions,
    UploadFile,
    UploadFiles,
    UploadRawFile,
    UploadProgressEvent,
  } from 'element-plus';
  import axios, { AxiosHeaders } from 'axios';

  defineOptions({
    name: 'UploadButton',
  });

  const props = withDefaults(
    defineProps<{
      uploadUrl: string;
      uploadData?: Record<string, any>;
      maxSize?: number;
      uploadFileAlias?: string;
      autoUpload?: boolean;
      disabled?: boolean;
      btnText?: string;
      accept?: string;
      multiple?: boolean;
    }>(),
    {
      uploadUrl: '',
      uploadData: () => {
        return {};
      },
      maxSize: 20 * 1024 * 1024,
      uploadFileAlias: 'file',
      autoUpload: true,
      disabled: false,
      btnText: '选择',
      accept: '.xls,.xlsx',
      multiple: false,
    }
  );

  const emit = defineEmits([
    'uploading',
    'uploadError',
    'uploadSuccess',
    'validError',
  ]);

  const uploadRef = ref();
  const attachmentName = ref('');
  const canUpload = ref(false);
  const uploadDataDict = ref({});
  const headers = ref({ md5: '' });
  const result = ref({ success: true, message: '' });
  const loading = ref(false);

  function startUpload() {
    loading.value = true;
    uploadRef.value?.submit();
  }

  function handleFileChange(uploadFile: UploadFile, uploadFiles: UploadFiles) {
    if (props.autoUpload || !uploadFiles.length) return;
    // Element Plus's status: ready, uploading, success, fail
    // Arco's status: init, uploading, success, error
    // We'll assume 'ready' is similar to 'init' for this logic, though direct mapping might not be perfect.
    canUpload.value = uploadFiles[0]?.status === 'ready';
  }

  async function handleBeforeUpload(rawFile: UploadRawFile) {
    uploadDataDict.value = {
      ...props.uploadData,
      filename: rawFile.name,
    };

    if (rawFile.size > props.maxSize) {
      // Element Plus uses on-exceed for this, but we can also check here
      // For consistency with original logic, we call handleExceededSize and reject
      // However, on-exceed will also be triggered if :limit is set for file count, not size directly.
      // Here, we manually trigger the message and prevent upload.
      const content = `文件大小不能超过${Math.floor(
        props.maxSize / 1024 / 1024
      )}MB`;
      ElMessage.error(content);
      result.value = {
        success: false,
        message: content,
      };
      emit('validError', result.value);
      return Promise.reject(new Error(content));
    }

    const md5 = await fileMD5(rawFile);
    headers.value.md5 = md5;

    if (props.autoUpload) loading.value = true;

    return true;
  }

  function customRequest(options: UploadRequestOptions) {
    // Changed return type to any
    const { onProgress, file, data } = options;

    const formData = new FormData();
    const paramData: Record<string, any> = data || {};
    Object.entries(paramData).forEach(([k, v]) => {
      formData.append(k, v);
    });
    formData.append(props.uploadFileAlias, file as File);
    emit('uploading');

    return axios.post(options.action, formData, {
      headers: options.headers as AxiosHeaders,
      onUploadProgress: ({ loaded, total }) => {
        onProgress({
          percent: total ? Math.floor((100 * loaded) / total) : 0,
        } as UploadProgressEvent);
      },
    });
  }

  function handleError(
    error: Error,
    uploadFile: UploadFile,
    uploadFiles: UploadFiles
  ) {
    canUpload.value = false;
    loading.value = false;
    result.value = {
      success: false,
      message: error.message || '上传失败',
    };
    ElMessage.error(result.value.message);
    emit('uploadError', result.value);
  }
  function handleSuccess(
    response: any,
    uploadFile: UploadFile,
    uploadFiles: UploadFiles
  ) {
    canUpload.value = false;
    loading.value = false;
    result.value = {
      success: true,
      message: '上传成功！',
    };
    ElMessage.success('上传成功！');
    emit('uploadSuccess', {
      ...result.value,
      filename: uploadFile.name,
      response,
    });
  }

  function handleExceededSize(files: File[]) {
    // This function is now primarily called by el-upload's on-exceed prop
    // The before-upload also has a check, this is a fallback or for multiple files if `limit` (count) is exceeded.
    const file = files[0]; // Assuming single file upload context for this message
    const content = `文件 ${file.name} 大小超过限制 (${Math.floor(
      props.maxSize / 1024 / 1024
    )}MB)`;
    result.value = {
      success: false,
      message: content,
    };
    loading.value = false;
    ElMessage.error(content);
    emit('validError', result.value);
  }
</script>

<style lang="less">
  .file-upload {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    .arco-upload-hide {
      display: inline-block;
    }
    .el-input__wrapper {
      flex-grow: 2;
      margin-right: 10px;
    }
    .arco-upload {
      flex-grow: 0;
      flex-shrink: 0;
    }
  }
</style>
