<template>
  <div class="w-full" :class="wrapperClass">
    <div v-if="isLoading" class="p-4">
      <el-skeleton animated :rows="3" />
    </div>
    <div v-else class="relative">
      <div
        v-show="hasData"
        ref="chartRef"
        class="w-full"
        :style="{ height }"
      />
      <el-empty v-if="!hasData" :description="emptyText" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, onBeforeUnmount, shallowRef, watch, ref, nextTick } from 'vue'
import { useResizeObserver } from '@vueuse/core'
import { ElMessage } from 'element-plus'

// ECharts (tree-shakeable imports)
import * as echarts from 'echarts/core'
import type { EChartsCoreOption } from 'echarts'
import { LineChart } from 'echarts/charts'
import {
  GridComponent,
  TooltipComponent,
  LegendComponent,
  DatasetComponent,
} from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'

echarts.use([LineChart, GridComponent, TooltipComponent, LegendComponent, DatasetComponent, CanvasRenderer])

interface TrendPoint {
  date: string | number
  value: number
}

interface Props {
  modelValue?: TrendPoint[]
  data?: TrendPoint[]
  title?: string
  height?: string
  seriesName?: string
  smooth?: boolean
  area?: boolean
  isLoading?: boolean
  emptyText?: string
  yMax?: number | null
  wrapperClass?: string
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => [],
  data: () => [],
  title: '',
  height: '260px',
  seriesName: '消息数量',
  smooth: true,
  area: false,
  isLoading: false,
  emptyText: '暂无数据',
  yMax: null,
  wrapperClass: '',
})

const chartRef = ref<HTMLDivElement | null>(null)
const chartInstance = shallowRef<echarts.ECharts | null>(null)

const mergedData = computed<TrendPoint[]>(() => {
  return props.data && props.data.length ? props.data : props.modelValue
})

const hasData = computed(() => mergedData.value && mergedData.value.length > 0)
const height = computed(() => props.height)
const wrapperClass = computed(() => props.wrapperClass)
const emptyText = computed(() => props.emptyText)
const isLoading = computed(() => props.isLoading)

function buildOption(points: TrendPoint[]): EChartsCoreOption {
  const x = points.map((p) => p.date)
  const y = points.map((p) => p.value)

  return {
    tooltip: {
      trigger: 'axis',
      axisPointer: { type: 'line' },
    },
    legend: { data: [props.seriesName] },
    grid: { left: 36, right: 20, top: 24, bottom: 36, containLabel: true },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: x,
      axisLine: { lineStyle: { color: '#e5e7eb' } },
      axisLabel: { color: '#6b7280' },
    },
    yAxis: {
      type: 'value',
      max: props.yMax === null ? undefined : props.yMax,
      axisLine: { show: false },
      splitLine: { lineStyle: { color: '#f1f5f9' } },
      axisLabel: { color: '#6b7280' },
    },
    series: [
      {
        type: 'line',
        name: props.seriesName,
        data: y,
        smooth: props.smooth,
        showSymbol: true,
        symbolSize: 6,
        lineStyle: { width: 2, color: '#3b82f6' },
        itemStyle: { color: '#3b82f6' },
        areaStyle: props.area
          ? {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: 'rgba(59,130,246,0.25)' },
                { offset: 1, color: 'rgba(59,130,246,0.03)' },
              ]),
            }
          : undefined,
      },
    ],
  }
}

function initChart() {
  if (!chartRef.value) return
  // Dispose if exists
  if (chartInstance.value) {
    chartInstance.value.dispose()
    chartInstance.value = null
  }
  try {
    chartInstance.value = echarts.init(chartRef.value)
    if (hasData.value) {
      chartInstance.value.setOption(buildOption(mergedData.value))
    }
  } catch (error) {
    ElMessage.error('图表初始化失败')
  }
}

function render() {
  if (!chartInstance.value || !hasData.value) return
  chartInstance.value.setOption(buildOption(mergedData.value), true)
}

onMounted(async () => {
  await nextTick()
  initChart()
})

onBeforeUnmount(() => {
  if (chartInstance.value) {
    chartInstance.value.dispose()
    chartInstance.value = null
  }
})

// Resize handling
useResizeObserver(chartRef, () => {
  if (chartInstance.value) {
    chartInstance.value.resize()
  }
})

watch(
  () => [mergedData.value, props.smooth, props.area, props.yMax, props.seriesName],
  () => {
    if (!chartInstance.value) initChart()
    render()
  },
  { deep: true }
)
</script>

<style scoped lang="scss">
.relative {
  position: relative;
}
</style>


