<!-- MonitorPanel.vue 完整版（支持销毁） -->
<template>
  <!-- 外层动画包裹层 -->

  <div class="panel-wrapper">
    <!-- 'monitor-panel-zzg': sensorData.positionName == '总支管#', -->
    <div class="monitor-panel" :class="{ alarm: hasAlarm }" ref="panelRef">
      <!-- <div style="position: absolute; top: -80px; right: 20px; font-size: 50px; width: 100%; text-align: center">总支管</div> -->
      <div>
        <div class="title"><div class="line"></div>{{ monitorData.positionName }}旋进漩涡流量计<div class="line"></div></div>
        <div class="panel-grid">
          <div class="panel-item">
            <span class="item-label">▸瞬时标况流量 </span>
            <div>
              <span class="item-value" :class="getStatusClass('flowStdInstant')">
                {{ monitorData.flowStdInstant ?? 'XXXX' }}
              </span>
              <span>Nm3/h</span>
            </div>
          </div>
          <div class="panel-item">
            <span class="item-label">▸ 压力</span>
            <div>
              <span class="item-value" :class="getStatusClass('injectionPressure')">
                {{ monitorData.injectionPressure ?? 'XXXX' }}
              </span>
              <span>MPa</span>
            </div>
          </div>
          <div class="panel-item">
            <span class="item-label">▸ 温度 </span>
            <div>
              <span class="item-value" :class="getStatusClass('injectionTemperature')">
                {{ monitorData.injectionTemperature ?? 'XXXX' }}
              </span>
              <span>℃</span>
            </div>
          </div>
          <div class="panel-item">
            <span class="item-label">▸ 累计注气量</span>
            <div>
              <span class="item-value" :class="getStatusClass('flowStdAccum')">
                {{ monitorData.flowStdAccum ?? 'XXXX' }}
              </span>
              <span>Nm3</span>
            </div>
          </div>
        </div>
      </div>
      <div>
        <div class="title"><div class="line"></div>{{ monitorData.positionName }}阀门<div class="line"></div></div>
        <div class="panel-grid">
          <div class="panel-item">
            <span class="item-label">▸ 阀门开度 </span>
            <div>
              <span class="item-value" :class="getStatusClass('valveOpening')">
                {{ monitorData.valveOpening ?? 'XXXX' }}
              </span>
              <span>°</span>
            </div>
          </div>
        </div>
      </div>

      <div :class="{ 'panel-arrow': monitorData.positionName !== '总支管#', 'panel-line': monitorData.positionName == '总支管#' }"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref, onMounted, computed, onUnmounted, Ref, watch } from 'vue';
  import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
  import type { Scene, Camera } from 'three';

  export interface AlarmThreshold {
    flowStdInstant?: number;
    flowStdAccum?: number;
    injectionTemperature?: number;
    injectionPressure?: number;
    valveOpening?: number;
    paiqiStatus?: number;
  }

  export interface SensorData {
    positionName?: string;
    flowStdInstant?: number;
    flowStdAccum?: number;
    injectionTemperature?: number;
    injectionPressure?: number;
    valveOpening?: number;
    paiqiStatus?: number;
  }

  const props = defineProps({
    sensorData: {
      type: Object as () => Ref<SensorData>,
      default: () => ({}),
    },
    threshold: {
      type: Object as () => AlarmThreshold,
      default: () => ({}),
    },
    position: {
      type: Array as () => [number, number, number],
      default: () => [0, 5, -10],
    },
    scale: {
      type: Number,
      default: 0.5,
    },
    threeScene: {
      type: Object as () => Scene,
      default: null,
    },
    instanceId: {
      type: String,
      default: '',
    },
  });

  const panelRef = ref<HTMLElement | null>(null);
  const cssObject = ref<CSS3DObject | null>(null);
  const monitorData = ref<SensorData>({});

  watch(
    () => props.sensorData.value,
    (newValue, oldValue) => {
      if (newValue) monitorData.value = newValue;
    },
    { immediate: true }
  );

  // 默认阈值
  const defaultThreshold: Required<AlarmThreshold> = {
    flowStdInstant: 100,
    flowStdAccum: 100,
    injectionTemperature: 100,
    injectionPressure: 10,
    valveOpening: 50,
    paiqiStatus: 30,
  };

  // 合并阈值
  const currentThreshold = computed(() => ({
    ...defaultThreshold,
    ...props.threshold,
  }));

  // ✅ 正确：访问 .value
  const getStatusClass = (key: keyof AlarmThreshold) => {
    // 1. 先获取当前数据对象
    const currentData = props.sensorData.value;

    // 2. 安全访问属性
    const value = currentData ? currentData[key] : undefined;

    if (value == null) return 'normal';

    const threshold = currentThreshold.value[key]!;
    if (value > threshold) {
      return 'alarm';
    }
    return 'normal';
  };

  // ✅ 正确：hasAlarm 也要修改
  const hasAlarm = computed(() => {
    const currentData = props.sensorData.value; // 👈 获取值
    if (!currentData) return false;

    return Object.keys(currentThreshold.value).some((key) => {
      const value = currentData[key as keyof AlarmThreshold];
      return value != null && value > currentThreshold.value[key as keyof AlarmThreshold]!;
    });
  });

  // 面朝相机更新
  const update = (camera: Camera) => {
    if (cssObject.value) {
      // cssObject.value.lookAt(camera.position);
      // 修复翻转
      // cssObject.value.rotation.z = Math.PI;
      // cssObject.value.rotation.x = Math.PI;
    }
  };

  onMounted(() => {
    if (!panelRef.value) return;
    cssObject.value = new CSS3DObject(panelRef.value);
    cssObject.value.scale.set(props.scale, props.scale, props.scale);
    // cssObject.value.scale.set(0, 0, 0);
    cssObject.value.position.set(props.position[0], props.position[1] + 1.56, props.position[2]);
    // cssObject.value.center.set(0, 0);
    cssObject.value.rotation.y -= Math.PI / 2;

    if (props.threeScene) {
      props.threeScene.add(cssObject.value);
    }
  });

  // 销毁方法
  const destroy = () => {
    if (cssObject.value && props.threeScene) {
      props.threeScene.remove(cssObject.value);
      (cssObject.value as any).element = null;
      cssObject.value = null;
    }
  };

  onUnmounted(() => {
    destroy();
  });

  // 暴露方法
  defineExpose({
    id: props.instanceId,
    cssObject: cssObject,
    update,
    destroy,
  });
</script>

<style scoped lang="less">
  /* ====================================== */
  /* 🔥 核心：从中间向两边扩散展开动画 */
  /* ====================================== */
  .panel-wrapper {
    animation: panelExpand 1.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  }

  /* 扩散动画：中间 → 左右展开 */
  @keyframes panelExpand {
    0% {
      opacity: 0;
      transform: scaleX(0); /* 中间闭合 */
    }
    100% {
      opacity: 1;
      transform: scaleX(1); /* 展开到完整宽度 */
    }
  }

  /* ====================================== */
  /* 主面板（科技风 + 状态颜色） */
  /* ====================================== */
  .monitor-panel {
    width: 1000px;
    background: linear-gradient(145deg, rgba(10, 42, 60, 0.55), rgba(15, 40, 80, 0.9));
    border: 5px solid #40d9ff;

    border-radius: 16px;
    padding: 20px 24px 40px;
    box-sizing: border-box;
    position: absolute;
    font-family: 'Microsoft YaHei', 'PingFang SC', sans-serif;
    color: #fff;
    box-shadow:
      0 12px 40px rgba(64, 169, 255, 0.25),
      inset 0 0 0 1px rgba(64, 169, 255, 0.15);
    backdrop-filter: blur(12px);
    transition: all 0.4s ease;
    overflow: visible;
    transform-origin: center center; /* 扩散中心点：中间 */
  }
  .monitor-panel-zzg {
    background: linear-gradient(145deg, rgba(10, 50, 60, 0.55), rgba(15, 56, 80, 0.9));
    border: 5px solid #9b9b9b;
  }

  /* 报警状态整体变红 */
  .monitor-panel .alarm {
    border-color: #ff4d4f;

    box-shadow:
      0 20px 40px rgba(255, 77, 79, 0.35),
      inset 0 0 6px 2px rgba(255, 77, 79, 0.2);
    animation: panelPulse 1.5s infinite alternate;
  }

  @keyframes panelPulse {
    0% {
      box-shadow:
        0 20px 40px rgba(255, 77, 79, 0.35),
        inset 0 0 6px 2px rgba(255, 77, 79, 0.2);
    }
    100% {
      box-shadow:
        0 20px 50px rgba(255, 77, 79, 0.5),
        inset 0 0 6px 2px rgba(255, 77, 79, 0.3);
    }
  }

  /* 标题 */
  .panel-title {
    text-align: center;
    font-size: 40px;
    font-weight: 700;
    margin-bottom: 24px;
    letter-spacing: 4px;
    background: linear-gradient(90deg, #40a9ff, #69c0ff);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    text-shadow: 0 0 16px rgba(64, 169, 255, 0.4);
    position: absolute;
  }

  /* 网格布局 */
  .panel-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
  }
  .title {
    width: 100%;
    font-size: 35px;
    text-align: center;
    padding: 20px 0;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    justify-content: space-between;
    .line {
      flex: 1;
      height: 1.2px;
      background-color: #36cffb;
    }
  }
  .item-full {
    grid-column: 1 / -1;
  }

  /* 监控项 */
  .panel-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: rgba(30, 70, 120, 0.4);
    border: 3px solid rgba(64, 169, 255, 0.3);
    padding: 12px 10px;
    border-radius: 12px;
    font-size: 28px;
    transition: all 0.3s ease;
    cursor: default;
  }

  .panel-item:hover {
    background: rgba(40, 90, 150, 0.5);
    border-color: rgba(64, 169, 255, 0.6);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(64, 169, 255, 0.2);
  }

  .item-label {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 500;
    color: #e6f3ff;
  }

  .ai-label {
    color: #36cffb;
    text-shadow: 0 0 8px rgba(54, 207, 251, 0.3);
  }

  /* 数值正常颜色 */
  .item-value {
    font-weight: 700;
    font-size: 27px;
    color: #40a9ff;
    letter-spacing: 2px;
    transition: all 0.3s ease;
    padding-right: 5px;
  }

  /* 报警闪烁 */
  .item-value .alarm {
    color: #ff4d4f !important;
    text-shadow: 0 0 12px rgba(255, 77, 79, 0.6);
    animation: valueBlink 0.8s infinite alternate;
  }

  @keyframes valueBlink {
    0% {
      opacity: 0.6;
      transform: scale(1);
    }
    100% {
      opacity: 1;
      transform: scale(1.05);
    }
  }

  /* 底部定位箭头 */
  .panel-arrow {
    position: absolute;
    bottom: -18px;
    left: 50%;
    transform: translateX(-50%);
    width: 0;
    height: 0;
    border-left: 18px solid transparent;
    border-right: 18px solid transparent;
    border-top: 18px solid #1eddff;
    filter: drop-shadow(0 4px 8px rgba(64, 169, 255, 0.3));
    transition: all 0.4s ease;
  }

  .panel-line {
    position: absolute;
    bottom: -180px;
    left: -180px;
    // transform: translateX(-50%);
    width: 180px;
    height: 8px;
    background: #7f8f9c;
    border-left: 2px solid #00aaff; /* 斜线颜色粗细 */
    border-bottom: 2px solid #00aaff;
    transform: skewY(-45deg); /* 角度 */
    transform-origin: left bottom; /* 从左下角开始 */
    // border-left: 18px solid transparent;
    // border-right: 18px solid transparent;
    // border-top: 18px solid #40a9ff;
    // filter: drop-shadow(0 4px 8px rgba(64, 169, 255, 0.3));
    // transition: all 0.4s ease;
  }

  .monitor-panel .alarm .panel-arrow {
    border-top-color: #ff4d4f;
    filter: drop-shadow(0 8px 16px rgba(255, 77, 79, 0.4));
  }
</style>
