<template>
  <div v-if="visible">
    <div class="overlay"></div>
    <el-card class="pop-card">
      <template #header>
        <div style="font-size: 16px; font-weight: 600">批量导入</div>
        <el-icon :size="18" @click="handleMainClose" style="cursor: pointer">
          <Close />
        </el-icon>
      </template>
      <div class="upload-content">
        <el-upload
          ref="upload"
          style="width: 384px; height: 192px; border-radius: 5px"
          :headers="getHeaders()"
          :multiple="false"
          :limit="1"
          drag
          :action="importApiUrl"
          :data="props.data"
          :with-credentials="true"
          :auto-upload="false"
          :before-upload="beforeUpload"
          :on-success="handleUploadSuccess"
          :on-exceed="handleExceed"
          :on-change="handleChange"
          :on-remove="handleRemove"
        >
          <el-icon class="el-icon--upload" style="width: 33px; height: 42px; color: #409efc">
            <Document />
          </el-icon>
          <div class="el-upload__text">
            <div style="font-size: 12px; color: red; margin-bottom: 5px">请下载模板并按要求填写后上传</div>
            <div style="font-size: 16px">点击或将文件拖拽到这里上传</div>
            <div style="font-size: 12px; color: rgba(0, 0, 0, 0.45); margin-top: 5px"
              >文件支持.xlsx .xls格式，仅支持上传一个文件</div
            >
          </div>
        </el-upload>
        <div style="margin-top: 72px; display: flex; justify-content: flex-end">
          <el-button v-if="props.showTemplate" @click="handleDownloadTemplate">下载模板</el-button>
          <el-button type="primary" @click="handleImport" :disabled="isImportDisable">导入</el-button>
        </div>
      </div>
    </el-card>

    <el-dialog v-model="dialogVisibleErr" title="Warning" width="544" align-center :show-close="false">
      <template #header>
        <el-icon :size="24" color="#f2b20a" style="margin: 0 5px 2px">
          <WarnTriangleFilled />
        </el-icon>
        <div class="header-text">导入提示</div>
        <el-icon class="close-icon" :size="18" @click="handleErrorDialogClose"><Close /></el-icon>
      </template>
      <!-- 简单模式或 ImportResponseDataPerson 类型：显示字符串消息 -->
      <div v-if="props.responseType === 'simple' || isPersonResponseType" class="simple-message">
        {{ simpleMessage }}
      </div>
      <!-- 详细模式：显示统计和错误详情表格 -->
      <template v-else>
        <div class="sum-count">
          成功导入 <span class="succ-sum">{{ sucCount }}</span> 条， 失败 <span class="err-sum">{{ errCount }}</span> 条
        </div>
        <el-table :data="errDetail" style="width: 100%" height="190">
          <el-table-column prop="rowNum" label="行数" width="100" fixed align="center" />
          <el-table-column
            prop="failReason"
            label="失败原因"
            show-overflow-tooltip
            class-name="error-reason"
            label-class-name="error-reason-label"
          />
        </el-table>
      </template>
      <template #footer>
        <el-button type="primary" @click="handleBackToImport">重新导入 </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
  import { ref, watch } from 'vue';
  import axios, { AxiosRequestConfig } from 'axios';
  import { getHeaders } from '@/utils/http/axios';
  import { genFileId, ElMessage } from 'element-plus';
  import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
  import { Close, Document, WarnTriangleFilled } from '@element-plus/icons-vue';
  import type { BatchImportProps, ErrorDetailItem, ImportResponseData, ImportResponseDataPerson } from './types';

  const props = withDefaults(defineProps<BatchImportProps>(), {
    templateName: '下载模板',
    showTemplate: true,
    responseType: 'detailed',
  });

  const emit = defineEmits<{
    (e: 'close'): void;
    (e: 'update', data?: ImportResponseData | ImportResponseDataPerson | string): void;
  }>();

  const upload = ref<UploadInstance>();
  const isImportDisable = ref<boolean>(true);
  const dialogVisibleErr = ref<boolean>(false);
  const sucCount = ref<number>(0);
  const errCount = ref<number>(0);
  const errDetail = ref<ErrorDetailItem[]>([]);
  const simpleMessage = ref<string>('');
  const lastResponseData = ref<ImportResponseData | ImportResponseDataPerson | string | undefined>(undefined);
  const isPersonResponseType = ref<boolean>(false);

  // 监听visible属性变化，重置状态
  watch(
    () => props.visible,
    (newVal) => {
      if (newVal) {
        isImportDisable.value = true;
        dialogVisibleErr.value = false;
        sucCount.value = 0;
        errCount.value = 0;
        errDetail.value = [];
        simpleMessage.value = '';
        lastResponseData.value = undefined;
        isPersonResponseType.value = false;
        // 清空上传文件
        if (upload.value) {
          upload.value.clearFiles();
        }
      }
    },
  );

  // 下载模板
  const handleDownloadTemplate = async () => {
    try {
      const config: AxiosRequestConfig = {
        headers: getHeaders(),
        responseType: 'blob',
      };
      const response = await axios.get(props.templateUrl, config);
      const blob = new Blob([response.data], {
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      });
      // 创建下载链接
      let downloadLink: HTMLAnchorElement | null = document.createElement('a');
      const url = window.URL.createObjectURL(blob);
      downloadLink.href = url;
      downloadLink.download = `${props.templateName}.xlsx`;
      downloadLink.click();
      // 移除下载链接
      window.URL.revokeObjectURL(url);
      downloadLink = null;
    } catch (error) {
      console.error('Error downloading file:', error);
      ElMessage.error('模板下载失败');
    }
  };

  // 导入
  const handleImport = async () => {
    upload.value?.submit();
  };

  // 上传文件之前的钩子，参数为上传的文件。即上传之前验证文件类型/后缀
  const beforeUpload = (file) => {
    const isExcel = /\.(xlsx|xls)$/.test(file.name.toLowerCase());
    if (!isExcel) {
      // 提示用户选择正确的文件类型
      ElMessage({
        message: '仅支持上传.xlsx .xls格式文件',
        type: 'error',
      });
      return false; // 阻止上传
    }
    return true; // 允许上传
  };

  function mergeFailReasons(data: ErrorDetailItem[]) {
    const grouped = data.reduce((acc, item) => {
      if (!acc[item.rowNum]) {
        acc[item.rowNum] = [];
      }
      // 避免重复添加
      if (!acc[item.rowNum].includes(item.failReason)) {
        acc[item.rowNum].push(item.failReason);
      }
      return acc;
    }, {} as Record<string, string[]>);

    return Object.entries(grouped).map(([rowNum, reasons]) => ({
      rowNum: parseInt(rowNum),
      failReason: reasons.join('、'),
    }));
  }

  const handleUploadSuccess = (response: { data: ImportResponseData | ImportResponseDataPerson | string } | string) => {
    // 简单模式：处理字符串返回
    if (props.responseType === 'simple') {
      try {
        // 提取字符串消息
        let message = '';
        if (typeof response === 'string') {
          message = response;
          simpleMessage.value = response;
          lastResponseData.value = response;
        } else if (typeof response.data === 'string') {
          message = response.data;
          simpleMessage.value = response.data;
          lastResponseData.value = response.data;
        } else if (response.data && typeof response.data === 'object' && 'message' in response.data) {
          message = (response.data as { message: string }).message;
          simpleMessage.value = message;
          lastResponseData.value = message;
        } else {
          message = '导入完成';
          simpleMessage.value = message;
          lastResponseData.value = message;
        }
        // 显示错误弹窗
        dialogVisibleErr.value = true;
        // 通知父组件更新数据（但不关闭主弹窗）
        emit('update', lastResponseData.value);
      } catch (error) {
        ElMessage({
          message: '导入失败',
          type: 'error',
        });
        emit('update', lastResponseData.value);
      }
      return;
    }

    // 详细模式：兼容字符串和对象返回
    let detailedData: ImportResponseData | ImportResponseDataPerson | undefined;
    if (typeof response === 'string') {
      // 如果后端返回纯字符串（理论不应出现，兜底）
      detailedData = undefined;
    } else if (response && typeof response.data === 'object') {
      const responseData = response.data;
      // 判断是 ImportResponseDataPerson 类型（有 successMembers 属性）
      if ('successMembers' in responseData) {
        detailedData = responseData as ImportResponseDataPerson;
        isPersonResponseType.value = true;
        // ImportResponseDataPerson 类型：在 dialog 中只显示 message
        simpleMessage.value = detailedData.message || '导入完成';
        // 保存返回值
        lastResponseData.value = detailedData;
        // 显示错误弹窗
        dialogVisibleErr.value = true;
        // 触发 update 事件，通知父组件更新数据（但不关闭主弹窗）
        emit('update', detailedData);
        return;
      } else {
        // 否则是 ImportResponseData 类型（有 successCount, failCount, failInfoList）
        detailedData = responseData as ImportResponseData;
        isPersonResponseType.value = false;
      }
    } else {
      // 如果 response.data 是字符串（异常情况，兜底）
      detailedData = undefined;
      isPersonResponseType.value = false;
    }

    // 保存返回值
    lastResponseData.value = detailedData;

    // 处理 ImportResponseData 类型（有 successCount, failCount, failInfoList）
    if (detailedData && 'successCount' in detailedData) {
      const importData = detailedData as ImportResponseData;
      sucCount.value = importData.successCount;
      errCount.value = importData.failCount;
      errDetail.value = importData.failInfoList;
    } else {
      sucCount.value = 0;
      errCount.value = 0;
      errDetail.value = [];
    }

    try {
      if (sucCount.value != 0 && errCount.value === 0 && errDetail.value.length === 0) {
        // 完全成功：通知父组件更新数据，然后关闭弹窗
        ElMessage({
          message: `导入成功！共导入${sucCount.value}条记录`,
          type: 'success',
        });
        emit('update', detailedData);
        emit('close');
      } else {
        // 有错误：显示错误弹窗，通知父组件更新数据（可选）
        dialogVisibleErr.value = true;
        errDetail.value = mergeFailReasons(errDetail.value);
        // 可选：如果父组件需要知道有错误，可以触发 update
        // emit('update', detailedData);
      }
    } catch (error) {
      ElMessage({
        message: '导入失败',
        type: 'error',
      });
      emit('update', lastResponseData.value);
    }
  };

  const handleBackToImport = () => {
    upload.value?.clearFiles();
    dialogVisibleErr.value = false;
  };

  // 当超出只能上传一个文件的限制时，自动替换上一个文件
  const handleExceed: UploadProps['onExceed'] = (files) => {
    upload.value?.clearFiles();
    const file = files[0] as UploadRawFile;
    file.uid = genFileId();
    upload.value?.handleStart(file);
  };

  const handleChange = () => {
    isImportDisable.value = false;
  };

  const handleRemove = () => {
    isImportDisable.value = true;
  };

  // 主弹窗关闭：直接关闭，不触发 update（因为可能没有数据更新）
  const handleMainClose = () => {
    emit('close');
  };

  // 错误弹窗关闭：关闭错误弹窗，并关闭主弹窗
  const handleErrorDialogClose = () => {
    dialogVisibleErr.value = false;
    emit('close');
  };
</script>

<style scoped lang="scss">
  .overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 999;
  }

  .pop-card {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1000;
  }

  .upload-content {
    margin: 40px 60px 10px 60px;
  }

  :deep(.el-card) {
    .el-card__header {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
  }

  :deep(.el-dialog) {
    padding: 0px;
    border-radius: 5px;

    .el-dialog__header {
      display: flex;
      align-items: flex-end;
      height: 70px;
      padding: 0px 0px 15px 15px;
      border-bottom: 1px solid #e7e7e7;

      .header-text {
        font-size: 20px;
      }

      .close-icon {
        position: absolute;
        right: 20px;
        top: 30px;
        cursor: pointer;
      }
    }

    .el-dialog__headerbtn {
      top: 15px;
      right: 3px;

      .el-dialog__close {
        font-size: 20px;
        color: black;
      }
    }

    .el-dialog__body {
      padding: 20px;

      .simple-message {
        font-size: 16px;
        line-height: 1.5;
        text-align: center;
        padding: 40px 20px;
        min-height: 190px;
        display: flex;
        align-items: center;
        justify-content: center;
        white-space: pre-wrap;
        word-break: break-word;
      }

      .sum-count {
        font-size: 20px;
        display: flex;
        justify-content: center;
        margin-bottom: 20px;

        .succ-sum {
          color: #52c41a;
        }

        .err-sum {
          color: #ff4d4f;
        }
      }
    }

    .el-dialog__footer {
      margin: 0 20px 20px 0;
    }
  }

  :deep(.el-table) {
    .error-reason {
      color: #ff4d4f;
    }

    .error-reason-label {
      color: #000;
    }
  }
</style>
