<template>
  <div class="echarts-wrapper">
    <!-- 加载状态 -->
    <div v-if="loading" class="loading-mask">
      <div class="loading-spinner"></div>
    </div>

    <div
      ref="chartRef"
      :style="{
        width: width,
        height: height,
        minHeight: '100px'
      }"
      class="echarts-container"
    />
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch, computed } from 'vue'
import * as echarts from 'echarts'
import debounce from 'lodash/debounce'

// Props 定义
const props = defineProps({
  // 图表数据
  data: {
    type: Array,
    required: true
  },
  // 图表类型配置
  config: {
    type: Object,
    default: () => ({})
  },
  // 标题
  title: {
    type: String,
    default: ''
  },
  // 图表主题
  theme: {
    type: String,
    default: ''
  },
  // 图表宽度
  width: {
    type: String,
    default: '100%'
  },
  // 图表高度
  height: {
    type: String,
    default: '400px'
  },
  // 是否自动调整大小
  autoResize: {
    type: Boolean,
    default: true
  },
  // 加载状态
  loading: {
    type: Boolean,
    default: false
  },
  // 动画时长
  animationDuration: {
    type: Number,
    default: 1000
  },
  // 是否平滑曲线(用于折线图)
  smooth: {
    type: Boolean,
    default: false
  },
  // 图表类型
  chartType: {
    type: String,
    default: 'line',
    validator: (value) => ['line', 'bar', 'pie', 'scatter'].includes(value)
  },
  // tooltip 显示的系列名称数组,为空则显示全部
  tooltipSeries: {
    type: Array,
    default: () => []
  },
  // 自定义 tooltip 格式化函数
  tooltipFormatter: {
    type: Function,
    default: null
  }
})

// Emits 定义
const emit = defineEmits(['chartReady', 'click', 'legendselectchanged'])

const chartRef = ref(null)
let chartInstance = null

// 默认配置
const defaultConfig = {
  xField: 'name',
  series: [
    {
      name: '数值',
      field: 'value',
      type: 'bar'
    }
  ],
  yAxis: [
    {
      name: '',
      min: 0
    }
  ]
}

// 合并配置
const mergedConfig = computed(() => ({
  ...defaultConfig,
  ...props.config
}))

// 生成图表配置
const generateOptions = computed(() => {
  if (!props.data?.length) return {}

  const config = mergedConfig.value
  const categories = props.data.map(item => item[config.xField])

  // 处理系列数据
  const series = config.series
    .filter(s => s.show !== false)  // 过滤掉 show: false 的系列
    .map(s => ({
      name: s.name,
      type: s.type,
      yAxisIndex: s.yAxisIndex || 0,
      data: props.data.map(item => item[s.field]),
      color: s.color,
      barMaxWidth: 50,
      barGap: '30%',
      itemStyle: {
        color: s.color,
        borderRadius: s.type === 'bar' ? [4, 4, 0, 0] : 0
      },
      label: s.showLabel ? {
        show: true,
        position: s.type === 'line' ? 'top' : 'inside',
        formatter: s.labelFormatter || '{c}',
        fontSize: 12,
        color: s.type === 'line' ? s.color : '#fff'
      } : undefined,
      emphasis: {
        focus: 'series'
      }
    }))

  return {
    title: props.title ? {
      text: props.title
    } : null,
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      },
      formatter: (params) => {
        // 找到原始配置中对应的系列配置
        const validParams = params.filter(param => {
          const seriesConfig = config.series.find(s => s.name === param.seriesName)
          return seriesConfig && seriesConfig.tooltip?.show !== false
        })

        if (validParams.length === 0) return ''

        let result = `${validParams[0].axisValue}<br/>`
        validParams.forEach(param => {
          // 找到对应的系列配置
          const seriesConfig = config.series.find(s => s.name === param.seriesName)
          // 提取 labelFormatter 中的单位
          let unit = ''
          if (seriesConfig?.labelFormatter) {
            const match = seriesConfig.labelFormatter.match(/\{c\}(.+)/)
            if (match) {
              unit = match[1]
            }
          }
          result += `${param.marker}${param.seriesName}: ${param.value}${unit}<br/>`
        })

        return result
      }
    },
    legend: {
      data: series.map(s => s.name)
    },
    xAxis: {
      type: 'category',
      data: categories,
      axisLabel: {
        interval: 0,
        rotate: categories.length > 5 ? 30 : 0
      }
    },
    yAxis: config.yAxis.map((axis, index) => ({
      type: 'value',
      name: axis.name,
      min: axis.min,
      max: axis.max,
      position: index === 0 ? 'left' : 'right',
      splitLine: {
        show: index === 0
      },
      axisLabel: axis.axisLabel ? {
        formatter: axis.axisLabel
      } : undefined
    })),
    series,
    grid: {
      top: '15%',
      bottom: '15%',
      left: '10%',
      right: '10%',
      containLabel: true
    }
  }
})

// 初始化图表
const initChart = () => {
  if (!chartRef.value) return

  chartInstance = echarts.init(chartRef.value, props.theme)
  chartInstance.setOption(generateOptions.value)
  emit('chartReady', chartInstance)
}

// 更新图表
const updateChart = () => {
  if (!chartInstance) return
  chartInstance.setOption(generateOptions.value)
}

// 调整图表大小
const resizeChart = debounce(() => {
  if (!chartInstance) return
  chartInstance.resize()
}, 100)

// 监听配置变化
watch(
  () => [props.data, props.config],
  () => updateChart(),
  { deep: true }
)

// 监听主题变化
watch(
  () => props.theme,
  () => {
    if (chartInstance) {
      chartInstance.dispose()
    }
    initChart()
  }
)

// 监听加载状态
watch(
  () => props.loading,
  (val) => {
    if (chartInstance) {
      val ? chartInstance.showLoading() : chartInstance.hideLoading()
    }
  }
)

onMounted(() => {
  initChart()
  if (props.autoResize) {
    window.addEventListener('resize', resizeChart)
  }
})

onBeforeUnmount(() => {
  if (props.autoResize) {
    window.removeEventListener('resize', resizeChart)
  }
  if (chartInstance) {
    chartInstance.dispose()
    chartInstance = null
  }
})
</script>

<style scoped>
.echarts-wrapper {
  position: relative;
  width: 100%;
}

.echarts-container {
  position: relative;
}

.loading-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
}

.loading-spinner {
  width: 40px;
  height: 40px;
  border: 3px solid #f3f3f3;
  border-top: 3px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style>