<template>
  <div
    v-loading="loading"
    element-loading-text="拼命加载中"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(0, 0, 0, 0.8)"
    class="statstics-wrapper"
  >
    <div
      ref="headerWrapper"
      class="statstics-header"
    >
    <PublicPageHeader class="TablePage_header" :page-title="dataTitle ? dataTitle : pageTitle">
      <template slot="d_foot">
        <SimpleQuery v-if="simpleQueryFlag" :selectOptions="advancedQueryValue" :simple-query-item="simpleQueryItem" @queryValue="queryValue" />
      </template>
    </PublicPageHeader>
      <!-- <StatisticsHeader
        :title="`${chartsTitle}统计`"
        :data="formData"
        :items="formItems"
        :custom-items="customFormItems"
        @getFormData="getFormData"
        @export="exportHandler"
      /> -->
    </div>
    <div class="statstics-content">
      <div
        id="chart"
        class="statistics-chart"
        :style="{ height: chartHeight }"
      />
    </div>
  </div>
</template>

<script>
import PublicPageHeader from '@/components/PublicPageHeader'
import SimpleQuery from '@/components/SimpleQuery'
import AuthButton from '@/components/AuthButton'
import StatisticsHeader from './statisticsHeader.vue'
import { TempQuery } from '@/api/temp'
import { mapGetters } from 'vuex'
import * as XLSX from 'xlsx'
import XLSX_STYLE from 'xlsx-style'
import FileSaver from 'file-saver'

export default {
  name: 'CommonBarStatisticsCharts',
  components: { StatisticsHeader, PublicPageHeader, SimpleQuery, AuthButton },
  props: {
    dataTitle: {
      type: String,
      default: ''
    },
    pageAuthtablesList: {
      type: Object,
      default: () => {},
    },
    chartsTitle: {
      type: String,
      required: true,
    },
    querySettings: {
      type: Object,
      required: true,
    },
    categories: {
      type: Array,
      validator(arr) {
        return (
          arr &&
          arr.every(
            category =>
              (category instanceof Object && 'name' in category) ||
              typeof category === 'string'
          )
        )
      },
    },
    formData: {
      type: Object,
      required: true,
    },
    formItems: {
      type: Array,
      default: () => [],
    },
    customFormItems: {
      type: Array,
      default: () => [],
    },
    pieTitle: {
      type: String,
      default: '总件数',
    },
  },
  data() {
    return {
      loading: false,
      myChart: null,
      debounceTime: 300,
      chartHeight: '70vh',
      hasChartData: false,
      tableData: [],
      params: [],
      options: {
        backgroundColor: '#ffffff',
        tooltip: {
          trigger: 'item',
        },
        title: {
          text: '',
          // 副标题
          subtext: '0',
          // 主副标题间距
          itemGap: 24,
          x: 'left',
          y: 'center',
          left: '30%',
          top: '40%',
          textAlign: 'center',
          // 主标题样式
          textStyle: {
            fontSize: '48',
            color: '#ffffff',
            fontWeight: 'bold',
            fontFamily: 'Microsoft YaHei',
          },
          // 副标题样式
          subtextStyle: {
            fontSize: '80',
            color: '#ffffff',
            fontWeight: 'bold',
          },
        },
        legend: {
          show: true,
          left: '60%',
          x: 'right',
          y: 'center',
          icon: 'rect',
          itemWidth: 20,
          itemHeight: 20,
          formatter: name => this.legendFormatter(name),
          textStyle: {
            backgroundColor: 'transparent',
            lineHeight: 0,
            rich: {
              chartsTitle: {
                width: 200,
                lineHeight: 100,
                fontSize: 32,
                fontFamily: 'Microsoft YaHei',
                fontWeight: 'bold',
                color: '#101116',
                padding: [0, 1000, 0, -20],
              },
              name: {
                fontSize: 20,
                fontFamily: 'Microsoft YaHei',
                fontWeight: 'bold',
                color: '#101116',
                lineHeight: 100,
              },
              label: {
                fontSize: 16,
                fontFamily: 'Microsoft YaHei',
                color: '#101116',
              },
              value: {
                width: 96,
                fontSize: 16,
                fontFamily: 'Helvetica',
                fontWeight: 'bold',
                color: '#101116',
              },
              ratio: {
                width: 80,
                fontSize: 16,
                fontFamily: 'Helvetica',
                fontWeight: 'bold',
                color: '#101116',
              },
              wrap: {
                padding: [0, 40, 0, 0],
              },
            },
          },
          selected: {
            [this.chartsTitle]: false,
          },
        },
        series: [
          {
            name: '',
            type: 'pie',
            left: '30%',
            width: 560,
            height: 560,
            center: [0, '60%'],
            radius: ['60%', '90%'],
            avoidLabelOverlap: false,
            label: {
              show: false,
              position: 'center',
            },
            emphasis: {
              label: {
                show: false,
                fontSize: '40',
                fontWeight: 'bold',
              },
            },
            labelLine: {
              show: false,
            },
            data: [],
          },
          {
            name: '总数',
            type: 'pie',
            left: '30%',
            width: 560,
            height: 560,
            center: [0, '60%'],
            radius: ['0%', '50%'],
            avoidLabelOverlap: false,
            itemStyle: {
              normal: {
                color: '#101116',
              },
            },
            label: {
              show: false,
              position: 'center',
            },
            // 自定义中心内容的话需要把这个关闭
            emphasis: {
              label: {
                show: false,
              },
            },
            labelLine: {
              show: false,
            },
            data: [],
          },
        ],
      },
      totalCount: [{ value: 0 }],
      categoryDatas: [],
      pageQuery: {},
      tableBtns: [], //表格按钮权限
      pageTitle: '', //页面名称
      pageServiceId: null, //表格serviceid
      selected: 0, //是否勾选
      triggerserviceid: null, //勾选后查询的serviceid
      defaultfilter: { 1: 1 }, //默认查询参数
      simpleQueryItem: [], //简易查询表单数据项
      advancedQueryValue: [], //高级查询缓存值
      simpleQueryFlag: false, //是否开启了简易查询
    }
  },
  computed: {
    ...mapGetters(['sidebar']),
    pageAuthBtnQuery () {
      return this.tableBtns.filter(item => item.servicetype == 0)[0]
    },
    pageAuthBtnAdd () {
      return this.tableBtns.filter(item => item.servicetype == 2)[0]
    },
  },
  watch: {
    pageAuthtablesList: {
      handler(obj) {
        this.getPageTableSetting(obj.authArrs, obj.pageAuthtables)
      },
      deep: true,
    },
    pieTitle: {
      handler(val) {
        this.options.title.text = val
      },
      immediate: true,
    },
    // 监听数据变化 重绘图形
    options: {
      handler(obj) {
        this.myChart.setOption(obj)
        this.resizeHandler()
      },
      deep: true,
    },
    categories: {
      handler(arr) {
        this.categoryDatas = arr.map(category => {
          if (category instanceof Object) {
            return {
              ...category,
              value: 0,
            }
          } else {
            return {
              name: category,
              key: category,
              value: 0,
            }
          }
        })
      },
      deep: true,
      immediate: true,
    },
    'sidebar.expand'() {
      this.setChartHeight()
    },
  },
  mounted() {
    this.setChartHeight()
    this.myChart = this.$echarts.init(document.getElementById('chart'))
    this.options.series[0].data = [
      {
        name: this.chartsTitle,
        key: this.chartsTitle,
        value: null,
      },
      ...this.categoryDatas,
    ]
    this.options.legend.data = [
      {
        name: this.chartsTitle,
        icon: 'none',
      },
      ...this.categoryDatas.map(({ name }, index) => ({ name })),
    ]
    this.options.series[1].data = this.totalCount
    this.myChart.setOption(this.options)
    this.myChart.on('legendselectchanged', ({ name }) => {
      if (name === this.chartsTitle) {
        this.myChart.dispatchAction({
          type: 'legendUnSelect',
          name,
        })
      }
    })
    // 监听页面缩放
    this.debouncedChartHeightSetter = this._.debounce(
      this.setChartHeight,
      this.debounceTime
    )
    window.addEventListener('resize', this.debouncedChartHeightSetter)
  },
  beforeDestroy() {
    // 销毁实例和移除监听
    window.removeEventListener('resize', this.debouncedChartHeightSetter)
    if (this.myChart) {
      this.myChart.dispose()
      this.myChart = null
    }
  },
  methods: {
    //根据页面table设置数据
    getPageTableSetting (pageAuths, pageAuthtables) {
      const authTableObj = pageAuthtables[0]
      //获取当前页面table的配置
      const { pagename, pageconfigurationid, serviceid, pagecode, userpermissionsid, defaultfilter, selected, triggerserviceid } = authTableObj
      this.pageTitle = pagename
      const currPageBtns = pageAuths.filter(item => item['superiorid'] == pageconfigurationid && item.pagetype == 'button')
      if (currPageBtns?.length) this.tableBtns.push(...currPageBtns)
      const tableColumnArrs = pageAuths.filter(item => item['superiorid'] == pageconfigurationid && item['pagetype'] == 'column')
      this.getColumnData(tableColumnArrs)
    },
    //获取表头数据
    getColumnData (columnArrs = []) {
      const returnData = [...columnArrs]
      const simpleQueryItem = _.cloneDeep(returnData).filter((item) => item.easysearch && item.isfiltercolumn)
      if (simpleQueryItem?.length) {
        this.simpleQueryFlag = true
        this.simpleQueryItem = simpleQueryItem
      }
    },
        //格式化传递参数数据
    formatDefault (item, data = {}) {
      if (typeof item != 'string') return {}
      const filterItem = {}
      const parameters = item.replace('{', '').replace('}', '')
      const parametersSplit = parameters?.split(',')
      parametersSplit.map(item => {
        const [key, val] = item?.split(':')
        filterItem[key] = data[val]
      })
      return filterItem
    },
    //根据页面按钮设置表单form数据
    getPageBtnFormSetting (pageAuths, pageAuthForms) {
      const { pageconfigurationid } = [...pageAuthForms][0]
      const tableColumnArrs = pageAuths.filter(item => item['superiorid'] == pageconfigurationid && item['pagetype'] == 'column')
      const formItemCopy = tableColumnArrs.filter((item) => item.isdisplay != 0)
      this.formItem = _.orderBy(formItemCopy, ['displaynumber'], ['asc'])
    },
        //简易查询-确定
    queryValue (dataRules) {
      const arr = [...dataRules]
      if (arr && arr.length) {
        arr.forEach(item => {
          item.value = typeof item.value == 'string' ? item.value.replace(/\s*/g, "") : item.value
        })
      }
      this.defaultfilter = arr.length ? arr : { 1: 1 }
      this.resetDatas()
      let params = {}
      this.defaultfilter.forEach(element => {
        params[element.column] = element.value
      });
      this.getMultipleChartsData(this.querySettings.serviceid, [params])
    },
    legendFormatter(name) {
      const index = this.categoryDatas.findIndex(
        category => category.name === name
      )
      if (index === -1) {
        return `{chartsTitle|${name}}`
      } else {
        const value = this.categoryDatas[index].value
        const ratio =
          value && this.totalCount.value
            ? ((value / this.totalCount.value) * 100).toFixed(2) + '%'
            : '0%'
        const richString = `{name|${name}}\n{label|数量：}{value|${value}}{label|占比：}{ratio|${ratio}}`
        return index % 2 ? richString + '{wrap| }' : richString
      }
    },
    resetDatas() {
      this.hasChartData = false
      this.categoryDatas.forEach(category => {
        category && (category.value = 0)
      })
      this.options.title.subtext = '0'
      this.options.series[1].data[0].value = 0
    },
    getFormData(formData) {
      this.resetDatas()
      const params = JSON.parse(JSON.stringify(formData))
      ;[params.fd1, params.fd2] = params.dateTime
      delete params.dateTime
      this.params = Object.values(params)
      const paramsList = [params]
      this.getMultipleChartsData(this.querySettings.serviceid, paramsList)
    },
    async getMultipleChartsData(serviceid, paramsList) {
      this.loading = true
      try {
        const listValuesArray = await Promise.all(
          paramsList.map(params => this.getChartsData(serviceid, params))
        )
        this.tableData = this._.sortBy(listValuesArray.flat(), 'fdt')
        const categories = this.categoryDatas.map(category => category.key)
        const listValues = listValuesArray.reduce(
          (preValues, currentValues) => {
            currentValues.forEach(value => {
              const preValue = preValues.find(
                preValue => preValue.fdt === value.fdt
              )
              if (preValue) {
                // console.log(value)
                categories.forEach(key => {
                  if (key == value.specialtype) {
                    preValue[key] = value.bags ?? 0
                  }
                })
              } else {
                const valuesObj = {
                  location: value.location,
                  fdt: value.fdt,
                }
                categories.forEach(key => {
                  if (key == value.specialtype) {
                    valuesObj[key] = value.bags ?? 0
                  }
                })
                console.log(valuesObj)
                preValues.push(valuesObj)
              }
              // console.log(value)
            })
            return preValues
          },
          []
        )
        this.setChartsData(this._.sortBy(listValues, 'fdt'))
      } catch (error) {
        this.$message.error(error.message)
      }
      this.loading = false
    },
    async getChartsData(serviceid, params) {
      try {
        const {
          code,
          returnData: listValues,
          message,
        } = await TempQuery({
          serviceid,
          datacontent: [{filter:params}],
          event: '0',
        })
        if (String(code) === '0') {
          return listValues.map(obj => ({
            ...obj,
            location: params.air_line || params.airport || '',
          }))
        } else {
          throw new Error(message)
        }
      } catch (error) {
        return Promise.reject(error.message || '失败')
      }
    },
    setChartsData(listValues) {
      if (listValues.length === 0) {
        this.$message.info('未查询到对应数据')
        return
      }
      let totalCount = 0
      listValues.forEach(element => {
        this.categoryDatas.forEach(category => {
          if (element[category.key]) {
            category.value += element[category.key]
            totalCount += element[category.key]
          }
        })
      })
      this.options.title.subtext = totalCount.toString()
      this.totalCount.value = totalCount
      this.hasChartData = true
    },
    setChartHeight() {
      const topBarHeight = 80
      const headerBlankHeight = 24
      const tabsWrapperHeight = 62
      const headerHeight = this.$refs['headerWrapper'].offsetHeight
      const footerBlankHeight = 24
      this.chartHeight = `calc(100vh - ${
        topBarHeight +
        headerBlankHeight +
        tabsWrapperHeight +
        headerHeight +
        footerBlankHeight
      }px)`
      this.$nextTick(() => {
        this.resizeHandler()
      })
    },
    resizeHandler() {
      if (this.myChart) {
        this.myChart.resize()
      }
    },
    exportHandler() {
      if (!this.hasChartData) {
        this.$message.warning('请查询后再进行导出')
        return
      }
      // const myCanvas = this.myChart._dom.querySelectorAll('canvas')[0]
      // const image = myCanvas.toDataURL('image/png')
      // const $a = document.createElement('a')
      // $a.setAttribute('href', image)
      // $a.setAttribute('download', `${this.chartsTitle}统计.png`)
      // $a.click()

      const xlsxDatas = [['时间', '位置', '分类', '数量', '占比']]
      xlsxDatas.push(
        ...this.tableData
          .map(element =>
            this.categoryDatas.map(category => [
              element['fdt'],
              element['location'],
              category.name,
              element[category.key],
              `${(
                (element[category.key] / this.totalCount.value) *
                100
              ).toFixed(2)}%`,
            ])
          )
          .flat(1)
      )
      xlsxDatas.push(['合计', '', '', this.totalCount.value, ''])
      // 计算列宽
      const columnWidths = []
      xlsxDatas.forEach((row, rowIndex) => {
        // 计算每一列宽度，考虑换行
        row.forEach((cell, columnIndex) => {
          const cellWidth = Math.max(
            ...cell
              .toString()
              .split('\n')
              .map(cellRow =>
                cellRow.split('').reduce((pre, curr) => {
                  const letterSize = curr.charCodeAt(0) > 255 ? 2 : 1
                  return pre + letterSize
                }, 0)
              )
          )
          if (
            (!columnWidths[columnIndex] && cellWidth > 0) ||
            cellWidth > columnWidths[columnIndex]
          ) {
            columnWidths[columnIndex] = cellWidth
          }
        })
      })
      // 生成表格
      const sheet = XLSX.utils.aoa_to_sheet(xlsxDatas)
      // 添加列宽度
      sheet['!cols'] = columnWidths.map(width => ({
        wch: width + 2,
      }))
      // 样式
      const borderStyle = {
        style: 'medium',
        color: {
          rgb: 'FFFFFF',
        },
      }
      const reg = /^[A-Z]+([\d]+$)/
      for (const key in sheet) {
        const match = reg.test(key)
        if (match) {
          const rowIndex = reg.exec(key)[1]
          let cellStyle = {
            alignment: {
              horizontal: 'center',
              vertical: 'center',
              wrapText: true,
            },
          }
          if (Number(rowIndex) === 1) {
            cellStyle = {
              ...cellStyle,
              border: {
                top: borderStyle,
                right: borderStyle,
                bottom: borderStyle,
                left: borderStyle,
              },
              font: {
                color: {
                  rgb: 'FFFFFF',
                },
              },
              fill: {
                fgColor: {
                  rgb: '3366FF',
                },
              },
            }
          } else {
            cellStyle.alignment.horizontal = 'left'
          }
          sheet[key].s = cellStyle
        }
      }
      // 表格数据转换
      const workBook = XLSX.utils.book_new()
      XLSX.utils.book_append_sheet(workBook, sheet, this.chartsTitle)
      const tableWrite = XLSX_STYLE.write(workBook, {
        bookType: 'xlsx',
        bookSST: true,
        type: 'buffer',
        cellStyles: true,
      })
      // 下载表格
      const fileName = `${this.chartsTitle}统计-${this.params.join('-')}.xlsx`
      FileSaver.saveAs(
        new Blob([tableWrite], { type: 'application/octet-stream' }),
        fileName
      )
    },
  },
}
</script>

<style lang="scss" scoped>
.statstics-wrapper{
  padding: 24px;
}
.statistics-chart {
  width: 100%;
}
</style>
