import { ElTableColumn } from 'element-ui/types/table-column'
import { utils } from 'xlsx'
import XLSX from 'xlsx-style'
import { get as getVal } from 'lodash'

function s2ab(s) {
  var buf = new ArrayBuffer(s.length)
  var view = new Uint8Array(buf)
  for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
  return buf
}

export const exportXlsx = (
  name: string = 'download',
  data: { [x: string]: any }[] = [],
  cols: Partial<ElTableColumn & { _slot?: boolean }>[] = [],
  ids: (string | number)[] = []
) => {
  const wb = utils.book_new()
  const validCols = cols.filter((item) => !item._slot && !!item.prop)
  const header = validCols.map((item) => item.label)
  const colWidth = header.map((text) => ({ wpx: text.length * 2 * 12 }))
  const sheetData: { [x: string]: string | number }[] = (() => {
    const keys = validCols.reduce((acc, { prop, label, formatter }) => {
      acc[label] = { prop, formatter }
      return acc
    }, {} as { [x: string]: { prop: string; formatter: Function } })
    return data
      .filter((item) => (ids.length === 0 ? true : ids.includes(item.id)))
      .map((item) => {
        const temp = {}
        Object.keys(keys).forEach((key, index) => {
          const { prop, formatter } = keys[key]
          const val = formatter ? formatter(item) : getVal(item, prop)
          temp[key] = val === null ? '' : val

          const maxLength = 160
          const chinessCharactersLength = String(temp[key] || '').replace(/[^\u4e00-\u9fa5]/g, '').length
          const valLength = (String(temp[key] || '').length + chinessCharactersLength) * 12

          const titleLength = colWidth[index].wpx

          const length = valLength > titleLength ? valLength : titleLength

          colWidth[index].wpx = length > maxLength ? maxLength : length
        })
        return temp
      })
  })()

  const ws = utils.json_to_sheet(sheetData, { header })
  ws['!cols'] = colWidth
  ws['!rows'] = header.map(() => ({ hpx: 34 }))

  for (const key in ws) {
    if (new RegExp('^[A-Za-z0-9]+$').exec(key)) {
      const isHeader = /^[A-Za-z]+1$/.test(String(key))
      const border = { style: 'thin', color: { rgb: '666666' } }
      ws[String(key)].s = {
        alignment: { horizontal: 'center', vertical: 'center', wrap_text: true },
        font: {
          name: 'Microsoft Yahei',
          sz: isHeader ? 12 : 11,
          bold: isHeader,
          color: isHeader ? { rgb: '303133' } : { rgb: '555555' }
        },
        fill: isHeader
          ? { fgColor: { rgb: 'E0EAFB' } }
          : { fgColor: { rgb: Number(String(key).replace(/\D/g, '')) % 2 === 0 ? 'F3F7FE' : 'FFFFFF' } },
        border: { top: border, right: border, bottom: border, left: border }
      }
    }
  }

  utils.book_append_sheet(wb, ws, 'Sheet1')
  const wbout = XLSX.write(wb, { type: 'binary', bookType: 'xlsx', bookSST: false })
  const blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.download = `${name}.xlsx`
  a.style.display = 'none'
  a.href = url
  document.body.appendChild(a)
  a.click()
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(true)
    }, 2000)
  })
}
