import ReactECharts from 'echarts-for-react'
import { useDataQuery, useDataFieldQuery } from '@/hooks/useQuery'
import { merge } from 'lodash-es'
import { Table } from 'antd'

const usePattern = (type = 'horizontal', color = '#5470C6') => {
  const createPattern = () => {
    const canvas = document.createElement('canvas')
    canvas.width = 10
    canvas.height = 10
    const ctx: any = canvas.getContext('2d')

    ctx.strokeStyle = color
    ctx.lineWidth = 2
    ctx.beginPath()

    switch (type) {
      case 'horizontal':
        ctx.moveTo(0, 5)
        ctx.lineTo(10, 5)
        break
      case 'vertical':
        ctx.moveTo(5, 0)
        ctx.lineTo(5, 10)
        break
      case 'diagonal':
        ctx.moveTo(0, 0)
        ctx.lineTo(10, 10)
        break
      case 'reverse-diagonal':
        ctx.moveTo(0, 10)
        ctx.lineTo(10, 0)
        break
      default:
        ctx.moveTo(0, 5)
        ctx.lineTo(10, 5)
    }

    ctx.stroke()
    return canvas
  }

  return {
    image: createPattern(),
    repeat: 'repeat',
  }
}

export default function Chart({
  type = '1',
  labelField = '',
  xField = '',
  yField = [],
  borderRadius = 0,
  color = 'auto',
  fillPattern = 'solid',
  style = { height: '400px', width: '100%' },
  ...props
}) {
  const { data } = useDataQuery()
  const { getFieldName } = useDataFieldQuery()
  const { image, repeat } = usePattern(fillPattern)
  const itemStyleColor = fillPattern === 'solid' ? color : { image, repeat }
  if (!yField) {
    return null
  }

  const dataset = { dimensions: [xField, ...yField], source: data.list }
  let defaultOptions: any = {
    legend: {},
    tooltip: {},
    yAxis: {},
    xAxis: {},
    series: [],
  }

  switch (type) {
    // 柱状图
    case '1':
      defaultOptions = merge(defaultOptions, {
        dataset,
        xAxis: { type: 'category' },
        series: yField.map((field) => ({
          type: 'bar',
          name: getFieldName(field),
          label: {
            show: !!labelField,
            position: 'top',
            formatter: (params: any) => {
              console.log(params.dataIndex)
              return data.list[params.dataIndex][labelField]
            },
          },
          itemStyle: { borderRadius, color: itemStyleColor },
        })),
      })
      break
    // 折线图
    case '2':
      defaultOptions = merge(defaultOptions, {
        dataset,
        xAxis: { type: 'category' },
        series: yField.map((field) => ({
          type: 'line',
          name: getFieldName(field),
          label: {
            show: !!labelField,
            position: 'top',
            formatter: (params: any) => data.list[params.dataIndex][labelField],
          },
        })),
      })
      break
    // 饼状图
    case '3':
      defaultOptions = merge(defaultOptions, {
        dataset,
        xAxis: { show: false },
        yAxis: { show: false },
        series: yField.map(() => ({
          type: 'pie',
          label: {
            show: !!labelField,
            position: 'outside',
            formatter: (params: any) => data.list[params.dataIndex][labelField],
          },
        })),
      })
      break
    // 雷达图
    case '4':
      defaultOptions = merge(defaultOptions, {
        xAxis: { show: false },
        yAxis: { show: false },
        radar: {
          shape: 'polygon',
          indicator: data.list.map((item: any) => ({
            name: item[xField],
            max: Math.max(...yField.map((field) => item[field])) + 100,
          })),
        },
        series: [
          {
            type: 'radar',
            label: {
              show: !!labelField,
              formatter(params: any) {
                return data.list[params.dataIndex][labelField]
              },
            },
            data: yField.map((field) => ({
              value: data.list.map((item: any) => item[field]),
              name: getFieldName(field),
            })),
          },
        ],
      })
      break
    // 散点图
    case '5':
      defaultOptions = merge(defaultOptions, {
        dataset,
        yAxis: { show: true, type: 'value' },
        xAxis: { show: true, type: xField ? 'category' : 'value' },
        series: yField.map((field) => ({
          type: 'scatter',
          name: getFieldName(field),
          symbolSize: 10,
          label: {
            show: !!labelField,
            position: 'top',
            formatter: (params: any) => data.list[params.dataIndex][labelField],
          },
        })),
      })
      break
    // 气泡图
    case '6':
      defaultOptions = merge(defaultOptions, {
        yAxis: { show: false },
        xAxis: { show: false },
        tooltip: {
          formatter: (params: any) => {
            if (params.dataType === 'node') {
              return `${params.name}: ${params.value}`
            }
            return ''
          },
        },
        series: yField.map((field) => ({
          type: 'graph',
          layout: 'force',
          roam: true,
          label: {
            show: true,
            position: 'right',
            formatter: '{b}',
          },
          force: {
            repulsion: 100,
            edgeLength: 30,
            gravity: 0.1,
          },
          emphasis: {
            focus: 'self',
            label: {
              show: true,
              fontSize: 14,
            },
          },
          data: data.list.map((item: any) => {
            const value = item[field] || 10
            const name = item[xField]
            return { name, value }
          }),
        })),
      })
      break
    // 词云
    case '7':
      defaultOptions = merge(defaultOptions, {
        tooltip: { show: true },
        series: [
          {
            type: 'wordCloud',
            shape: 'circle',
            sizeRange: [12, 60],
            rotationRange: [-90, 90],
            textStyle: {
              color: () =>
                'rgb(' +
                [
                  Math.round(Math.random() * 160),
                  Math.round(Math.random() * 160),
                  Math.round(Math.random() * 160),
                ].join(',') +
                ')',
            },
            emphasis: {
              focus: 'self',
              textStyle: {
                shadowBlur: 10,
                shadowColor: '#333',
              },
            },
          },
        ],
      })
      break
    // 地图
    case '8':
      defaultOptions.series = [{ type: 'map' }]
      break
    // 指标卡
    case '9':
      defaultOptions = merge(defaultOptions, {
        tooltip: {
          formatter: '{a} <br/>{b} : {c}%',
        },
        series: [
          {
            type: 'gauge',
            name: getFieldName(yField[0]),
            detail: { formatter: '{value}%' },
            axisLine: {
              lineStyle: {
                width: 10,
                color: [
                  [0.3, '#fd666d'],
                  [0.7, '#37a2da'],
                  [1, '#67e0e3'],
                ],
              },
            },
            pointer: {
              itemStyle: {
                color: 'auto',
              },
            },
            axisTick: {
              distance: -10,
              length: 8,
              lineStyle: {
                color: '#fff',
                width: 2,
              },
            },
            splitLine: {
              distance: -10,
              length: 10,
              lineStyle: {
                color: '#fff',
                width: 4,
              },
            },
            axisLabel: {
              color: 'inherit',
              distance: 20,
              fontSize: 12,
            },
            title: {
              offsetCenter: [0, '-20%'],
              fontSize: 14,
            },
          },
        ],
      })
      break
    // 漏斗图
    case '10':
      defaultOptions = merge(defaultOptions, {
        dataset,
        tooltip: { trigger: 'item', formatter: '{b} : {c}' },
        legend: {
          show: true,
          orient: 'vertical',
          left: 'left',
          data: data.list.map((item: any) => item[xField]),
        },
        series: [
          {
            type: 'funnel',
            name: getFieldName(yField[0]),
            left: '10%',
            top: 60,
            bottom: 60,
            width: '80%',
            min: 0,
            max: Math.max(...data.list.map((item: any) => item[yField[0]] || 0)),
            minSize: '0%',
            maxSize: '100%',
            sort: 'descending',
            gap: 2,
            label: {
              show: true,
              position: 'inside',
              formatter: '{b}',
            },
            labelLine: {
              length: 10,
              lineStyle: { width: 1, type: 'solid' },
            },
            itemStyle: {
              borderColor: '#fff',
              borderWidth: 1,
            },
            emphasis: {
              label: { fontSize: 20 },
            },
          },
        ],
      })
      break
    // 直方图
    case '11':
      defaultOptions = merge(defaultOptions, {
        tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
        xAxis: { type: 'category' },
        yAxis: { type: 'value', name: 'Frequency' },
        series: [
          {
            type: 'bar',
            name: `Histogram of ${getFieldName(yField[0])}`,
            barWidth: '99.3%',
            label: {
              show: !!labelField,
              position: 'top',
              formatter: (params: any) => data.list[params.dataIndex][labelField],
            },
            itemStyle: { color: itemStyleColor },
          },
        ],
      })
      break
    // 表格
    case '12': {
      const columns = yField.map((field) => ({
        title: getFieldName(field),
        dataIndex: field,
      }))
      return <Table dataSource={data.list} columns={columns} />
    }
    // 帕累托图
    case '13': {
      const paretoData = [...data.list].sort((a, b) => b[yField[0]] - a[yField[0]])
      const total = paretoData.reduce((sum, item) => sum + parseFloat(item[yField[0]]), 0)
      let cumulative = 0
      const cumulativeData = paretoData.map((item) => {
        cumulative += parseFloat(item[yField[0]])
        return {
          ...item,
          cumulative: ((cumulative / total) * 100).toFixed(2),
        }
      })

      defaultOptions = merge(defaultOptions, {
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'shadow' },
        },
        xAxis: {
          type: 'category',
          data: cumulativeData.map((item) => item[xField]),
        },
        yAxis: [
          {
            type: 'value',
            name: getFieldName(yField[0]),
          },
          {
            type: 'value',
            min: 0,
            max: 100,
            show: false,
          },
        ],
        series: [
          {
            name: getFieldName(yField[0]),
            type: 'bar',
            data: cumulativeData.map((item) => item[yField[0]]),
          },
          {
            type: 'line',
            yAxisIndex: 1,
            data: cumulativeData.map((item) => item.cumulative),
            symbol: 'circle',
            symbolSize: 8,
            smooth: true,
            lineStyle: { width: 2 },
            markLine: {
              symbol: 'none',
              label: {
                formatter: '80%',
                position: 'end',
              },
              data: [
                {
                  yAxis: 80,
                },
              ],
            },
          },
        ],
      })
      break
    }
    // 矩形树图
    case '14': {
      defaultOptions = merge(defaultOptions, {
        xAxis: { show: false },
        yAxis: { show: false },
        legend: { selectedMode: 'single' },
        series: yField.map((field) => ({
          name: getFieldName(field),
          type: 'treemap',
          label: { show: !!labelField, formatter: (params: any) => data.list[params.dataIndex - 1]?.[labelField] },
          data: data.list.map((item: any) => ({ name: item[xField], value: item[field] || 0 })),
        })),
      })
      break
    }
    default:
      defaultOptions.series = [{ type: 'bar' }]
  }
  const options = merge(props, defaultOptions)

  return <ReactECharts option={options} notMerge={true} lazyUpdate={true} style={style} />
}
