<template>
  <el-dialog title="导出"  v-model="visible" :width="710" :z-index="1900" :before-close="handleClose">
    <div class="export">
      <div>
        将导出从第
        <el-input-number v-model="pageStart" :min="1" :max="lastPage"  />
        页到第
        <el-input-number v-model="pageEnd" :min="1" :max="lastPage"  />
        页的数据(共{{ total }}条)
      </div>
      <div>
        数据越多耗时越长, 请先搜索后再导出，确认无误请点击确定
      </div>
      <el-progress :percentage="percentage" />
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="() => handleClose(() => visible = false)">取消</el-button>
        <el-button type="primary" :loading="isStart" @click="start">
          确定
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { useApi } from '@/hooks/useApi';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useBaseAsync } from 'hpsfir-managebase-ui';
import { computed, ref } from 'vue';
import * as xlsx from 'xlsx';
import FileSaver from 'file-saver';
import dayjs from 'dayjs';

const visible = ref(false);
const pageStart = ref(1);
const pageEnd = ref(1);
const pageSize = ref(10);
const percentage = ref(0);
const apiName = ref('');
const apiFnc = ref('');
const params = ref<any>({});
const columns = ref<any[]>([]);
const lastPageSize = ref(10);
const lastPage = ref(1);

const total = computed(() => {
  if (Number(pageEnd.value) < Number(pageStart.value)) {
    return 0;
  }
  // 包含最后一页
  if (Number(pageEnd.value) === lastPage.value) {
    return (pageSize.value * (pageEnd.value - pageStart.value)) + lastPageSize.value;
  }
  return pageSize.value * (pageEnd.value - pageStart.value + 1);
});

const isStart = ref(false);
const waitStop = ref(false);


const getProgress = useBaseAsync(async() => {
  try {
    const datas: any = [];
    for (let i = 0; i <= pageEnd.value - pageStart.value; i++) {
      const res = await (useApi() as any)[apiName.value]?.[apiFnc.value]({
        ...params.value,
        pageQuery: {
          page: pageStart.value - 1 + i,
          pageSize: pageSize.value,
        },
      });
      if (waitStop.value) {
        isStart.value = false;
        visible.value = false;
        return;
      }
      datas.push(...(res.data?.data?.data || []));
      percentage.value = Math.floor(((i + 1) / (pageEnd.value - pageStart.value + 1)) * 90);
    }

    const worksheet = xlsx.utils.json_to_sheet(datas.map((item: any) => columns.value.reduce((res: any, current: any) => {
      if (!current.hideTable) {
        res[current.label] = current.render ? current.render({ row: item }) : item[current.name];
      }
      return res;
    }, {})));

    if (waitStop.value) {
      isStart.value = false;
      visible.value = false;
      return;
    }
    percentage.value = 95;
    const workbook = xlsx.utils.book_new();
    xlsx.utils.book_append_sheet(workbook, worksheet, 'Dates');
    const wbout = xlsx.write(workbook, {
      bookType: 'xlsx',
      bookSST: true,
      type: 'array',
    });

    if (waitStop.value) {
      isStart.value = false;
      visible.value = false;
      return;
    }
    FileSaver.saveAs(
      new Blob([wbout], {
        type: 'application/octet-stream',
      }),
      `export_${dayjs().format('YYYY_MM_DD_HH_mm_ss')}.xlsx`,
    );
    percentage.value = 100;
    isStart.value = false;
    visible.value = false;
  } catch (error: any) {
    console.log('导出失败', error);
    ElMessage.error('导出失败');
    isStart.value = false;
  }
});

const handleClose = (done: () => void) => {
  if (isStart.value) {
    ElMessageBox.confirm('确认要停止导出吗？', '取消', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
    }).then(() => {
      waitStop.value = true;
    });
  } else {
    done();
  }
};


const start = useBaseAsync(() => {
  if (pageStart.value < 1 || pageStart.value > pageEnd.value) {
    ElMessage.error('请输入正确的页码，从1开始，结束页码不能小于开始页码');
    isStart.value = false;
    return;
  }
  isStart.value = true;
  getProgress();
});

defineExpose({
  show: (
    _apiName: string,
    _apiFnc: string,
    _params: any,
    _columns: any,
    _pageSize: number,
    _total: number,
  ) => {
    waitStop.value = false;
    percentage.value = 0;
    apiName.value = _apiName;
    apiFnc.value = _apiFnc;
    columns.value = _columns;
    visible.value = true;
    isStart.value = false;
    params.value = _params;
    pageStart.value = 1;
    pageSize.value = _pageSize;
    pageEnd.value = Math.ceil(_total / _pageSize);
    lastPage.value = pageEnd.value;
    lastPageSize.value = (_total % _pageSize) || _pageSize;
  },
});

</script>

<style lang="scss">
.export {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
</style>
