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

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',
  }
}

const transformData = (data: any[], yField: string[], yRule: string, ySort: string, xField: string = '') => {
  let transformedData = [...data]

  // Apply calculation rule
  if (yRule) {
    // Group data by xField if it exists
    const groupedData = xField
      ? transformedData.reduce((acc: Record<string, any[]>, item) => {
          const key = item[xField]
          if (!acc[key]) {
            acc[key] = []
          }
          acc[key].push(item)
          return acc
        }, {})
      : { all: transformedData }

    // Calculate results for each group
    transformedData = Object.entries(groupedData).map(([, group]) => {
      const newItem = { ...group[0] }
      yField.forEach((field) => {
        const values = group.map((d) => parseFloat(d[field]) || 0)
        let result = 0
        switch (yRule) {
          case 'sum':
            result = Number(values.reduce((a, b) => a + b, 0).toFixed(2))
            break
          case 'avg':
            result = Number((values.reduce((a, b) => a + b, 0) / values.length).toFixed(2))
            break
          case 'count':
            result = values.length
            break
          case 'max':
            result = Number(Math.max(...values).toFixed(2))
            break
          case 'min':
            result = Number(Math.min(...values).toFixed(2))
            break
          case 'median': {
            const sorted = [...values].sort((a, b) => a - b)
            const mid = Math.floor(sorted.length / 2)
            result = Number((sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]).toFixed(2))
            break
          }
          case 'variance': {
            const mean = values.reduce((a, b) => a + b, 0) / values.length
            result = Number((values.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / values.length).toFixed(2))
            break
          }
        }
        newItem[field] = result
      })
      return newItem
    })
  }

  // Apply sorting rule
  if (ySort) {
    const [sortType, topN] = ySort.split('Top')
    if (sortType) {
      transformedData.sort((a, b) => {
        const aValue = parseFloat(a[yField[0]]) || 0
        const bValue = parseFloat(b[yField[0]]) || 0
        return sortType === 'asc' ? aValue - bValue : bValue - aValue
      })
    }
    if (topN) {
      const n = parseInt(topN)
      transformedData = transformedData.slice(0, n)
    }
  }

  return transformedData
}

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

  const datalist = transformData(data.list, yField, yRule, ySort, xField)

  const dataset = { dimensions: [xField, ...yField].filter(Boolean), source: datalist }

  const fieldColorMap = fieldColors.reduce((acc: Record<string, string>, item: any) => {
    if (item.field && item.color) {
      acc[item.field] = item.color
    }
    return acc
  }, {})
  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 datalist[params.dataIndex][labelField]
            },
          },
          itemStyle: { borderRadius, color: fieldColorMap[field] || 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) => datalist[params.dataIndex][labelField],
          },
        })),
      })
      break
    // 饼状图
    case '3':
      defaultOptions = merge(defaultOptions, {
        dataset,
        xAxis: { show: false },
        yAxis: { show: false },
        series: yField.map((field) => ({
          name: getFieldName(field),
          type: 'pie',
          label: {
            show: !!labelField,
            position: 'outside',
            formatter: (params: any) => datalist[params.dataIndex][labelField],
          },
        })),
      })
      break
    // 雷达图
    case '4':
      defaultOptions = merge(defaultOptions, {
        xAxis: { show: false },
        yAxis: { show: false },
        radar: {
          shape: 'polygon',
          indicator: datalist.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 datalist[params.dataIndex][labelField]
              },
            },
            data: yField.map((field) => ({
              value: datalist.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) => datalist[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) => {
          const maxVal = Math.max(...datalist.map((item: any) => item[field]))
          const minVal = Math.min(...datalist.map((item: any) => item[field]))
          return {
            type: 'graph',
            layout: 'force',
            roam: true,
            force: {
              repulsion: 150,
              gravity: 0.05,
              edgeLength: 20,
            },
            data: datalist.map((item: any) => {
              const size = 20 + ((parseFloat(item[field]) - minVal) / (maxVal - minVal || 1)) * 60 // 字体大小映射
              const value = item[field] || 10
              const name = item[xField]
              return {
                name,
                value,
                symbolSize: size,
                label: {
                  show: !!labelField,
                  position: 'inside',
                  fontSize: size / 4,
                  formatter: (params: any) => datalist[params.dataIndex][labelField],
                },
              }
            }),
          }
        }),
      })
      break
    }
    // 词云
    case '7':
      defaultOptions = merge(defaultOptions, {
        series: [
          {
            type: 'wordCloud',
            shape: 'circle',
            data: datalist.map((item: any) => ({
              name: item[labelField],
              value: item[yField[0]],
            })),
          },
        ],
      })
      break
    // 地图
    case '8':
      defaultOptions.series = [{ type: 'map' }]
      break
    // 指标卡
    case '9': {
      const count = datalist.reduce((acc: any, item: any) => acc + parseFloat(item[yField[0]]), 0).toFixed(2)
      defaultOptions = merge(defaultOptions, {
        graphic: {
          elements: [
            {
              type: 'text',
              left: 'center',
              top: 'middle',
              style: {
                text: count,
                fontSize: 36,
                fontWeight: 'bold',
                fill: color,
              },
            },
          ],
        },
      })
      break
    }
    // 漏斗图
    case '10': {
      defaultOptions = merge(defaultOptions, {
        dataset,
        xAxis: { show: false },
        yAxis: { show: false },
        series: [
          {
            type: 'funnel',
            name: getFieldName(yField[0]),
            left: '10%',
            top: 60,
            bottom: 60,
            width: '80%',
            min: 0,
            max: Math.max(...datalist.map((item: any) => item[yField[0]] || 0)),
            minSize: '0%',
            maxSize: '100%',
            sort: 'descending',
            gap: 2,
            label: {
              show: !!labelField,
              position: 'inside',
              formatter: (params: any) => datalist[params.dataIndex][labelField],
            },
          },
        ],
      })
      break
    }
    // 直方图
    case '11':
      defaultOptions = merge(defaultOptions, {
        dataset,
        xAxis: { type: 'category' },
        series: yField.map((field) => ({
          type: 'bar',
          name: getFieldName(field),
          label: {
            show: !!labelField,
            position: 'top',
            formatter: (params: any) => {
              return datalist[params.dataIndex][labelField]
            },
          },
          itemStyle: { borderRadius, color: itemStyleColor },
        })),
      })
      break
    // 表格
    case '12': {
      const columns = yField.map((field) => ({ title: getFieldName(field), dataIndex: field }))
      return <Table rowKey="pk_id" dataSource={datalist} columns={columns} />
    }
    // 帕累托图
    case '13': {
      const paretoData = [...datalist].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) => datalist[params.dataIndex - 1]?.[labelField] },
          data: datalist.map((item: any) => ({ name: item[xField], value: item[field] || 0 })),
        })),
      })
      break
    }
    default:
      defaultOptions.series = [{ type: 'bar' }]
  }
  const options = merge(props, defaultOptions)
  console.log(options)
  return <ReactECharts option={options} notMerge={true} lazyUpdate={true} style={style} />
}
