import {
  G2PlotChartView,
  G2PlotDrawOptions
} from '@/views/chart/components/js/panel/types/impl/g2plot'
import type { Heatmap, HeatmapOptions } from '@antv/g2plot/esm/plots/heatmap'
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util'
import { useI18n } from '@/hooks/web/useI18n'
import { deepCopy } from '@/utils/utils'
import { cloneDeep } from 'lodash-es'
import {
  configAxisLabelLengthLimit,
  getPadding,
  getXAxis,
  getYAxis
} from '@/views/chart/components/js/panel/common/common_antv'
import { valueFormatter } from '@/views/chart/components/js/formatter'

const { t } = useI18n()
const DEFAULT_DATA = []
/**
 * 热力图
 */
export class TableHeatmap extends G2PlotChartView<HeatmapOptions, Heatmap> {
  properties: EditorProperty[] = [
    'basic-style-selector',
    'background-overall-component',
    'label-selector',
    'legend-selector',
    'x-axis-selector',
    'y-axis-selector',
    'title-selector',
    'tooltip-selector',
    'jump-set',
    'linkage',
    'border-style'
  ]
  propertyInner: EditorPropertyInner = {
    'background-overall-component': ['all'],
    'basic-style-selector': ['colors'],
    'label-selector': ['fontSize', 'color', 'labelFormatter'],
    'x-axis-selector': ['name', 'color', 'fontSize', 'position', 'axisLabel', 'axisLine'],
    'y-axis-selector': [
      'name',
      'color',
      'fontSize',
      'position',
      'axisLabel',
      'axisLine',
      'showLengthLimit'
    ],
    'title-selector': [
      'title',
      'fontSize',
      'color',
      'hPosition',
      'isItalic',
      'isBolder',
      'remarkShow',
      'fontFamily',
      'letterSpace',
      'fontShadow'
    ],
    'legend-selector': ['orient', 'color', 'fontSize', 'hPosition', 'vPosition'],
    'tooltip-selector': ['show', 'color', 'fontSize', 'backgroundColor', 'tooltipFormatter'],
    'border-style': ['all']
  }
  axis: AxisType[] = ['xAxis', 'xAxisExt', 'extColor', 'filter']
  axisConfig: AxisConfig = {
    xAxis: {
      name: `${t('chart.x_axis')} / ${t('chart.dimension')}`,
      type: 'd',
      limit: 1
    },
    xAxisExt: {
      name: `${t('chart.y_axis')} / ${t('chart.dimension')}`,
      type: 'd',
      limit: 1
    },
    extColor: {
      name: `${t('chart.color')} / ${t('chart.dimension_or_quota')}`,
      limit: 1
    }
  }
  protected getDefaultLength = (chart, l) => {
    const containerDom = document.getElementById(chart.container)
    const containerHeight = containerDom?.clientHeight || 100
    const containerWidth = containerDom?.clientWidth || 100
    let defaultLength = containerHeight - containerHeight * 0.5
    if (l.orient !== 'vertical') {
      defaultLength = containerWidth - containerWidth * 0.5
    }
    return defaultLength
  }
  protected sortData = (fieldObj, data) => {
    const { deType, sort, customSort } = fieldObj

    if (sort === 'desc') {
      if (deType === 0) {
        return data.sort().reverse()
      } else {
        return data.sort((a, b) => b - a)
      }
    } else if (sort === 'asc') {
      if (deType === 0) {
        return data.sort()
      } else {
        return data.sort((a, b) => a - b)
      }
    }

    // 如果没有指定排序方式，直接返回原始数据或 customSort
    return customSort && customSort.length > 0 ? customSort : data
  }
  async drawChart(drawOptions: G2PlotDrawOptions<Heatmap>): Promise<Heatmap> {
    const { chart, container, action } = drawOptions
    const xAxis = deepCopy(chart.xAxis)
    const xAxisExt = deepCopy(chart.xAxisExt)
    const extColor = deepCopy(chart.extColor)
    if (!xAxis?.length || !xAxisExt?.length || !extColor?.length) {
      return
    }
    const xField = xAxis[0].dataeaseName
    const xFieldExt = xAxisExt[0].dataeaseName
    const extColorField = extColor[0].dataeaseName
    // data
    const tmpData = cloneDeep(chart.data.tableRow)
    const data =
      tmpData?.filter(cell => cell[xField] && cell[xFieldExt] && cell[extColorField]) || []
    data?.forEach(i => {
      Object.keys(i).forEach(key => {
        if (key === '*') {
          i['@'] = i[key]
        }
      })
    })

    // options
    const initOptions: HeatmapOptions = {
      data: data,
      xField: xField,
      yField: xFieldExt,
      colorField: extColorField === '*' ? '@' : extColorField,
      appendPadding: getPadding(chart),
      meta: {
        [xField]: {
          type: 'cat',
          values: this.sortData(xAxis[0], [...new Set(data.map(i => i[[xField]]))])
        },
        [xFieldExt]: {
          type: 'cat',
          values: this.sortData(xAxisExt[0], [...new Set(data.map(i => i[[xFieldExt]]))]).reverse()
        }
      },
      legend: {
        layout: 'vertical',
        position: 'right',
        slidable: true,
        label: {
          align: 'left',
          spacing: 10
        }
      }
    }
    chart.container = container
    const options = this.setupOptions(chart, initOptions)
    const { Heatmap } = await import('@antv/g2plot/esm/plots/heatmap')
    const newChart = new Heatmap(container, options)
    newChart.on('plot:click', param => {
      if (!param.data?.data) {
        return
      }
      const pointData = param.data.data
      const dimensionList = []
      chart.data.fields.forEach(item => {
        Object.keys(pointData).forEach(key => {
          if (key.startsWith('f_') && item.dataeaseName === key) {
            dimensionList.push({
              id: item.id,
              dataeaseName: item.dataeaseName,
              value: pointData[key]
            })
          }
        })
      })
      action({
        x: param.data.x,
        y: param.data.y,
        data: {
          data: {
            ...param.data.data,
            value: dimensionList[1].value,
            name: dimensionList[1].id,
            dimensionList: dimensionList,
            quotaList: [dimensionList[1]]
          }
        }
      })
    })
    newChart.on('afterrender', ev => {
      const l = JSON.parse(JSON.stringify(parseJson(chart.customStyle).legend))
      if (l.show) {
        const rail = ev.view.getController('legend').option[extColor[0].dataeaseName]?.['rail']
        if (rail) {
          rail.defaultLength = this.getDefaultLength(chart, l)
        }
      }
    })
    configAxisLabelLengthLimit(chart, newChart)
    return newChart
  }

  protected configTheme(chart: Chart, options: HeatmapOptions): HeatmapOptions {
    const tmp = super.configTheme(chart, options)
    tmp.theme.innerLabels.offset = 0
    return tmp
  }

  protected configBasicStyle(chart: Chart, options: HeatmapOptions): HeatmapOptions {
    const basicStyle = parseJson(chart.customAttr).basicStyle
    const color = basicStyle.colors?.map(ele => {
      return hexColorToRGBA(ele, basicStyle.alpha)
    })
    return {
      ...options,
      color
    }
  }
  protected configTooltip(chart: Chart, options: HeatmapOptions): HeatmapOptions {
    let tooltip
    let customAttr: DeepPartial<ChartAttr>
    if (chart.customAttr) {
      customAttr = parseJson(chart.customAttr)
      // tooltip
      if (customAttr.tooltip) {
        const extColor = deepCopy(chart.extColor)
        const xAxisExt = deepCopy(chart.xAxisExt)
        const tooltipFiledList = [xAxisExt, extColor]
        const t = JSON.parse(JSON.stringify(customAttr.tooltip))
        if (t.show) {
          tooltip = {
            showTitle: true,
            customItems(originalItems) {
              const items = []
              const createItem = (fieldObj, items, originalItems) => {
                const name = fieldObj?.chartShowName ? fieldObj?.chartShowName : fieldObj?.name
                let value = originalItems[0].data[fieldObj.dataeaseName]
                if (!isNaN(Number(value))) {
                  value = valueFormatter(value, customAttr.tooltip.tooltipFormatter)
                }
                items.push({
                  ...originalItems[0],
                  name: name,
                  value: value
                })
              }
              tooltipFiledList.forEach(field => {
                createItem(field[0], items, originalItems)
              })
              return items
            }
          }
        } else {
          tooltip = false
        }
      }
    }
    return {
      ...options,
      tooltip
    }
  }

  protected configXAxis(chart: Chart, options: HeatmapOptions): HeatmapOptions {
    const xAxis = getXAxis(chart)
    return {
      ...options,
      xAxis: xAxis ? { ...xAxis, grid: null } : false
    }
  }

  protected configYAxis(chart: Chart, options: HeatmapOptions): HeatmapOptions {
    const yAxis = getYAxis(chart)
    return {
      ...options,
      yAxis: yAxis ? { ...yAxis, grid: null } : false
    }
  }

  protected configLegend(chart: Chart, options: HeatmapOptions): HeatmapOptions {
    const tmpOptions = super.configLegend(chart, options)
    if (tmpOptions.legend) {
      const l = JSON.parse(JSON.stringify(parseJson(chart.customStyle).legend))
      tmpOptions.legend.slidable = true
      tmpOptions.legend.minHeight = 10
      tmpOptions.legend.minWidth = 10
      tmpOptions.legend.maxHeight = 600
      tmpOptions.legend.maxWidth = 600
      const containerDom = document.getElementById(chart.container)
      const containerHeight = containerDom?.clientHeight || 100
      const containerWidth = containerDom?.clientWidth || 100
      let defaultLength = containerHeight - containerHeight * 0.5
      if (l.orient === 'vertical') {
        tmpOptions.legend.offsetY = -5
      } else {
        defaultLength = containerWidth - containerWidth * 0.5
      }
      tmpOptions.legend.rail = { defaultLength: defaultLength }
      tmpOptions.legend.label = {
        spacing: 10,
        style: {
          fill: l.color,
          fontSize: l.fontSize
        }
      }
    }
    return tmpOptions
  }

  setupDefaultOptions(chart: ChartObj): ChartObj {
    chart.customStyle.legend.orient = 'vertical'
    chart.customStyle.legend.vPosition = 'center'
    chart.customStyle.legend.hPosition = 'right'
    chart.customStyle.legend['rail'] = { defaultLength: 100 }
    return chart
  }

  protected configLabel(chart: Chart, options: HeatmapOptions): HeatmapOptions {
    const tmpOptions = super.configLabel(chart, options)
    if (tmpOptions.label) {
      const extColor = deepCopy(chart.extColor)
      const { label: labelAttr } = parseJson(chart.customAttr)
      const layout = []
      if (!tmpOptions.label.fullDisplay) {
        layout.push(...tmpOptions.label.layout)
      }
      const label = {
        ...tmpOptions.label,
        position: 'middle',
        layout,
        formatter: data => {
          const value = data[extColor[0]?.dataeaseName]
          if (!isNaN(Number(value))) {
            return valueFormatter(value, labelAttr.labelFormatter)
          }
          return value
        }
      }
      return {
        ...tmpOptions,
        label
      }
    }
    return tmpOptions
  }

  protected setupOptions(chart: Chart, options: HeatmapOptions): HeatmapOptions {
    return flow(
      this.configTheme,
      this.configXAxis,
      this.configYAxis,
      this.configBasicStyle,
      this.configLegend,
      this.configTooltip,
      this.configLabel
    )(chart, options)
  }

  constructor() {
    super('t-heatmap', DEFAULT_DATA)
  }
}
