<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="12" :sm="12" :md="6">
        <el-card shadow="never" class="kpi-card">
          <div class="kpi-label">采样记录数</div>
          <div class="kpi-value">{{ toNumber(overviewData.sampleCount) }}</div>
          <div class="metric-foot">用于判断本次诊断是否建立在足够样本基础上。</div>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="12" :md="6">
        <el-card shadow="never" class="kpi-card">
          <div class="kpi-label">设备数量</div>
          <div class="kpi-value">{{ toNumber(overviewData.deviceCount) }}</div>
          <div class="metric-foot">当前筛选口径下参与分析的设备总数。</div>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="12" :md="6">
        <el-card shadow="never" class="kpi-card">
          <div class="kpi-label">主看指标</div>
          <div class="kpi-value kpi-metric">{{ overviewData.metricLabel || activeMetric.label }}</div>
          <div class="metric-foot">位移是当前看板唯一主指标，图表与排序口径已统一收敛。</div>
        </el-card>
      </el-col>
      <el-col :xs="12" :sm="12" :md="6">
        <el-card shadow="never" class="kpi-card">
          <div class="kpi-label">覆盖率</div>
          <div class="kpi-value">{{ formatPercentValue(overviewData.coverageRate) }}</div>
          <div class="metric-foot">覆盖率偏低时，请优先检查设备离线或采集链路问题。</div>
        </el-card>
      </el-col>
    </el-row>

    <el-row :gutter="16" class="mt-4 vibration-grid">
      <el-col :xs="24" :sm="12" :xl="6" v-for="item in overviewData.metricCards || []" :key="item.field">
        <el-card shadow="never" class="metric-card" :style="{ borderTop: `4px solid ${metricColorMap[item.field || ''] || '#5b8ff9'}` }">
          <div class="kpi-label">{{ item.label }}</div>
          <div class="kpi-value">
            {{ formatMetricValue(item.latest) }}<span class="unit">{{ item.unit }}</span>
          </div>
          <div class="metric-foot">均值 {{ formatMetricValue(item.avg) }}{{ item.unit }}</div>
          <div class="metric-foot">峰值 {{ formatMetricValue(item.max) }}{{ item.unit }}</div>
        </el-card>
      </el-col>
    </el-row>

    <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-row :gutter="16" class="vibration-grid">
          <el-col :xs="24" :xl="12">
            <el-card shadow="never" class="chart-card">
              <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="OVERVIEW_HELP" />
                </div>
              </template>
              <div ref="gaugeChartRef" class="chart-container-lg" />
            </el-card>
          </el-col>
          <el-col :xs="24" :xl="12">
            <el-card shadow="never" class="chart-card">
              <template #header>
                <div class="card-header">
                  <div class="card-title-group">
                    <div class="card-title">{{ hasMultiDevice ? '设备排名对比图' : '主看指标统计分布图' }}</div>
                    <div class="card-subtitle">
                      {{
                        hasMultiDevice
                          ? '同时对比均值、最新值与峰值，快速定位最值得排查的设备。'
                          : '单机模式下对照最小值、均值、最大值与当前值，判断当前工况是否偏离常态。'
                      }}
                    </div>
                  </div>
                  <HelpButton :title="hasMultiDevice ? '设备排名对比图' : '主看指标统计分布图'" :content="OVERVIEW_HELP" />
                </div>
              </template>
              <div ref="rankChartRef" class="chart-container-lg" />
            </el-card>
          </el-col>
        </el-row>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import { getDisplacementOverviewData as getVibrationOverviewData, type VibrationOverviewPageVO } from '@/api/ems/report/displacementBoard';
import HelpButton from '../components/HelpButton.vue';
import VibrationBoardFilter from '../components/VibrationBoardFilter.vue';
import VibrationBoardDeviceTree from '../components/VibrationBoardDeviceTree.vue';
import { OVERVIEW_HELP } from '../components/helpContent';
import { useChartResize } from '../components/useChartResize';
import { useVibrationBoardQueryState } from '../components/useVibrationBoardQueryState';
import {
  buildCategoryDataZoom,
  formatMetricValue,
  formatPercentValue,
  getVibrationMetricOption,
  toNumber,
  vibrationMetricOptions
} from '../components/vibrationBoardShared';

defineOptions({ name: 'VibrationBoardOverview' });

const gaugeChartRef = ref<HTMLElement>();
const rankChartRef = ref<HTMLElement>();
const { getChart } = useChartResize(gaugeChartRef, rankChartRef);

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

const overviewData = ref<VibrationOverviewPageVO>({ metricCards: [], gaugeItems: [], deviceRanks: [] });
const metricColorMap = Object.fromEntries(vibrationMetricOptions.map((item) => [item.field, item.color]));
const activeMetric = computed(() => getVibrationMetricOption(overviewData.value.metricField || queryForm.value.vibrationParam));

const buildGaugeCenters = (count: number) => {
  if (count <= 1) {
    return [['50%', '58%']];
  }
  if (count === 2) {
    return [
      ['28%', '58%'],
      ['72%', '58%']
    ];
  }
  return [
    ['18%', '58%'],
    ['50%', '58%'],
    ['82%', '58%']
  ];
};

const renderCharts = () => {
  const gaugeChart = getChart(gaugeChartRef);
  const rankChart = getChart(rankChartRef);
  const gaugeItems = overviewData.value.gaugeItems || [];
  const deviceRanks = overviewData.value.deviceRanks || [];
  const unit = overviewData.value.unit || activeMetric.value.unit;
  const currentMetricColor = metricColorMap[overviewData.value.metricField || queryForm.value.vibrationParam] || activeMetric.value.color;

  if (gaugeItems.length && gaugeChart) {
    const gaugeCenters = buildGaugeCenters(gaugeItems.length);
    gaugeChart.setOption(
      {
        tooltip: {
          trigger: 'item',
          formatter: (params: any) => `${params.seriesName}<br/>当前值: <b>${formatMetricValue(params.value)} ${unit}</b>`
        },
        series: gaugeItems.map((item, index) => {
          const gaugeColor = vibrationMetricOptions[index]?.color || currentMetricColor;
          return {
            name: item.name,
            type: 'gauge',
            min: 0,
            max: Math.max(toNumber(item.maxValue), toNumber(item.value), 1),
            radius: gaugeItems.length === 1 ? '88%' : '74%',
            center: gaugeCenters[index] || gaugeCenters[0],
            progress: {
              show: true,
              roundCap: true,
              width: 14,
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
                  { offset: 0, color: gaugeColor },
                  { offset: 1, color: '#dbeafe' }
                ])
              }
            },
            axisLine: {
              lineStyle: {
                width: 14,
                color: [[1, 'rgba(148, 163, 184, 0.16)']]
              }
            },
            splitLine: { length: 10, lineStyle: { color: 'rgba(100, 116, 139, 0.28)' } },
            axisTick: { show: false },
            axisLabel: { distance: 18, fontSize: 10, color: '#64748b' },
            pointer: { show: false },
            anchor: { show: false },
            title: { offsetCenter: [0, '82%'], fontSize: 12, color: '#475569' },
            detail: {
              offsetCenter: [0, '18%'],
              valueAnimation: true,
              formatter: () => `${formatMetricValue(item.value)} ${item.unit || unit}`,
              color: gaugeColor,
              fontSize: gaugeItems.length === 1 ? 26 : 18,
              fontWeight: 700
            },
            data: [{ value: toNumber(item.value), name: item.name }]
          };
        })
      },
      true
    );
  } else {
    gaugeChart?.clear();
  }

  if (!rankChart) {
    return;
  }

  if (hasMultiDevice.value) {
    if (!deviceRanks.length) {
      rankChart.clear();
      return;
    }
    const categoryNames = deviceRanks.map((item) => item.monitorName || item.monitorId || '--');
    rankChart.setOption(
      {
        color: [currentMetricColor, '#36cfc9', '#f97316'],
        tooltip: {
          trigger: 'axis',
          axisPointer: { type: 'shadow' },
          valueFormatter: (value: number) => `${formatMetricValue(value)} ${unit}`
        },
        legend: {
          top: 8,
          data: ['均值', '最新值', '峰值'],
          textStyle: { color: '#475569' }
        },
        grid: { left: 150, right: 30, top: 56, bottom: 20 },
        xAxis: {
          type: 'value',
          name: unit,
          splitLine: { lineStyle: { type: 'dashed', color: 'rgba(148, 163, 184, 0.35)' } },
          axisLabel: { color: '#64748b' }
        },
        yAxis: {
          type: 'category',
          data: categoryNames,
          axisLabel: { color: '#334155', width: 110, overflow: 'truncate' }
        },
        dataZoom: buildCategoryDataZoom(categoryNames.length),
        series: [
          {
            name: '均值',
            type: 'bar',
            barMaxWidth: 16,
            data: deviceRanks.map((item) => toNumber(item.avg)),
            itemStyle: { borderRadius: [0, 6, 6, 0] }
          },
          {
            name: '最新值',
            type: 'bar',
            barMaxWidth: 16,
            data: deviceRanks.map((item) => toNumber(item.latest)),
            itemStyle: { borderRadius: [0, 6, 6, 0] }
          },
          {
            name: '峰值',
            type: 'bar',
            barMaxWidth: 16,
            data: deviceRanks.map((item) => toNumber(item.max)),
            itemStyle: { borderRadius: [0, 6, 6, 0] }
          }
        ]
      },
      true
    );
    return;
  }

  const stats = overviewData.value.primaryMetricStats;
  if (!stats) {
    rankChart.clear();
    return;
  }
  rankChart.setOption(
    {
      color: [currentMetricColor, '#36cfc9'],
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'shadow' },
        valueFormatter: (value: number) => `${formatMetricValue(value)} ${unit}`
      },
      legend: {
        top: 8,
        data: ['统计值', '当前值'],
        textStyle: { color: '#475569' }
      },
      grid: { left: 56, right: 20, top: 56, bottom: 36 },
      xAxis: {
        type: 'category',
        data: ['最小值', '均值', '最大值'],
        axisLabel: { color: '#334155' }
      },
      yAxis: {
        type: 'value',
        name: unit,
        splitLine: { lineStyle: { type: 'dashed', color: 'rgba(148, 163, 184, 0.35)' } },
        axisLabel: { color: '#64748b' }
      },
      series: [
        {
          name: '统计值',
          type: 'bar',
          barMaxWidth: 34,
          data: [toNumber(stats.min), toNumber(stats.avg), toNumber(stats.max)],
          itemStyle: {
            borderRadius: [6, 6, 0, 0],
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              { offset: 0, color: currentMetricColor },
              { offset: 1, color: 'rgba(91, 143, 249, 0.2)' }
            ])
          },
          label: {
            show: true,
            position: 'top',
            color: '#475569',
            formatter: ({ value }: any) => formatMetricValue(value)
          }
        },
        {
          name: '当前值',
          type: 'line',
          smooth: true,
          symbol: 'circle',
          symbolSize: 10,
          lineStyle: { width: 2, type: 'dashed' },
          data: [toNumber(stats.latest), toNumber(stats.latest), toNumber(stats.latest)]
        }
      ]
    },
    true
  );
};

const handleQuery = async () => {
  loading.value = true;
  try {
    const { data } = await getVibrationOverviewData(buildQuery());
    overviewData.value = data || { metricCards: [], gaugeItems: [], deviceRanks: [] };
    await nextTick();
    // 先等 DOM 完成栅格重排，再按最新容器尺寸重画图表，避免首次进入时出现裁切。
    renderCharts();
  } finally {
    loading.value = false;
  }
};

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

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

.kpi-metric {
  font-size: clamp(18px, 1.6vw, 24px);
}
</style>
