<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="handleMetricChange"
      @query="handleQuery"
    />

    <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="ANOMALY_HELP" />
            </div>
          </template>
      <el-form :inline="true" size="small" label-width="110px" class="threshold-form">
        <el-form-item label="高阈值">
          <el-input-number v-model="queryForm.highThreshold" :min="0" :precision="2" class="threshold-input" />
        </el-form-item>
        <el-form-item label="预警阈值">
          <el-input-number v-model="queryForm.warningThreshold" :min="0" :precision="2" class="threshold-input" />
        </el-form-item>
        <el-form-item label="连续样本数">
          <el-input-number v-model="queryForm.minContinuousSamples" :min="2" :max="100" class="threshold-input" />
        </el-form-item>
        <el-form-item label="变化率阈值">
          <el-input-number v-model="queryForm.rapidRiseThreshold" :min="0.1" :precision="2" :step="0.1" class="threshold-input" />
        </el-form-item>
        <el-form-item label="抖动阈值">
          <el-input-number v-model="queryForm.stddevThreshold" :min="0.1" :precision="2" :step="0.1" class="threshold-input" />
        </el-form-item>
      </el-form>
    </el-card>

    <el-row :gutter="16" class="mt-4 vibration-grid">
      <el-col :xs="12" :md="6">
        <el-card shadow="never" class="kpi-card">
          <div class="kpi-label">高风险事件</div>
          <div class="kpi-value danger">{{ toNumber(anomalyData.highEventCount) }}</div>
          <div class="metric-foot">超过高阈值的记录数。</div>
        </el-card>
      </el-col>
      <el-col :xs="12" :md="6">
        <el-card shadow="never" class="kpi-card">
          <div class="kpi-label">连续超标段</div>
          <div class="kpi-value warning">{{ toNumber(anomalyData.continuousEventCount) }}</div>
          <div class="metric-foot">持续恶化比瞬时毛刺更值得关注。</div>
        </el-card>
      </el-col>
      <el-col :xs="12" :md="6">
        <el-card shadow="never" class="kpi-card">
          <div class="kpi-label">变化过快</div>
          <div class="kpi-value primary">{{ toNumber(anomalyData.rapidRiseEventCount) }}</div>
          <div class="metric-foot">常见于冲击、松动或工况突变。</div>
        </el-card>
      </el-col>
      <el-col :xs="12" :md="6">
        <el-card shadow="never" class="kpi-card">
          <div class="kpi-label">抖动异常</div>
          <div class="kpi-value purple">{{ toNumber(anomalyData.jitterEventCount) }}</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" :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">异常构成概览</div>
                <div class="card-subtitle">先看异常构成，再决定是优先处理持续超标、突增冲击，还是高频抖动类问题。</div>
              </div>
              <HelpButton title="异常构成概览" :content="ANOMALY_HELP" />
            </div>
          </template>
          <div ref="eventChartRef" class="chart-container" />
        </el-card>

        <el-row :gutter="16" class="mt-4 vibration-grid">
          <el-col :xs="24" :xl="12">
            <el-card shadow="never" class="table-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="ANOMALY_HELP" />
                </div>
              </template>
              <el-table :data="anomalyData.highEvents || []" stripe size="small" max-height="320" class="data-table">
                <el-table-column prop="monitorName" label="设备" min-width="160" show-overflow-tooltip />
                <el-table-column prop="value" label="数值" width="120" align="right">
                  <template #default="{ row }">
                    <span class="danger">{{ Number(row.value || 0).toFixed(2) }}</span>
                  </template>
                </el-table-column>
                <el-table-column prop="recodeTime" label="时间" min-width="180" show-overflow-tooltip />
              </el-table>
            </el-card>
          </el-col>
          <el-col :xs="24" :xl="12">
            <el-card shadow="never" class="table-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="ANOMALY_HELP" />
                </div>
              </template>
              <el-table :data="anomalyData.rapidRiseEvents || []" stripe size="small" max-height="320" class="data-table">
                <el-table-column prop="monitorName" label="设备" min-width="160" show-overflow-tooltip />
                <el-table-column prop="diff" label="变化量" width="120" align="right">
                  <template #default="{ row }">
                    <span class="primary">{{ Number(row.diff || 0).toFixed(2) }}</span>
                  </template>
                </el-table-column>
                <el-table-column prop="recodeTime" label="时间" min-width="180" show-overflow-tooltip />
              </el-table>
            </el-card>
          </el-col>
        </el-row>

        <el-card shadow="never" class="table-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="ANOMALY_HELP" />
            </div>
          </template>
          <el-table :data="anomalyData.continuousEvents || []" stripe size="small" max-height="320" class="data-table">
            <el-table-column prop="monitorName" label="设备" min-width="180" show-overflow-tooltip />
            <el-table-column prop="startTime" label="开始时间" min-width="180" show-overflow-tooltip />
            <el-table-column prop="endTime" label="结束时间" min-width="180" show-overflow-tooltip />
            <el-table-column prop="maxValue" label="峰值" width="120" align="right">
              <template #default="{ row }">
                <span class="warning">{{ Number(row.maxValue || 0).toFixed(2) }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="sampleCount" label="样本数" width="100" align="right" />
          </el-table>
        </el-card>

        <el-card shadow="never" class="table-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="ANOMALY_HELP" />
            </div>
          </template>
          <el-table :data="anomalyData.jitterEvents || []" stripe size="small" max-height="320" class="data-table">
            <el-table-column prop="monitorName" label="设备" min-width="160" show-overflow-tooltip />
            <el-table-column prop="hourBucket" label="小时桶" min-width="180" show-overflow-tooltip />
            <el-table-column prop="stddev" label="标准差" width="120" align="right">
              <template #default="{ row }">
                <span class="purple">{{ Number(row.stddev || 0).toFixed(2) }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="sampleCount" label="样本数" width="100" align="right" />
          </el-table>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import { getDisplacementAnomalyData as getVibrationAnomalyData, type VibrationAnomalyPageVO } from '@/api/ems/report/displacementBoard';
import HelpButton from '../components/HelpButton.vue';
import VibrationBoardFilter from '../components/VibrationBoardFilter.vue';
import VibrationBoardDeviceTree from '../components/VibrationBoardDeviceTree.vue';
import { ANOMALY_HELP } from '../components/helpContent';
import { useChartResize } from '../components/useChartResize';
import { useVibrationBoardQueryState } from '../components/useVibrationBoardQueryState';
import { toNumber } from '../components/vibrationBoardShared';

defineOptions({ name: 'VibrationBoardAnomaly' });

const eventChartRef = ref<HTMLElement>();
const { getChart } = useChartResize(eventChartRef);

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

const anomalyData = ref<VibrationAnomalyPageVO>({
  highEvents: [],
  continuousEvents: [],
  rapidRiseEvents: [],
  jitterEvents: []
});

const applyThresholdDefaults = (data?: VibrationAnomalyPageVO) => {
  if (!data) {
    return;
  }
  queryForm.value.highThreshold = Number(data.highThreshold ?? queryForm.value.highThreshold ?? 0);
  queryForm.value.warningThreshold = Number(data.warningThreshold ?? queryForm.value.warningThreshold ?? 0);
  queryForm.value.minContinuousSamples = Number(data.minContinuousSamples ?? queryForm.value.minContinuousSamples ?? 3);
  queryForm.value.rapidRiseThreshold = Number(data.rapidRiseThreshold ?? queryForm.value.rapidRiseThreshold ?? 0);
  queryForm.value.stddevThreshold = Number(data.stddevThreshold ?? queryForm.value.stddevThreshold ?? 0);
};

const renderEventChart = () => {
  const chart = getChart(eventChartRef);
  if (!chart) {
    return;
  }
  const eventItems = [
    { name: '高风险事件', value: toNumber(anomalyData.value.highEventCount), color: '#ef4444' },
    { name: '连续超标段', value: toNumber(anomalyData.value.continuousEventCount), color: '#f59e0b' },
    { name: '变化过快', value: toNumber(anomalyData.value.rapidRiseEventCount), color: '#3b82f6' },
    { name: '抖动异常', value: toNumber(anomalyData.value.jitterEventCount), color: '#8b5cf6' }
  ].filter((item) => item.value > 0);

  if (!eventItems.length) {
    chart.clear();
    return;
  }

  chart.setOption(
    {
      color: eventItems.map((item) => item.color),
      tooltip: {
        trigger: 'item',
        formatter: (params: any) => `${params.name}<br/>事件数: <b>${params.value}</b><br/>占比: <b>${params.percent}%</b>`
      },
      legend: {
        type: 'scroll',
        orient: 'vertical',
        left: 8,
        top: 'middle',
        textStyle: { color: '#475569' }
      },
      graphic: [
        {
          type: 'text',
          left: '54%',
          top: '42%',
          style: {
            text: `总事件\n${eventItems.reduce((sum, item) => sum + item.value, 0)}`,
            textAlign: 'center',
            fill: '#1f2937',
            font: '700 18px sans-serif'
          }
        }
      ],
      series: [
        {
          type: 'pie',
          radius: ['46%', '72%'],
          center: ['60%', '50%'],
          label: { formatter: '{b}\n{d}%', color: '#334155' },
          itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 },
          data: eventItems
        }
      ]
    },
    true
  );
};

const handleMetricChange = (_value: string) => {
  // 筛选器已不再暴露指标切换，但兼容旧事件签名时仍统一回到“位移默认阈值”。
  resetAnomalyThresholds();
  setVibrationParam('vibrationDisplacement');
};

const handleQuery = async () => {
  loading.value = true;
  try {
    const { data } = await getVibrationAnomalyData(buildQuery());
    anomalyData.value = data || {
      highEvents: [],
      continuousEvents: [],
      rapidRiseEvents: [],
      jitterEvents: []
    };
    applyThresholdDefaults(data);
    await nextTick();
    renderEventChart();
  } finally {
    loading.value = false;
  }
};

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

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

.threshold-form {
  display: flex;
  flex-wrap: wrap;
}

.threshold-form :deep(.el-form-item) {
  margin-right: 12px;
  margin-bottom: 12px;
}

.threshold-input {
  width: 148px;
}

.danger {
  color: #ef4444;
}

.warning {
  color: #f59e0b;
}

.primary {
  color: #3b82f6;
}

.purple {
  color: #8b5cf6;
}

@media (max-width: 768px) {
  .threshold-input {
    width: 100%;
  }
}
</style>
