
import XLSXST from "xlsx-js-style";



const headerStyle = {
  font: { name: "微软雅黑", sz: 14, bold: true, color: { rgb: "000000" } },
  fill: { fgColor: { rgb: "FFFFFF" } },
  alignment: { vertical: "center", horizontal: "center" },
};
// 基础样式定义
const baseStyle = {
  font: { name: "微软雅黑", sz: 12 },
  alignment: { vertical: "center", horizontal: "center" },
  border: {
    top: { style: "thin", color: { rgb: "000000" } },
    bottom: { style: "thin", color: { rgb: "000000" } },
    left: { style: "thin", color: { rgb: "000000" } },
    right: { style: "thin", color: { rgb: "000000" } }
  }
};
/** 获取表头样式 */
export function getHeadStyle(styleObj = {}) {
  return { ...headerStyle, ...styleObj }
}
/** 获取基础样式 */
export function getBaseStyle(styleObj = {}) {
  return { ...baseStyle, ...styleObj }
}

/** 对象数组转成 excel需要的二维数组
 * @param {Array} data - 列表数组
 * @param {Object} title - 表头对象 - 例如{title: '标题', content: '内容'}
 * @return {Array} - excel需要的二维数组 - 例如: [['标题', '内容'], ['安全要闻', '安全事情234']]
 */
export function dataToExcelArr(data = [], title = {}) {
  let arr = []
  let keysArr = Object.keys(title)
  data.map(item => {
    arr.push(keysArr.map(key => item[key] || ''))
  })
  return arr
}



/** 根据数组创建sheet
 * @param {Object} titleObj 标题对象
 * @param {Array} data 列表数据 格式[{title: '', content: ''}]
 * @param {String} sheetName sheet名称
 * @param {Object} otherParams 其他参数
 * @param {Array} otherParams.titleWidth 列宽 例如 {title: 200, content: 150}
 * @param {String} otherParams.sheetName sheet名称
 * @param {String} otherParams.sheetTitle sheet 标题（第一行的文字）
 * @param {Array} otherParams.rowsH sheet 高度 格式[30,30]
 * @param {Array} otherParams.merges 合并数组 格式[{ s: { r: 0, c: 0 }, e: { r: 0, c: 11 } }] // 合并第一行 0-11列
 * @param {Function} otherParams.beforeToSheet 转换为sheet之前执行 返回的数组为要转的数组
 * @param {Function} otherParams.beforeAppendSheet 在加入sheet之前执行 返回的数组为最后的数组
 */
export function ExpXlsx(titleObj, data, exprtName, otherParams = {}) {
  const titleWidth = otherParams.titleWidth || {}
  /** sheet名称 */
  const sheetName = otherParams.sheetName || 'sheet1';
  const sheetTitle = otherParams.sheetTitle
  const rowsH = otherParams.rowsH
  const merges = otherParams.merges
  const beforeToSheet = otherParams.beforeToSheet
  const beforeAppendSheet = otherParams.beforeAppendSheet

  const wb = XLSXST.utils.book_new();
  const titleData = Object.values(titleObj)
  const tableData = dataToExcelArr(data, titleObj)
  /** sheet用 二维数组 */
  let sheetTableData = [[sheetTitle || exprtName], titleData, ...tableData]
  // 如果需要 修改表格数据
  if (typeof beforeToSheet === 'function') sheetTableData = beforeToSheet(sheetTableData)
  let ws = XLSXST.utils.aoa_to_sheet(sheetTableData);

  ws['!cols'] = Object.keys(titleObj).map(key => {
    if (titleWidth[key] > 0) return { wpx: titleWidth[key] }
    return { wpx: 120 }
  });
  ws['!rows'] = [
    { hpx: 30 },
  ];
  if (rowsH) ws['!rows'] = rowsH.map(item => { return { hpx: item } });
  /** 有多少列 */
  const count = Object.keys(titleObj).length;

  ws['!merges'] = [];
  // 合并规则 s:开始位置(start) e:结束位置（end）  r:行数(row,0开始) c:列数(column，0开始)
  ws['!merges'].push({ s: { r: 0, c: 0 }, e: { r: 0, c: count - 1 } });
  if (merges?.length) ws['!merges'] = merges
  // 设置表头样式
  for (let col = 0; col < data.length; col++) {
    const cell = XLSXST.utils.encode_cell({ r: 0, c: col });
    if (cell && ws[cell]) {
      ws[cell].s = getHeadStyle()
    }
  }
  const baseStyle = {
    font: { name: "微软雅黑", sz: 12 },
    alignment: { vertical: "center", horizontal: "center" },
    border: {
      top: { style: "thin", color: { rgb: "000000" } },
      bottom: { style: "thin", color: { rgb: "000000" } },
      left: { style: "thin", color: { rgb: "000000" } },
      right: { style: "thin", color: { rgb: "000000" } }
    }
  };
  // 设置数据行样式
  for (let row = 1; row < sheetTableData.length; row++) {
    for (let col = 0; col < sheetTableData[row].length; col++) {
      const cell = XLSXST.utils.encode_cell({ r: row, c: col }); // 根据行列索引获取单元格名称 例如 r:0,c:0 =>> A1
      if (cell && ws[cell]) ws[cell].s = baseStyle;// 本质上他们公用一个，修改记得用.s = xxx的方式
    }
  }
  if (typeof beforeAppendSheet === 'function') ws = beforeAppendSheet(ws, XLSXST)
  XLSXST.utils.book_append_sheet(wb, ws, sheetName);
  XLSXST.writeFile(wb, `${exprtName}.xlsx`);
}
