<template>
  <div v-loading="loading" class="app-container vibration-board-page">
    <VibrationBoardFilter
      :selection-label="queryForm.selectionLabel"
      :time-range="daterangeRecordTime"
      :sampling-interval="queryForm.samplingInterval"
      :vibration-param="queryForm.vibrationParam"
      @update:time-range="setTimeRange"
      @update:sampling-interval="setSamplingInterval"
      @update:vibration-param="setVibrationParam"
      @query="handleQuery"
    />

    <el-row :gutter="16" class="mt-4 vibration-grid">
      <el-col :xs="24" :lg="7" :xl="6">
        <VibrationBoardDeviceTree :loading="treeLoading" :tree-data="monitorTreeOptions" :tree-props="treeProps" @node-click="handleTreeNodeClick" />
      </el-col>
      <el-col :xs="24" :lg="17" :xl="18">
        <el-card shadow="never" class="chart-card">
          <template #header>
            <div class="card-header">
              <div class="card-title-group">
                <div class="card-title">{{ trendData.multiDevice ? '设备对比趋势图' : '多指标趋势图' }}</div>
                <div class="card-subtitle">
                  {{
                    trendData.multiDevice
                      ? '多设备位移趋势对比适合横向发现谁的位移上升更快。'
                      : '单设备位移趋势适合观察当前设备是否存在持续抬升、波动放大或突变。'
                  }}
                </div>
              </div>
              <HelpButton :title="trendData.multiDevice ? '设备对比趋势图' : '位移趋势图'" :content="TREND_HELP" />
            </div>
          </template>
          <div ref="trendChartRef" class="chart-container-xl" />
        </el-card>

        <el-card shadow="never" class="chart-card mt-4">
          <template #header>
            <div class="card-header">
              <div class="card-title-group">
                <div class="card-title">小时均值图</div>
                <div class="card-subtitle">对短时抖动做平滑后，更容易识别班次、工况切换和持续升高的风险趋势。</div>
              </div>
              <HelpButton title="小时均值图" :content="TREND_HELP" />
            </div>
          </template>
          <div ref="hourlyChartRef" class="chart-container" />
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import { getDisplacementTrendData as getVibrationTrendData, type VibrationTrendPageVO } from '@/api/ems/report/displacementBoard';
import HelpButton from '../components/HelpButton.vue';
import VibrationBoardFilter from '../components/VibrationBoardFilter.vue';
import VibrationBoardDeviceTree from '../components/VibrationBoardDeviceTree.vue';
import { TREND_HELP } from '../components/helpContent';
import { useChartResize } from '../components/useChartResize';
import { useVibrationBoardQueryState } from '../components/useVibrationBoardQueryState';
import { buildCategoryDataZoom, getVibrationMetricOption, toNumber, vibrationMetricOptions } from '../components/vibrationBoardShared';

defineOptions({ name: 'VibrationBoardTrend' });

const trendChartRef = ref<HTMLElement>();
const hourlyChartRef = ref<HTMLElement>();
const { getChart } = useChartResize(trendChartRef, hourlyChartRef);

const {
  loading,
  treeLoading,
  monitorTreeOptions,
  treeProps,
  daterangeRecordTime,
  queryForm,
  loadTree,
  handleTreeNodeClick,
  setTimeRange,
  setSamplingInterval,
  setVibrationParam,
  buildQuery
} = useVibrationBoardQueryState();

const trendData = ref<VibrationTrendPageVO>({ series: [], hourlyItems: [] });
const metricColorMap = Object.fromEntries(vibrationMetricOptions.map((item) => [item.field, item.color]));
const activeMetric = computed(() => getVibrationMetricOption(trendData.value.metricField || queryForm.value.vibrationParam));

const renderCharts = () => {
  const trendChart = getChart(trendChartRef);
  const hourlyChart = getChart(hourlyChartRef);
  const series = trendData.value.series || [];
  const unit = trendData.value.unit || activeMetric.value.unit;

  if (trendChart) {
    if (!series.length) {
      trendChart.clear();
    } else {
      trendChart.setOption(
        {
          color: series.map((item) => metricColorMap[item.field || queryForm.value.vibrationParam] || activeMetric.value.color),
          tooltip: {
            trigger: 'axis',
            formatter: (params: any[]) => {
              const rows = params.map((item) => `${item.marker}${item.seriesName}: <b>${Number(item.value?.[1] ?? 0).toFixed(2)} ${unit}</b>`);
              return [`<b>${params[0]?.axisValueLabel || '--'}</b>`, ...rows].join('<br/>');
            }
          },
          legend: {
            type: 'scroll',
            top: 8,
            data: series.map((item) => item.name || '--'),
            textStyle: { color: '#475569' }
          },
          grid: { left: 60, right: 24, top: 60, bottom: 80 },
          dataZoom: [
            { type: 'inside', xAxisIndex: 0, filterMode: 'none' },
            { type: 'slider', xAxisIndex: 0, filterMode: 'none', height: 16, bottom: 18 }
          ],
          xAxis: {
            type: 'time',
            axisLabel: { color: '#64748b' },
            axisLine: { lineStyle: { color: '#cbd5e1' } }
          },
          yAxis: {
            type: 'value',
            name: unit,
            splitLine: { lineStyle: { type: 'dashed', color: 'rgba(148, 163, 184, 0.35)' } },
            axisLabel: { color: '#64748b' }
          },
          series: series.map((item) => {
            const seriesColor = metricColorMap[item.field || queryForm.value.vibrationParam] || activeMetric.value.color;
            return {
              name: item.name,
              type: 'line',
              smooth: true,
              showSymbol: false,
              connectNulls: true,
              sampling: 'lttb',
              lineStyle: { width: 2.4 },
              areaStyle: trendData.value.multiDevice
                ? undefined
                : {
                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                      { offset: 0, color: `${seriesColor}55` },
                      { offset: 1, color: `${seriesColor}08` }
                    ])
                  },
              emphasis: { focus: 'series' },
              data: (item.points || []).map((point) => [point.time, toNumber(point.value)])
            };
          })
        },
        true
      );
    }
  }

  if (hourlyChart) {
    const hourlyItems = trendData.value.hourlyItems || [];
    if (!hourlyItems.length) {
      hourlyChart.clear();
      return;
    }
    const values = hourlyItems.map((item) => toNumber(item.avgValue));
    const avgLine = values.reduce((sum, item) => sum + item, 0) / values.length;
    hourlyChart.setOption(
      {
        color: [activeMetric.value.color],
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'shadow' },
          formatter: (params: any[]) => `${params[0].axisValue}<br/>小时均值: <b>${Number(params[0].value).toFixed(2)} ${unit}</b>`
        },
        legend: {
          top: 8,
          data: ['小时均值'],
          textStyle: { color: '#475569' }
        },
        grid: { left: 56, right: 24, top: 52, bottom: 40 },
        xAxis: {
          type: 'category',
          data: hourlyItems.map((item) => item.hour),
          axisLabel: { color: '#334155' }
        },
        yAxis: {
          type: 'value',
          name: unit,
          splitLine: { lineStyle: { type: 'dashed', color: 'rgba(148, 163, 184, 0.35)' } },
          axisLabel: { color: '#64748b' }
        },
        dataZoom: buildCategoryDataZoom(hourlyItems.length, 'x'),
        series: [
          {
            name: '小时均值',
            type: 'bar',
            barMaxWidth: 28,
            data: values,
            itemStyle: {
              borderRadius: [8, 8, 0, 0],
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: activeMetric.value.color },
                { offset: 1, color: 'rgba(15, 118, 110, 0.18)' }
              ])
            },
            markLine: {
              symbol: 'none',
              lineStyle: { color: '#f97316', type: 'dashed' },
              label: { formatter: `整体均值 ${avgLine.toFixed(2)} ${unit}` },
              data: [{ yAxis: Number(avgLine.toFixed(2)) }]
            }
          }
        ]
      },
      true
    );
  }
};

const handleQuery = async () => {
  loading.value = true;
  try {
    const { data } = await getVibrationTrendData(buildQuery());
    trendData.value = data || { series: [], hourlyItems: [] };
    await nextTick();
    // 趋势图包含滚动缩放与时间轴，必须在容器最终尺寸稳定后再绑定数据缩放区间。
    renderCharts();
  } finally {
    loading.value = false;
  }
};

onMounted(async () => {
  await loadTree();
  await handleQuery();
});
</script>

<style scoped lang="scss">
@import '../components/vibrationBoardReport.scss';
</style>
