

import { utils, write } from 'xlsx';
import { dateUtil } from '/nerv-lib/util/date-util';
import { NsMessage } from '/nerv-lib/component/message';
import axios from 'axios';
import { createVNode, h, render as vueRender } from 'vue';
import { NsXlsxImport } from '/nerv-lib/component/xlsx';
import { NsModal } from '/nerv-lib/component/modal';

interface MapItem {
  title: string;
  dataIndex: string;
  format?: Function;
}
type objProps = {
  [name: string]: any;
};

type argType = {
  data: Array<object>;
  xlsxMap: Array<MapItem>;
  xlsxName: string;
  limit?: number;
};

const DATE_FORMAT = 'YYYY-MM-DD ';
const MODAL_INFO = {
  title: '警告',
  okText: '确认',
  cancelText: '取消',
};

const errorTable = [
  {
    title: '行数',
    dataIndex: 'row',
  },
  {
    title: '错误内容',
    dataIndex: 'reason',
  },
];

const sheet2blob = (sheet: any, sheetName = 'sheet1') => {
  sheetName = sheetName || 'sheet1';
  const workbook = {
    SheetNames: [sheetName],
    Sheets: {},
  };
  workbook['Sheets'][sheetName] = sheet;
  // 生成excel的配置项
  const wbout = write(workbook, {
    bookType: 'xlsx', // 要生成的文件类型
    bookSST: false, // 是否生成Shared String Table，官方解释是，如果开启生成速度会下降，但在低版本IOS设备上有更好的兼容性
    type: 'binary',
  });
  const blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' });
  // 字符串转ArrayBuffer
  function s2ab(s: any) {
    const buf = new ArrayBuffer(s.length);
    const view = new Uint8Array(buf);
    for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
    return buf;
  }
  return blob;
};

function openDownloadDialog(url: string | Blob | MediaSource, saveName: string) {
  if (typeof url == 'object' && url instanceof Blob) {
    url = URL.createObjectURL(url); // 创建blob地址
  }
  const aLink = document.createElement('a');
  aLink.href = url;
  aLink.download = saveName || '';
  document.body.appendChild(aLink);
  aLink.click();
  document.body.removeChild(aLink);
}

function download(table: unknown[][], name: string, config: any) {
  let isHandle;
  if (config && config['isHandle']) {
    isHandle = config['isHandle'];
  }
  let sheet;
  //isHandle 表示自己处理表格样式和数据，不需要再做处理
  isHandle ? (sheet = table) : (sheet = utils.aoa_to_sheet(table));
  openDownloadDialog(sheet2blob(sheet), `${name}.xlsx`);
}

function DataHandler(data: Array<object>, keyMap: Array<MapItem>) {
  const tableHeader: string[] = []; // 表头
  const tableHeaderKeyMap: objProps = {}; // 表头索引map

  keyMap?.map((item: MapItem) => {
    tableHeader.push(item['title']);
    tableHeaderKeyMap[item['title']] = item['dataIndex'];
  });

  const table = [tableHeader];
  data.forEach((item: object) => {
    const rowData: any[] = [];
    tableHeader.forEach((th: string, index: number) => {
      let temp = item[tableHeaderKeyMap[th]];
      const format = keyMap[index].format;
      if (format) temp = format(temp, item);
      rowData.push(temp);
    });
    table.push(rowData);
  });
  return table;
}

export const importFile = (
  { api, params }: any,
  reload: Function,
  event: any,
  successBack?: Function,
  errorBack?: Function,
) => {
  const formData = new FormData();
  params &&
    Object.keys(params).map((item) => {
      formData.append(item, params[item]);
    });
  formData.append('file', event);
  axios
    .post(api, formData)
    .then((res) => {
      if (res) {
        NsMessage.success('导入成功', 1, () => {
          reload && reload();
          successBack && successBack(res);
        });
      }
    })
    .catch((err) => {
      if (errorBack) {
        errorBack(err);
      } else {
        NsMessage.error(err.response?.data?.msg || '导入失败');
        const error = err.response?.data?.data;
        if (error)
          xlsxExport({
            data: error,
            xlsxMap: errorTable,
            xlsxName: '导入数据不规范说明YYYY-MM-DD',
          });
      }
    });
};
const checkLimit = (data: Array<object>, limit?: number) => {
  if (limit && data.length > limit) {
    NsModal.confirm({
      ...MODAL_INFO,
      content: `本次数据下载超过${limit}条，请重新选择数据！`,
    });
    return false;
  }
  return true;
};

export const xlsxExport = ({ data, xlsxMap, xlsxName, limit }: argType) => {
  if (!checkLimit(data, limit)) return;
  const name = dateUtil(new Date()).format(xlsxName);
  download(DataHandler(data, xlsxMap), `${name}`, '');
};

export const xlsxImport = (data: any) => {
  const div = document.createElement('div');
  const vm = h(NsXlsxImport, { ...data }, '');
  vueRender(vm, div);
};
