<script setup>
import { Line, Column, Pie } from '@antv/g2plot'
import { queryChartsData } from '@vue2-client/services/api/common'
import { ref, onUnmounted, onMounted, watch } from 'vue'
import { colorItems } from './constants'
import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'

const errorMsg = ref([])
const loading = ref(false)
const empty = ref(false)
let plot = null

// 接收props中的传参
const props = defineProps({
  config: {
    type: Object,
    default: () => {}
  },
  requestParameters: {
    type: Object,
    default: () => {}
  },
  isDev: {
    type: Boolean,
    default: false
  },
  chatsKey: {
    type: [String, Number],
    default: ''
  }
})
// 添加验证函数
const validateConfig = (config, requestParameters) => {
  const errors = []
  // 基础验证
  if (!config.type || !config.dataSource) {
    errors.push('图表类型或数据源未配置')
  }
  if (!config.xField) {
    errors.push('请选择横轴字段')
  }
  // yFieldType 验证
  if (config.yFieldType === 'sum') {
    if (!config.yField || config.yField.length === 0) {
      errors.push('请至少添加一个统计字段')
    }
    if (config.yField.some((field) => !field.field)) {
      errors.push('存在未选择的统计字段')
    }
  }
  if (errors.length === 0 && config?.customFunction) {
    const result = executeStrFunctionByContext(this, config.customFunction, [config, requestParameters])
    // 判断 result 是否为数组
    if (Array.isArray(result)) {
      errors.push(...result)
    }
  }
  return errors
}

// 添加排序处理函数
const sortData = (data, config) => {
  const { xFieldSortBy, xFieldSortType, xField, yField } = config

  return [...data].sort((a, b) => {
    let compareResult = 0

    switch (xFieldSortBy) {
      case 'xValue':
        // 按横轴值排序
        compareResult = a[xField] < b[xField] ? -1 : 1
        break
      case 'yValue':
        // 按纵轴值排序
      {
        const yFieldName =
          typeof yField === 'string' ? yField : yField?.[0]?.field
        compareResult = parseFloat(a[yFieldName]) - parseFloat(b[yFieldName])
      }
        break
      default:
        compareResult = a[xField] < b[xField] ? -1 : 1
    }

    // 处理排序方向
    return xFieldSortType === 'asc' ? compareResult : -compareResult
  })
}

// 根据类型创建对应的图表实例
const createPlot = (type, container, options) => {
  switch (type) {
    case 'line':
      return new Line(container, options)
    case 'bar':
      return new Column(container, options)
    case 'pie':
      return new Pie(container, {
        ...options,
        // 饼图特殊配置
        angleField: options.yField,
        colorField: options.xField,
      })
    default:
      return new Line(container, options)
  }
}

// 修改错误边界处理
const handleError = (error) => {
  errorMsg.value = Array.isArray(error) ? error : ['图表渲染失败']
  // 出错时销毁图表实例
  if (plot) {
    plot.destroy()
    plot = null
  }
  loading.value = false
}

/**
 * 初始化
 * @param config 图表配置
 * @param requestParameters 查询参数
 */
const init = (config = {}, requestParameters = {}) => {
  try {
    loading.value = true
    empty.value = false
    errorMsg.value = []

    const errors = validateConfig(config, requestParameters)
    if (errors.length > 0) {
      handleError(errors)
      return
    }

    // 处理请求参数，移除循环引用
    const sanitizedConfig = JSON.parse(JSON.stringify({
      ...config,
      chartsConfigArray: undefined // 移除可能导致循环引用的属性
    }))

    const sanitizedParams = JSON.parse(JSON.stringify({
      conditionParams: {},
      chartsConfigArray: undefined,
      ...requestParameters
    }))

    // 验证通过后进行数据请求和图表渲染
    queryChartsData({ config: sanitizedConfig, requestParameters: sanitizedParams, preview: true }, config.serviceName, props.isDev)
      .then((res) => {
        const xField =
          config.dataSource === 'curCrud'
            ? config.xField.replace('.', '_')
            : config.xField

        const yFieldConfig = config.yField?.[0]
        const yField =
          config.dataSource === 'curCrud'
            ? yFieldConfig?.field.replace('.', '_')
            : yFieldConfig?.field

        // 对数据进行排序
        const sortedData = sortData(res, {
          ...config,
          xField,
          yField,
        })

        const baseOptions = {
          data: sortedData,
          xField: xField,
          yField: 'value',
          meta: {
            [yField]: {
              alias: yFieldConfig?.label || yFieldConfig?.field
            }
          },
          seriesField: 'series',
          title: {
            visible: true,
            text: config.title,
          },
          description: {
            visible: true,
            text: config.description,
          },
          // 修改图表工具的配置方式
          label: config.chartsTools.includes('label')
            ? {
              visible: true,
              autoHide: true,
              style: {
                fontSize: 12,
              },
            }
            : false,
          point: config.chartsTools.includes('point')
            ? {
              visible: true,
              size: 4,
            }
            : false,
          xAxis: config.chartsTools.includes('xyVisible')
            ? {
              visible: true,
              label: {
                offset: 12,
                autoRotate: true,
                autoHide: true,
                rotate: 0.3
              },
            }
            : {
              visible: false,
            },
          yAxis: config.chartsTools.includes('xyVisible')
            ? {
              visible: true,
            }
            : {
              visible: false,
            },
          legend: config.chartsTools.includes('legend')
            ? {
              visible: true,
              position: 'top-left',
              marker: {
                symbol: 'circle',
              },
              itemName: {
                style: {
                  fill: '#333',
                }
              }
            }
            : false,
          grid: config.chartsTools.includes('grid')
            ? {
              visible: true,
            }
            : {
              visible: false,
            },
          forceFit: true,
          padding: 'auto',
          // 添加主题色配置
          color: config.colorIndex !== undefined ? colorItems[config.colorIndex].map(item => item.color) : undefined,

          // 为饼图特别设置颜色
          pieStyle: config.type === 'pie' ? {
            stroke: 'white',
            lineWidth: 1,
          } : undefined,
          theme: {
            colors10: config.colorIndex !== undefined ? colorItems[config.colorIndex].map(item => item.color) : undefined,
          },
        }
        // 如果data 超过 50 增加缩略图
        if (sortedData.length > 500) {
          baseOptions.slider = {
            start: 0,
            end: 0.2,
          }
        } else if (sortedData.length > 200) {
          baseOptions.slider = {
            start: 0,
            end: 0.4,
          }
        } else if (sortedData.length > 100) {
          baseOptions.slider = {
            start: 0,
            end: 0.6,
          }
        } else if (sortedData.length > 50) {
          baseOptions.slider = {
            start: 0,
            end: 0.8,
          }
        }
        if (config.type !== 'pie') {
          baseOptions.isGroup = true
        }
        if (sortedData.length === 0) {
          empty.value = true
          return
        }
        // 如果实例存在且类型相同,只更新配置
        if (plot && plot.constructor.name.toLowerCase() === config.type) {
          try {
            plot.update({
              ...baseOptions,
              // 其他配置保持不变
              ...plot.options,
              // 需要更新的配置
              data: sortedData,
              xField,
              yField: 'value',
              meta: baseOptions.meta
            })
          } catch (error) {
            handleError(error)
          }
        } else {
          // 如果实例不存在或类型不同,需要重新创建
          if (plot) {
            plot.destroy()
          }
          plot = createPlot(
            config.type,
            document.getElementById(`container${props.chatsKey}`),
            baseOptions
          )
          plot.render()
        }
      })
      .catch(error => {
        handleError(error)
      })
      .finally(() => {
        loading.value = false
      })
  } catch (error) {
    handleError(error)
  }
}

// 组件卸载时清理图表实例
onUnmounted(() => {
  if (plot) {
    plot.destroy()
  }
})

// 添加对 props 的监听
watch(
  [() => props.config, () => props.requestParameters],
  ([newConfig, newRequestParameters]) => {
    init(newConfig, newRequestParameters)
  },
  {
    deep: true
  }
)

onMounted(() => {
  init(props.config, props.requestParameters)
})

defineExpose({ init })
</script>

<template>
  <div
    :id="`container${chatsKey}`"
    style="height: 100%"
  >
    <a-spin :spinning="loading">
      <a-result
        v-if="errorMsg.length > 0"
        status="warning"
        title="图表构建错误"
        sub-title="配置不完善或者数据源格式错误，请检查"
      >
        <div
          class="desc"
          style="text-align: center"
        >
          <p
            v-for="(item, index) in errorMsg"
            :key="index"
          >
            <a-icon
              :style="{ color: 'red' }"
              type="close-circle"
            />
            {{ item }}
          </p>
        </div>
      </a-result>
      <a-empty v-else-if="empty"/>
    </a-spin>
  </div>
</template>

<style scoped lang="less">
.custom-chart-title {
  font-size: 16px;
  font-weight: 500;
  margin-bottom: 8px;
}

.custom-chart-desc {
  font-size: 12px;
  color: rgba(0, 0, 0, .45);
  margin-bottom: 16px;
}</style>
