<template>
  <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose title="上传文件" :width="1150" :showOkBtn="false" :showCancelBtn="false">
    <div>
      <p>
        <a-row>
          <a-col :span="18">
            <span color="blue" style="font-size: 16px; margin: 10px"
              >最大<font style="color: red">{{ maxFileSize }}</font
              >M</span
            >
            <span color="blue" style="font-size: 16px; margin: 10px"
              >一次最多<font style="color: red">{{ maxFileNum }}</font
              >个文件</span
            >
          </a-col>
          <a-col :span="6">
            <vxe-button status="primary" @click="insertEvent(true)">选择文件</vxe-button>
            <vxe-button status="primary" @click="uploadAndSaveFile" v-show="fileCount">上传全部文件</vxe-button>
          </a-col>
        </a-row>
      </p>
      <vxe-table border show-overflow ref="tableRef" height="400" 
      :column-config="{resizable: true}"
      :edit-config="{trigger: 'manual', mode: 'row'}">
        <vxe-column type="seq" width="50" />
        <vxe-column field="name" title="文件名称" width="350" :edit-render="{}">
          <template #edit="{ row }">
            <!-- <div>{{ row.name }}</div> -->
            <vxe-input v-model="row.name" type="text" />
            <Progress :percent="row.progress"  status="active" stroke-color="#52c41a">
            </Progress>
          </template>
        </vxe-column>
        <vxe-column field="fileTp" title="文件类型" width="100" />
        <vxe-column field="fileSize" title="文件大小" width="100" />
        <vxe-column field="date" title="最后修改日期" width="150" />
        <vxe-column field="status" title="状态" type="html" width="90">
          <template #default="{ row }">
            <span v-if="!row.status" style="color: red"></span>
            <span v-else-if="row.status == -3" style="color: red"> 文件太大 </span>
            <span v-else-if="row.status == -2" style="color: red"> 已存在 </span>
            <span v-else-if="row.status == -1" style="color: red"> 上传失败 </span>
            <span v-else-if="row.status == 1" style="color: yellow"> 上传中 </span>
            <span v-else style="color: green"> 上传成功 </span>
          </template>
        </vxe-column>
        <vxe-column field="opt" title="操作" width="300">
          <template #default="{ row }">
      
            <template v-if="row.status == -3">
              <vxe-button status="danger" @click="removeRow(row)">删除</vxe-button>
            </template>
            <template v-else-if="row.status != -2">
              <vxe-button status="danger" @click="removeRow(row)">删除</vxe-button>
              <vxe-button status="primary" @click="uploadFile(row)">上传</vxe-button>
            </template>
            <template v-else>
              <vxe-button status="primary" @click="replaceFile(row)">替换原文件</vxe-button>
              <template v-if="isActiveStatus(row)">
                <vxe-button status="primary" @click="uploadFile2(row)">上传</vxe-button>
                <vxe-button @click="cancelRowEvent(row)">取消</vxe-button>
              </template>
              <template v-else>
                <vxe-button status="primary" @click="editRowEvent(row)">新增副本</vxe-button>
              </template>
            </template>
          </template>
        </vxe-column>
      </vxe-table>
    </div>
  </BasicModal>
</template>

<script lang="ts" setup>
  import { ref, computed, unref } from 'vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { formSchema } from '../DocFiles.data';
  import { saveOrUpdate, checkFileExist,deleteByName } from '../DocFiles.api';
  import { uploadApi } from '/@/api/sys/upload';
  import { BasicUpload } from '/@/components/Upload';

  import { useMessage } from '/@/hooks/web/useMessage';

  import { VXETable } from 'vxe-table';
  import XEUtils from 'xe-utils';
  import { defHttp } from '/@/utils/http/axios';
  import { UploadApiResult } from '/@/api/sys/model/uploadModel';
  import { UploadFileParams } from '/#/axios';

  import { buildUUID } from '/@/utils/uuid';
  import { Progress } from 'ant-design-vue';

  const { createMessage } = useMessage();
  const tableRef = ref();
  const tableData = ref([]);
  const ctp = ref(1);
  const fileCount = ref(0);

  const maxFileNum = ref(20);
  const maxFileSize = ref(50);

  const emit = defineEmits(['success']);
  const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
    ctp.value = data.record.ctp;
    setModalProps({ disabled: !data?.showFooter });
  });

  const insertEvent = async (isMultiple) => {
    const $table = tableRef.value;
    if ($table) {
      const existRows = $table.getInsertRecords();
      if (existRows.length >= maxFileNum.value) {
        createMessage.warning('一次最多上传' + maxFileNum.value + '个文件');
        return;
      }
      const { files } = await $table.readFile({ multiple: isMultiple });
      fileCount.value = files.length;

      let fileNames = [];
      const records = Array.from(files).map((file) => {
        const ns = file.name.split('.');
        const name = ns.slice(0, ns.length - 1).join('');
        const fileTp = ns[ns.length - 1];
        fileNames.push(name);

        let fileSizeM = file.size / 1048576
    
        return {
          uuid: buildUUID(),
          name: name,
          size: file.size,
          fileSize: formatFileSize(file.size),
          fileTp: fileTp,
          date: XEUtils.toDateString(file.lastModifiedDate),
          file: file,
          status: fileSizeM >maxFileSize.value?-3:0
        };
      });
      $table.insert(records);

      await checkFileExist1(fileNames);
    }
  };

  const removeRow = async (row) => {
    const $table = tableRef.value;
    if ($table) {
      await $table.remove(row);
    }
  };

  const uploadAndSaveFile = () => {
    const $table = tableRef.value;
    if ($table) {
      const rows = $table.getInsertRecords();
      for (let row of rows) {
        if (!row.status || row.status == -1) {
            uploadFile(row);
        }
      }
    }
  };

  function formatFileSize(bytes) {
    if (!bytes) {
      return '';
    }

    if (bytes >= 1073741824) {
      return (bytes / 1073741824).toFixed(2) + ' GB';
    } else if (bytes >= 1048576) {
      return (bytes / 1048576).toFixed(2) + ' MB';
    } else if (bytes >= 1024) {
      return (bytes / 1024).toFixed(2) + ' KB';
    } else {
      return bytes + ' bytes';
    }
  }

  const percentage = ref();
  const progressLoad = ref();
  const uploadLeftTime = ref();
  const speedStr = ref();
  const showPrercentage = ref(true)

  async function uploadFile(row) {
    if (row.status == -2) {
      createMessage.warning('文件已经存在，不能重复上传！');
      return false;
    }

    let fileSizeM = row.file.size / 1048576
    if ( fileSizeM > maxFileSize.value) {
     return  false
    }

    const params: UploadFileParams = {
      file: row.file,
      data: {
        uuid: row.uuid,
      },
    };

    const onUploadProgress = (progressEvent) => {
      uploadCallback(progressEvent, row);
    };

    percentage.value = 0;
    progressLoad.value = true;

    uploadApi(params, onUploadProgress)
      .then((result) => {
        handleChange(result);
      })
      .catch((error) => {
        row['status'] = -1;
      });
  }

  async function uploadFile2(row) {
    row.status=2
    uploadFile(row)
  }

  let lastTime = 0; // 上一次计算时间
  let lastSize = 0; // 上一次计算的文件大

  function uploadCallback(progressEvent, row) {
    if (lastTime == 0) {
      lastTime = new Date().getTime();
      lastSize = progressEvent.loaded;
      return;
    }

    let nowTime = new Date().getTime();
    let intervalTime = (nowTime - lastTime) / 1000;
    let intervalSize = progressEvent.loaded - lastSize;
    lastTime = nowTime;
    lastSize = progressEvent.loaded;
    let speed = intervalSize / intervalTime;
    let bSpeed = speed; // 保存以b/s为单位的速度值，方便计算剩余时间
    let units = 'b/s'; // 单位名称
    if (speed / 1024 > 1) {
      speed = speed / 1024;
      units = 'k/s';
    } else if (speed / 1024 > 1) {
      speed = speed / 1024;
      units = 'M/s';
    }

    let leftTime = progressEvent.total < progressEvent.loaded ? 0 : (progressEvent.total - progressEvent.loaded) / bSpeed;
    let progress = parseInt((progressEvent.loaded / progressEvent.total) * 100);
    percentage.value = progress;
    uploadLeftTime.value = leftTime.toFixed(1) + '秒';
    speedStr.value = speed.toFixed(1) + units;
    row['status'] = percentage.value < 100 ? 1 : 2;
    row['progress'] = percentage.value;
  }

  function handleChange(ret) {
    let data = ret['data'];
    if (data.success) {
      saveRowDb(data.result);
    }
  }

  async function saveRowDb(retData) {
    const uuid = retData.uuid;
    const url = retData.url;
    const author = retData.author || '';
    const detail = retData.detail || '';

    const $table = tableRef.value;
    if ($table) {
      const rows = $table.getInsertRecords();
      if (!rows) return true;
      const row = rows.find((item) => item.uuid === uuid);
      if (!row) return true;

      let formData = {
        ctp: ctp.value,
        fileName: row.name,
        filePath: url,
        fileTp: row.fileTp,
        author: author,
        fileSize: row.size,
        lastModifyTime: row.date,
        fileDetail: JSON.stringify(detail),
      };

      await saveOrUpdate(formData, false);
      removeRow(row);
      closeThisModal();
      return true;
    }

    async function closeThisModal() {
      const $table = tableRef.value;
      if ($table) {
        const rows = $table.getInsertRecords();
        if (rows.length == 0) {
          fileCount.value = 0;
          await sleep(500);
          closeModal();
          emit('success');
        }
      }
    }

    function sleep(ms) {
      return new Promise((resolve) => setTimeout(resolve, ms));
    }
  }

  async function checkFileExist1(fileNames) {
    if (!fileNames) {
      return;
    }
    const $table = tableRef.value;
    if (!$table) {
      return;
    }
    let existFiles = await checkFileExist({ fileNames: fileNames.join(',') });

    if (!existFiles || existFiles.length == 0) {
      return;
    }

    const rows = $table.getInsertRecords();
    for (let fname of existFiles) {
      const trow = rows.find((item) => item.name === fname);
      trow.status = -2;
    }
  }

  const loading = ref(false);

  const isActiveStatus = (row: RowVO) => {
    const $table = tableRef.value;
    if ($table) {
      showPrercentage.value = $table.isEditByRow(row);
      return $table.isEditByRow(row);
    }
  };

  const editRowEvent = (row: RowVO) => {
    const $table = tableRef.value;
    if ($table) {
      row["name"] = row["name"]+"[1]"
      $table.setEditRow(row);
    }
  };

  const cancelRowEvent = (row: RowVO) => {
    const $table = tableRef.value;
    if ($table) {
      $table.clearEdit().then(() => {
        // 还原行数据
        $table.revertData(row);
      });
    }
  };

  
  const replaceFile = (row: RowVO) => {
    deleteByName({fileName:row.name},function(){
      row.status = 1;
      uploadFile(row)
    })
  };

</script>

<style lang="less" scoped>
  /** 时间和数字输入框样式 */
  :deep(.ant-input-number) {
    width: 100%;
  }

  :deep(.ant-calendar-picker) {
    width: 100%;
  }
</style>
