<template>
  <div class="situational-awareness">
    <!-- 顶部导航栏 -->
    <PageHeader @back="handleBack" />

    <!-- 主内容区域 -->
    <div class="situational-awareness__main">
      <!-- 地图底层 -->
      <div class="situational-awareness__map-layer" :class="{ 'is-compare-mode': isCompareMode }">
        <!-- 左侧地图容器（对比模式下显示灾前场景） -->
        <div id="leftCesiumContainer" class="situational-awareness__left-map"></div>

        <!-- 中间分割线 -->
        <div v-if="isCompareMode" class="situational-awareness__center-divider"></div>

        <!-- 右侧地图（主地图 - 灾后场景） -->
        <div class="situational-awareness__right-map">
          <MapViewer :active-tool-key="activeToolKey" @tool-change="handleMapToolChange" />
        </div>
      </div>

      <!-- 地图遮罩层 -->
      <div class="situational-awareness__map-mask" aria-hidden="true"></div>

      <!-- 场景标签层 - 独立层级，显示在遮罩层之上 -->
      <div class="situational-awareness__scene-labels-layer">
        <ActionButton type="primary" v-if="isCompareMode" class="situational-awareness__sync-btn"
          @click="toggleCameraSync" :text="isCameraSyncEnabled ? '同步灾前灾后实景' : '未同步灾前灾后实景'
            ">
        </ActionButton>
        <!-- 灾前现场实景标签 - 在中间分割线左侧 -->
        <SceneLabel v-if="isCompareMode" text="灾前现场实景" position="center-left" />

        <!-- 灾后现场实景标签 - 在右侧面板左边 -->
        <SceneLabel text="灾后现场实景" position="right-left" />
      </div>

      <!-- 浮动面板层 -->
      <div class="situational-awareness__panels-layer">
        <Transition name="panel-slide-left">
          <div v-show="!isLeftPanelCollapsed"
            class="situational-awareness__panel-column situational-awareness__panel-column--left">
            <LeftPanel @start-dispatch="handleStartDispatch" @view-plan="handleViewPlan"
              @force-preset-toggle="handleForcePresetToggle" @quick-response-toggle="handleQuickResponseToggle" />
          </div>
        </Transition>

        <Transition name="panel-slide-right">
          <div v-show="!isRightPanelCollapsed"
            class="situational-awareness__panel-column situational-awareness__panel-column--right">
            <RightPanel @quick-disposal-click="handleQuickDisposalClick" />
          </div>
        </Transition>
      </div>

      <!-- 折叠按钮层 -->
      <div class="situational-awareness__collapse-buttons-layer">
        <!-- 左侧折叠按钮 -->
        <button class="situational-awareness__collapse-btn situational-awareness__collapse-btn--left"
          :class="{ 'is-collapsed': isLeftPanelCollapsed }" @click="toggleLeftPanel"
          :aria-label="isLeftPanelCollapsed ? '展开左侧面板' : '收起左侧面板'">
          <img :src="isLeftPanelCollapsed ? collapseRightArrow : collapseLeftArrow" alt="" class="collapse-arrow" />
        </button>

        <!-- 右侧折叠按钮 -->
        <button class="situational-awareness__collapse-btn situational-awareness__collapse-btn--right"
          :class="{ 'is-collapsed': isRightPanelCollapsed }" @click="toggleRightPanel"
          :aria-label="isRightPanelCollapsed ? '展开右侧面板' : '收起右侧面板'">
          <img :src="isRightPanelCollapsed ? collapseLeftArrow : collapseRightArrow
            " alt="" class="collapse-arrow" />
        </button>
      </div>

      <!-- 地图控件层 - 高于遮罩和面板 -->
      <div class="situational-awareness__controls-layer">
        <div id="sa-controls" class="situational-awareness__controls"></div>
      </div>

      <!-- 地图 Tooltip 层 - 用于显示地图标记点的轻量级信息提示框 -->
      <div class="situational-awareness__tooltip-layer">
        <MapTooltip :visible="mapTooltip.visible" :x="mapTooltip.x" :y="mapTooltip.y" :title="mapTooltip.title"
          :icon="mapTooltip.icon" :z-index="mapTooltip.zIndex"
          :show-video-icon="mapTooltip.data && mapTooltip.data.supportVideo" :video-icon-src="mediaIcon"
          @video-icon-click="handleVideoIconClick" @close="handleMapTooltipClose">
          <!-- Tooltip 内容插槽 - 根据实际业务数据渲染 -->
          <template v-if="mapTooltip.data && mapTooltip.data.fields">
            <div v-for="(field, index) in mapTooltip.data.fields" :key="index" class="tooltip-field-item">
              <span class="tooltip-field-label">{{ field.label }}：</span>
              <span class="tooltip-field-value">{{ field.value }}</span>
            </div>
          </template>

          <!-- 操作按钮插槽 -->
          <template v-if="mapTooltip.data && mapTooltip.data.actions" #actions>
            <button v-for="(action, index) in mapTooltip.data.actions" :key="index" class="tooltip-action-btn"
              @click="handleTooltipAction(action)">
              {{ action.label }}
            </button>
          </template>
        </MapTooltip>
      </div>

      <!-- 加载动画层 - 一键启动后显示 -->
      <div v-if="showLoading" class="situational-awareness__loading-layer">
        <img src="./assets/images/加载3.gif" alt="加载中" class="situational-awareness__loading-gif" />
        <!-- <img
          src="./assets/images/加载.gif"
          alt="加载中"
          class="situational-awareness__loading-gif"
        /> -->
      </div>
    </div>

    <!-- 弹窗组件 -->
    <PersonnelDetail :visible="showPersonnelDetail" :personnel-data="selectedPersonnel"
      @close="showPersonnelDetail = false" @link="handlePersonnelLink" />

    <EmergencyCenterDetail :visible="showCenterDetail" :center-data="selectedCenter"
      @close="showCenterDetail = false" />

    <!-- 视频监控弹窗 -->
    <VideoModal v-if="showVideoModal" :visible="showVideoModal" :monitor="selectedVideoMonitor"
      @close="handleVideoModalClose" />

    <!-- 智能应急方案弹窗 -->
    <StretchableModal :visible="showStretchableModal" title="公路灾害现场处置推荐方案" :close-on-click-modal="true"
      :close-on-press-escape="true" :show-close="true" @close="showStretchableModal = false"
      width="clamp(100px, 50vw, 1400px)">
      <!-- 使用应急方案内容组件 -->
      <EmergencyPlanContent :stations="disasterData.forcePreset.value.stations" />

      <!-- 底部一键启动按钮 -->
      <template #extraButtons>
        <ActionButton text="响应调度" type="inModal" size="medium" @click="handleModalStartDispatch" />
      </template>
    </StretchableModal>
  </div>
</template>

<script setup>
/**
 * 3D 态势感知主页面（重构版）
 *
 * 架构说明：
 * - 使用 Composition API 和 Composable 模式
 * - 生命周期管理：useCesiumLifecycle 统一管理资源
 * - 功能模块化：每个功能由独立的 composable 管理
 * - 数据层分离：硬编码数据移至 constants 目录
 *
 * 主要职责：
 * 1. 组件布局和模板渲染
 * 2. 子组件编排和事件转发
 * 3. 生命周期入口（初始化和清理）
 * 4. 用户交互事件处理
 */

import { ref, provide, onMounted, onUnmounted, watch } from "vue";
import * as Cesium from "cesium";
import { ElMessage } from "element-plus";

// ========== 组件导入 ==========
import PageHeader from "./components/PageHeader.vue";
import LeftPanel from "./components/LeftPanel/index.vue";
import MapViewer from "./components/MapViewer/index.vue";
import RightPanel from "./components/RightPanel/index.vue";
import PersonnelDetail from "./components/Popups/PersonnelDetail.vue";
import EmergencyCenterDetail from "./components/Popups/EmergencyCenterDetail.vue";
import VideoModal from "./components/RightPanel/VideoModal.vue";
import MapTooltip from "./components/shared/MapTooltip.vue";
import SceneLabel from "./components/SceneLabel.vue";
import StretchableModal from "./components/shared/StretchableModal.vue";
import ActionButton from "./components/shared/ActionButton.vue";
import EmergencyPlanContent from "./components/shared/EmergencyPlanContent.vue";

// ========== Composables 导入 ==========
import { useDisasterData } from "./composables/useDisasterData";
import { useDualMapCompare } from "./composables/useDualMapCompare";
import { useMapMarkers } from "./composables/useMapMarkers";
import { use3DTiles } from "./composables/use3DTiles";
import { useEntityAnimation } from "./composables/useEntityAnimation";

// 新的 composables
import { useCesiumLifecycle } from "./composables/useCesiumLifecycle";
import { useMapTooltip } from "./composables/useMapTooltip";
import { useMockData } from "./composables/useMockData";
import { useMapClickHandler } from "./composables/useMapClickHandler";
import { useRangeCircle } from "./composables/useRangeCircle";
import { usePathLines } from "./composables/usePathLines";
import { useEmergencyDispatch } from "./composables/useEmergencyDispatch";
import { useEmergencyRouteSelection } from "./composables/useEmergencyRouteSelection";
import { useSimulatedMarkers } from "./composables/useSimulatedMarkers";

// ========== 工具和常量导入 ==========
import { useMapStore } from "@/map";
import { request } from "@shared/utils/request";
import {
  DISASTER_CENTER,
  DEFAULT_CAMERA_CARTESIAN,
  DEFAULT_CAMERA_POSITION,
  DEFAULT_CAMERA_POSITION_CENTER,
  DEFAULT_CAMERA_VIEW,
  DEFAULT_SEARCH_RADIUS,
  MARKER_ICON_SIZE,
} from "./constants";
import { calculateDistance, isValidCoordinate } from "./utils/geoUtils";

// ========== 图标资源导入 ==========
import emergencyCenterIcon from "./assets/images/应急中心.png";
import eventIcon from "./assets/images/事件icon.png";
import soldierIcon from "./assets/images/SketchPngfbec927027ff9e49207749ebaafd229429315341fda199251b6dfb1723ff17fb.png";
import deviceIcon from "./assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png";
import emergencyBaseIcon from "./assets/images/应急基地.png";
import reserveCenterIcon from "./assets/images/储备中心.png";
import cityEmergencyIcon from "./assets/images/市应急点.png";
import districtEmergencyIcon from "./assets/images/区县应急点.png";
import otherEmergencyIcon from "./assets/images/其他应急点.png";
import mediaIcon from "./assets/images/media.png";
import collapseLeftArrow from "./assets/images/折叠面板左箭头.png";
import collapseRightArrow from "./assets/images/折叠面板右箭头.png";

// ====================
// 数据层
// ====================

// 使用灾害数据 composable
const disasterData = useDisasterData();

// 地图 store
const mapStore = useMapStore();

// 地图viewer
const cesiumViewer = ref(null);

// ====================
// 生命周期管理
// ====================

// Cesium 资源生命周期管理
const {
  registerEventHandler,
  registerPostRenderListener,
  registerTimeout,
  cleanup,
} = useCesiumLifecycle();

// ====================
// 地图功能模块
// ====================

// 双地图对比功能
const { isCompareMode, toggleCompareMode, isCameraSyncEnabled } =
  useDualMapCompare();

const toggleCameraSync = () => {
  ElMessage.success(
    isCameraSyncEnabled.value ? "画面同步已关闭" : "画面同步已启用"
  );
  console.log("[index.vue] 切换相机同步状态");
  isCameraSyncEnabled.value = !isCameraSyncEnabled.value;
};

// 快速处置点击事件
const handleQuickDisposalClick = async () => {
  console.log("[index.vue] 快速处置点击事件");
  const success = await setCompareToolState(false, "quick-disposal");

  if (!success) {
    // 如果关闭对比模式失败,不继续执行后续操作
    console.error("[index.vue] 关闭地图对比模式失败,中止快速处置操作");
    return;
  }

  const viewer = mapStore.viewer;
  console.log("[index.vue] 设置相机到目标位置...");
  viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(
      DEFAULT_CAMERA_POSITION_CENTER.lon,
      DEFAULT_CAMERA_POSITION_CENTER.lat,
      DEFAULT_CAMERA_VIEW.height
    ),
    orientation: {
      heading: Cesium.Math.toRadians(DEFAULT_CAMERA_VIEW.heading),
      pitch: Cesium.Math.toRadians(DEFAULT_CAMERA_VIEW.pitch),
      roll: DEFAULT_CAMERA_VIEW.roll,
    },
  });

  console.log("[index.vue] 已关闭地图对比模式");
};

// 地图标记功能
const {
  initializeMarkers,
  addEmergencyResourceMarkers,
  clearEmergencyResourceMarkers,
  addReserveCenterMarkers,
  clearReserveCenterMarkers,
  showMarkers,
  hideMarkers,
  markerEntities,
  reserveCenterEntities,
  emergencyResourceEntities,
  drawCollapseBoundary,
  drawCollapseBoundaryLeft,
  clearCollapseBoundary,
  showCollapseBoundary,
  hideCollapseBoundary,
  triggerJumpAnimation,
} = useMapMarkers();

// 3D Tiles 加载
const { load3DTileset, waitForTilesetReady } = use3DTiles();

// 地图 Tooltip
const tooltipComposable = useMapTooltip();
const {
  tooltipState: mapTooltip,
  showTooltip,
  hideTooltip,
} = tooltipComposable;

// 实体动画
const entityAnimationComposable = useEntityAnimation();

// 模拟数据服务
const mockDataService = useMockData();

// 范围圈管理
const rangeCircleComposable = useRangeCircle();
const {
  rangeCircleEntity,
  createOrUpdateRangeCircle,
  clearRangeCircle,
  showRangeCircle,
  hideRangeCircle,
} = rangeCircleComposable;

// 路径线管理
const pathLinesComposable = usePathLines();

// 地图点击事件处理
const mapClickHandler = useMapClickHandler({
  tooltipComposable,
  icons: {
    soldierIcon,
    deviceIcon,
    emergencyCenterIcon,
    emergencyBaseIcon,
    reserveCenterIcon,
    cityEmergencyIcon,
    districtEmergencyIcon,
    otherEmergencyIcon,
  },
  rangeCircleEntity,
});

// 应急调度流程
const { showLoading, loadingMessage, startDispatch, startDispatchWithRouting } =
  useEmergencyDispatch({
    pathLinesComposable,
    entityAnimationComposable,
    mapStore,
    registerTimeoutFn: registerTimeout,
  });

// 应急点选择
const { selectByType } = useEmergencyRouteSelection();

// 模拟标记管理
const {
  createSimulatedMarkers,
  clearSimulatedMarkers,
  hideEmergencyMarkers,
  getEmergencyMarkerData,
} = useSimulatedMarkers();

// ====================
// UI 状态
// ====================

// 面板折叠状态
const isLeftPanelCollapsed = ref(false);
const isRightPanelCollapsed = ref(false);

// 标记点和范围圈显示状态
const showMarkersAndRange = ref(false);

// 快速响应执行状态
const quickResponseExecuted = ref(false);

// 地图工具激活状态 - 默认激活模型对比
const activeToolKey = ref("modelCompare");

// 工具键常量
const COMPARE_TOOL_KEY = "modelCompare";

// 对比模式切换锁,防止并发操作
const isCompareTogglePending = ref(false);

// 弹窗状态
const showPersonnelDetail = ref(false);
const showCenterDetail = ref(false);
const showStretchableModal = ref(false);
const showVideoModal = ref(false);

// 选中的数据
const selectedPersonnel = ref({
  name: "张强",
  department: "安全生产部",
  distance: 0.6,
  estimatedArrival: 10,
  avatar: null,
});

const selectedCenter = ref({
  name: "忠县应急中心",
  adminLevel: "国道",
  department: "交通公路部门",
  distance: 0.6,
  image: null,
});

const selectedVideoMonitor = ref({
  id: "",
  title: "",
  videoSrc: "",
  dateRange: "",
  hasMegaphone: false,
  hasAudio: true,
  hasDirectionControl: false,
});

// ====================
// 事件处理函数
// ====================

/**
 * 切换左侧面板
 */
const toggleLeftPanel = () => {
  isLeftPanelCollapsed.value = !isLeftPanelCollapsed.value;
};

/**
 * 切换右侧面板
 */
const toggleRightPanel = () => {
  isRightPanelCollapsed.value = !isRightPanelCollapsed.value;
};

/**
 * 返回驾驶舱
 */
const handleBack = () => {
  console.log("返回驾驶舱");
  // 实际实现：路由跳转
  // router.push('/cockpit')

  // 从本地取出token
  const token = localStorage.getItem("token");

  const baseUrl = "http://58.144.223.132:30017/index";
  const targetUrl = `${baseUrl}?token=${encodeURIComponent(token || "")}`;
  window.location.href = targetUrl;
};

/**
 * 处理人员联动
 */
const handlePersonnelLink = (personnel) => {
  console.log("联动人员:", personnel);
  showPersonnelDetail.value = false;
};

/**
 * 处理 Tooltip 操作按钮点击事件
 */
const handleTooltipAction = (action) => {
  console.log("[index.vue] Tooltip 操作按钮点击:", action);

  if (action.type === "link") {
    // 应急人员的"联动"操作
    ElMessage.success(
      `已联动应急人员: ${action.data.name?.getValue() || "未知"}`
    );
    hideTooltip();
  } else if (action.type === "connect") {
    // 应急基地的"连线"操作
    ElMessage.success(
      `已连线应急基地: ${action.data.name?.getValue() || "未知"}`
    );
    hideTooltip();
  }
};

/**
 * 关闭地图 Tooltip
 */
const handleMapTooltipClose = () => {
  mapTooltip.value.visible = false;
};

/**
 * 处理视频图标点击事件
 */
const handleVideoIconClick = () => {
  const { data } = mapTooltip.value;
  if (data && data.supportVideo) {
    selectedVideoMonitor.value = {
      id: Date.now().toString(),
      title: data.videoTitle || "视频监控",
      videoSrc: data.videoSrc || "",
      dateRange: new Date().toLocaleDateString(),
      hasMegaphone: false,
      hasAudio: true,
      hasDirectionControl: false,
    };
    showVideoModal.value = true;
  }
};

/**
 * 处理视频弹窗关闭事件
 */
const handleVideoModalClose = () => {
  showVideoModal.value = false;
};

/**
 * 处理力量调度启动事件
 */
const handleStartDispatch = async (payload) => {
  console.log("[index.vue] 启动响应调度");

  await createOrUpdateRangeCircle(mapStore.viewer, 30);
  await createOrUpdateRangeCircle(mapStore.viewer, 50);

  // Check if Quick Response has been executed
  if (!quickResponseExecuted.value) {
    console.log("[index.vue] 快速响应未执行，自动执行...");
    await executeQuickResponse();
    quickResponseExecuted.value = true;
  }

  // Get emergency marker data
  const emergencyMarkerData = getEmergencyMarkerData();

  if (emergencyMarkerData.length === 0) {
    ElMessage.error("未找到应急点数据");
    return;
  }

  // Start dispatch with routing using emergency points
  startDispatchWithRouting({
    emergencyPoints: emergencyMarkerData.map((marker) => ({
      lon: marker.markerCoords.lon,
      lat: marker.markerCoords.lat,
      type: marker.type === "emergencyPersonnel" ? "personnel" : "equipment",
      name: marker.name,
    })),
  });
};

/**
 * 处理查看智能应急方案事件
 */
const handleViewPlan = (plan) => {
  console.log("[index.vue] 查看智能应急方案:", plan);
  showStretchableModal.value = true;
};

/**
 * 处理弹窗中的一键启动按钮点击事件
 */
const handleModalStartDispatch = async () => {
  console.log("[index.vue] 弹窗中点击一键启动 - 使用智能路径规划");
  showStretchableModal.value = false;

  // Check if Quick Response has been executed
  if (!quickResponseExecuted.value) {
    console.log("[index.vue] 快速响应未执行，自动执行...");
    await executeQuickResponse();
    quickResponseExecuted.value = true;
  }

  // Get emergency marker data
  const emergencyMarkerData = getEmergencyMarkerData();

  if (emergencyMarkerData.length === 0) {
    ElMessage.error("未找到应急点数据");
    return;
  }

  // Use emergency marker data for routing
  startDispatchWithRouting({
    emergencyPoints: emergencyMarkerData.map((marker) => ({
      lon: marker.markerCoords.lon,
      lat: marker.markerCoords.lat,
      type: marker.type === "emergencyPersonnel" ? "personnel" : "equipment",
      name: marker.name,
    })),
  });
};

/**
 * 统一的对比模式状态管理助手
 * 职责:
 * 1. 同步管理 activeToolKey 和 isCompareMode
 * 2. 提供失败回滚机制
 * 3. 防止并发操作
 *
 * @param {boolean} shouldActivate - 是否激活对比模式
 * @param {string} source - 调用来源(用于日志追踪)
 * @returns {Promise<boolean>} 操作是否成功
 */
const setCompareToolState = async (shouldActivate, source = "unknown") => {
  // 1. 并发保护
  if (isCompareTogglePending.value) {
    console.warn(`[index.vue] ${source} - 对比模式正在切换中,忽略本次操作`);
    return false;
  }

  if (isCompareMode.value === shouldActivate) {
    console.log(
      `[index.vue] ${source} - 对比模式已是目标状态 (${shouldActivate}),无需操作`
    );
    return true;
  }

  // 2. 保存当前状态(用于失败回滚)
  const prevToolKey = activeToolKey.value;
  const prevCompareMode = isCompareMode.value;

  // 3. 设置锁
  isCompareTogglePending.value = true;

  // 4. 乐观更新UI状态(立即响应)
  activeToolKey.value = shouldActivate ? COMPARE_TOOL_KEY : null;

  try {
    // 5. 执行实际的模式切换
    console.log(`[index.vue] ${source} - 开始切换对比模式: ${shouldActivate}`);
    await toggleCompareMode(shouldActivate, mapStore.viewer);

    console.log(`[index.vue] ${source} - 对比模式切换成功`);
    return true;
  } catch (error) {
    // 6. 失败回滚
    console.error(`[index.vue] ${source} - 切换对比模式失败:`, error);

    activeToolKey.value = prevToolKey;
    if (isCompareMode.value !== prevCompareMode) {
      console.warn(`[index.vue] isCompareMode状态不一致,强制回滚`);
      isCompareMode.value = prevCompareMode;
    }

    ElMessage.error({
      message: `切换对比模式失败: ${error.message || "未知错误"}`,
      duration: 3000,
    });

    return false;
  } finally {
    // 7. 释放锁
    isCompareTogglePending.value = false;
  }
};

/**
 * 处理快速匹配标题点击事件 - 切换显示/隐藏标记和范围圈
 */
const handleForcePresetToggle = async () => {
  console.log(
    "[index.vue] 快速匹配标题点击, 当前状态:",
    showMarkersAndRange.value ? "已显示" : "已隐藏"
  );

  // 点击时就展开50m的范围圈
  // await createOrUpdateRangeCircle(mapStore.viewer, 50);

  // 切换显示状态
  if (!showMarkersAndRange.value) {
    // 当前隐藏,切换为显示

    // 切换搜索范围为50km
    // disasterData.updateSearchRadius(50);

    // 1. 关闭地图对比模式(使用统一助手)
    if (isCompareMode.value) {
      console.log("[index.vue] 快速匹配需要关闭对比模式");
      const success = await setCompareToolState(false, "force-preset");

      if (!success) {
        // 如果关闭对比模式失败,不继续执行后续操作
        console.error("[index.vue] 关闭地图对比模式失败,中止快速匹配操作");
        return;
      }

      console.log("[index.vue] 已关闭地图对比模式");
    }

    // 2. 显示所有标记和范围圈（现在是异步函数）
    await showAllMarkersAndRange();

    // 3. 调整相机到最佳视角
    flyToBestViewForMarkers();

    // 更新状态
    showMarkersAndRange.value = true;
  } else {
    // 当前显示,切换为隐藏
    hideAllMarkersAndRange();

    // 更新状态
    showMarkersAndRange.value = false;
  }
};

/**
 * 处理快速响应标题点击事件
 */
const handleQuickResponseToggle = async () => {
  console.log("[index.vue] 快速响应标题点击");

  if (!quickResponseExecuted.value) {
    // Execute Quick Response
    await executeQuickResponse();
    quickResponseExecuted.value = true;
  } else {
    // Hide Quick Response markers
    hideQuickResponse();
    quickResponseExecuted.value = false;
  }
};

/**
 * 辅助函数：判断是否为应急点标记
 */
const isEmergencyPointMarker = (type) => {
  return (
    type === "cityEmergency" ||
    type === "districtEmergency" ||
    type === "otherEmergency"
  );
};

/**
 * 执行快速响应逻辑
 */
const executeQuickResponse = async () => {
  const viewer = mapStore.viewer;
  if (!viewer) return;

  console.log("[index.vue] 执行快速响应...");

  // 1. Hide all other markers
  viewer.entities.values.forEach((entity) => {
    if (entity.properties) {
      const type = entity.properties.type?.getValue();
      const isSimulated = entity.properties.isSimulated?.getValue();

      // Hide non-simulated, non-emergency-point markers
      if (!isSimulated && !isEmergencyPointMarker(type)) {
        entity.show = false;
      }
    }
  });

  // Hide养护站等 emergency resource markers
  hideMarkers();

  // 2. Load emergency points within range
  const rangeResponse = await request({
    url: `/snow-ops-platform/yhYjll/list`,
    method: "GET",
    params: {
      longitude: DISASTER_CENTER.lon,
      latitude: DISASTER_CENTER.lat,
      maxDistance: disasterData.forcePreset.value.searchRadius, // 30 or 50 km
    },
  });

  if (!rangeResponse?.data || !Array.isArray(rangeResponse.data)) {
    ElMessage.error("加载应急点失败");
    return;
  }

  // 3. Display emergency points on map
  await displayEmergencyPoints(rangeResponse.data);

  // 4. Select 2 nearest emergency points
  const emergencyPoints = rangeResponse.data;
  const pointsWithDistance = emergencyPoints.map((point) => ({
    ...point,
    distance: calculateDistance(
      { lon: DISASTER_CENTER.lon, lat: DISASTER_CENTER.lat },
      { lon: point.gl1Lng, lat: point.gl1Lat }
    ),
  }));

  const sortedPoints = pointsWithDistance.sort(
    (a, b) => a.distance - b.distance
  );
  const nearest2Points = sortedPoints.slice(0, 2);

  if (nearest2Points.length < 2) {
    ElMessage.warning("应急点数量不足2个");
    return;
  }

  console.log(
    "[index.vue] 选择最近的2个应急点:",
    nearest2Points.map((p) => p.gl1Yjllmc)
  );

  // 5. Create 6 simulated markers
  createSimulatedMarkers(viewer, DISASTER_CENTER, nearest2Points);

  // 6. Force render
  viewer.scene.requestRender();

  console.log("[index.vue] 快速响应执行完成");
};

/**
 * 显示应急点标记
 */
const displayEmergencyPoints = async (emergencyPoints) => {
  const viewer = mapStore.viewer;
  if (!viewer) return;

  // Clear existing emergency point markers
  viewer.entities.values.forEach((entity) => {
    const type = entity.properties?.type?.getValue();
    if (isEmergencyPointMarker(type)) {
      viewer.entities.remove(entity);
    }
  });

  // Add new emergency point markers
  emergencyPoints.forEach((point) => {
    // Determine icon based on level
    const levelString = String(point.gl1Lx || "").trim();
    let icon = otherEmergencyIcon;
    let type = "otherEmergency";
    let levelName = "其他";

    if (levelString.startsWith("1") || levelString === "1") {
      icon = cityEmergencyIcon;
      type = "cityEmergency";
      levelName = "市级";
    } else if (levelString.startsWith("2") || levelString === "2") {
      icon = districtEmergencyIcon;
      type = "districtEmergency";
      levelName = "区县级";
    }

    viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(point.gl1Lng, point.gl1Lat, 0),
      billboard: {
        image: icon,
        width: 29,
        height: 32,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      },
      properties: new Cesium.PropertyBag({
        type: type,
        name: point.gl1Yjllmc,
        level: levelName,
        district: point.gl1Qxmc,
        personnel: point.gl1Rysl,
        area: point.gl1Zdmj,
      }),
    });
  });

  console.log(`[index.vue] 显示 ${emergencyPoints.length} 个应急点`);
};

/**
 * 隐藏快速响应标记
 */
const hideQuickResponse = () => {
  const viewer = mapStore.viewer;
  if (!viewer) return;

  console.log("[index.vue] 隐藏快速响应标记...");

  // Hide emergency point markers
  viewer.entities.values.forEach((entity) => {
    const type = entity.properties?.type?.getValue();
    if (isEmergencyPointMarker(type)) {
      entity.show = false;
    }
  });

  // Clear simulated markers
  clearSimulatedMarkers(viewer);

  console.log("[index.vue] 已隐藏快速响应标记");
};

/**
 * 处理地图工具变化事件
 */
const handleMapToolChange = async ({ tool, active }) => {
  console.log(`[index.vue] 地图工具变化: ${tool}, 激活状态: ${active}`);

  if (tool === COMPARE_TOOL_KEY) {
    // 模型对比工具: 使用统一助手管理状态
    const loadingMessage = ElMessage({
      message: active ? "正在启用模型对比..." : "正在关闭模型对比...",
      type: "info",
      duration: 0,
      showClose: false,
    });

    const success = await setCompareToolState(active, "map-controls");

    loadingMessage.close();

    if (success) {
      ElMessage.success(active ? "模型对比已启用" : "模型对比已关闭");
    }
    // 失败消息已在助手函数中处理
  } else {
    // 其他工具: 保持原有逻辑
    activeToolKey.value = active ? tool : null;
    console.log(`[index.vue] 工具 ${tool} ${active ? "激活" : "取消"}`);
  }
};

/**
 * 处理距离范围变更
 */
const handleDistanceChange = async (newDistance) => {
  console.log(`[index.vue] 距离范围改变为: ${newDistance}km`);

  // 1. 更新搜索半径
  disasterData.updateSearchRadius(newDistance);

  // 2. 更新范围圈
  if (mapStore.viewer) {
    createOrUpdateRangeCircle(mapStore.viewer, newDistance);
  }

  // 3. 重新加载应急统计数据
  await loadEmergencyBaseAndPreset(DISASTER_CENTER.lon, DISASTER_CENTER.lat);

  // 4. 重新加载应急资源数据并更新地图标记
  await loadReserveCentersAndPresets(DISASTER_CENTER.lon, DISASTER_CENTER.lat);

  // 3. 重新加载储备中心和预置点数据并更新地图标记 并且 重新加载应急统计数据 (新增)
  // await loadReserveCentersAndPresetsAndStatistics(DISASTER_CENTER.lon, DISASTER_CENTER.lat);


};

/**
 * 显示所有标记点和范围圈
 */
const showAllMarkersAndRange = async () => {
  const viewer = mapStore.viewer;
  if (!viewer) return;

  // 1. 显示模拟点位
  // viewer.entities.values.forEach((entity) => {
  //   if (entity.properties) {
  //     const props = entity.properties
  //     if (props.type?.getValue() === 'soldier' ||
  //         props.type?.getValue() === 'device' ||
  //         props.isPathStartMarker?.getValue()) {
  //       entity.show = true
  //     }
  //   }
  // })

  // 2. 显示接口标记
  // hideMarkers()

  // 2. 加载全部储备中心/预置点到地图（不限制距离）
  // console.log("[index.vue] 加载全部储备中心/预置点到地图...");
  // await loadReserveCentersAndPresetsAndStatistics(
  //   DISASTER_CENTER.lon,
  //   DISASTER_CENTER.lat,
  //   true
  // );

  // 2. 加载全部储备中心/预置点到地图（不限制距离）
  console.log("[index.vue] 加载全部储备中心/预置点到地图...");
  await loadReserveCentersAndPresets(
    DISASTER_CENTER.lon,
    DISASTER_CENTER.lat,
    true
  );


  // 3. 显示范围圈
  showRangeCircle();

  console.log("[index.vue] 已显示所有标记点和范围圈");
};

/**
 * 隐藏所有标记点和范围圈
 */
const hideAllMarkersAndRange = () => {
  const viewer = mapStore.viewer;
  if (!viewer) return;

  // 1. 隐藏模拟点位
  viewer.entities.values.forEach((entity) => {
    if (entity.properties) {
      const props = entity.properties;
      if (
        props.type?.getValue() === "soldier" ||
        props.type?.getValue() === "device" ||
        props.isPathStartMarker?.getValue()
      ) {
        entity.show = false;
      }
    }
  });

  // 2. 隐藏接口标记
  hideMarkers();

  // 3. 隐藏范围圈
  hideRangeCircle();

  console.log("[index.vue] 已隐藏所有标记点和范围圈");
};

/**
 * 在选中的应急点位置显示人员/装备初始标记
 * @param {Array} personnelPoints - 选中的人员应急点
 * @param {Array} equipmentPoints - 选中的装备应急点
 */
const showEmergencyPointMarkers = (personnelPoints, equipmentPoints) => {
  const viewer = mapStore.viewer;
  if (!viewer) return;

  console.log("🔥🔥🔥 [NEW CODE] 在应急点位置添加人员/装备标记 🔥🔥🔥");

  // 清除旧的应急点标记
  viewer.entities.values.forEach((entity) => {
    if (entity.properties) {
      const type = entity.properties.type?.getValue();
      if (type === "emergencyPersonnel" || type === "emergencyEquipment") {
        entity.show = false;
      }
    }
  });

  // 添加人员标记
  personnelPoints.forEach((point, index) => {
    viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(point.lon, point.lat, 0),
      billboard: {
        image: soldierIcon,
        width: 36,
        height: 40,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      },
      properties: new Cesium.PropertyBag({
        type: "emergencyPersonnel",
        name: point.name || `应急人员${index + 1}`,
        emergencyPointId: point.id,
      }),
      show: true,
    });
    console.log(`[index.vue] 已添加人员标记: ${point.name}`);
  });

  // 添加装备标记
  equipmentPoints.forEach((point, index) => {
    viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(point.lon, point.lat, 0),
      billboard: {
        image: deviceIcon,
        width: 36,
        height: 40,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      },
      properties: new Cesium.PropertyBag({
        type: "emergencyEquipment",
        name: point.name || `应急装备${index + 1}`,
        emergencyPointId: point.id,
      }),
      show: true,
    });
    console.log(`[index.vue] 已添加装备标记: ${point.name}`);
  });

  viewer.scene.requestRender();
  console.log("[index.vue] 应急点标记显示完成");
};

/**
 * 调整相机到显示范围圈区域
 * 根据当前搜索半径动态调整视角
 */
const flyToBestViewForMarkers = () => {
  const viewer = mapStore.viewer;
  if (!viewer) return;

  const { camera } = mapStore.services();

  // 获取当前搜索半径(公里)
  const radiusKm = disasterData.forcePreset.value.searchRadius + 20; // 加20km 保证能看到完整范围圈
  const radiusMeters = radiusKm * 1000;

  // 范围圈中心点
  const centerLon = DISASTER_CENTER.lon;
  const centerLat = DISASTER_CENTER.lat;

  // 计算范围圈边界的4个点(东西南北)
  // 1度纬度 ≈ 111km
  const latOffset = radiusKm / 111.32;
  // 1度经度 ≈ 111km * cos(纬度)
  const lonOffset =
    radiusKm / (111.32 * Math.cos(Cesium.Math.toRadians(centerLat)));

  const boundaryPoints = [
    { lon: centerLon, lat: centerLat + latOffset }, // 北
    { lon: centerLon + lonOffset, lat: centerLat }, // 东
    { lon: centerLon, lat: centerLat - latOffset }, // 南
    { lon: centerLon - lonOffset, lat: centerLat }, // 西
    { lon: centerLon, lat: centerLat }, // 中心
  ];

  // 使用智能聚焦方法飞向范围圈区域
  camera.fitBoundsWithTrajectory(boundaryPoints, {
    duration: 2, // 2秒飞行时间
    padding: 0.1, // 10%边距,确保范围圈完整显示
  });

  console.log(`[index.vue] 相机已调整到范围圈视角 (半径: ${radiusKm}km)`);
};

// ====================
// 数据加载函数
// ====================

/**
 * 加载养护站数据
 */
const loadEmergencyResources = async (longitude, latitude) => {
  try {
    const response = await request({
      url: `/snow-ops-platform/disaster/matchEmergencyResources`,
      method: "GET",
      params: {
        longitude,
        latitude,
        maxDistance: disasterData.forcePreset.value.searchRadius,
      },
    });

    if (response?.data) {
      disasterData.updateForcePreset(response.data);
      console.log("[index.vue] 应急资源数据加载成功:", response.data);

      if (mapStore.viewer) {
        console.log("[index.vue] 更新地图应急资源标记...");
        clearEmergencyResourceMarkers(mapStore.viewer);
        await addEmergencyResourceMarkers(
          mapStore.viewer,
          response.data,
          { longitude, latitude },
          { heightOffset: 10 }
        );
      } else {
        console.warn("[index.vue] 地图viewer未就绪，跳过标记更新");
      }
    } else {
      console.warn("[index.vue] 应急资源接口返回数据为空");
    }

    return response;
  } catch (error) {
    console.error("[index.vue] 加载应急资源数据失败:", error);
    ElMessage.warning({
      message: "应急资源数据加载失败,使用默认数据",
      duration: 3000,
    });
    return null;
  }
};

/**
 * 加载储备中心和预置点数据
 * @param {number} longitude - 经度（可选，不传则查询全部）
 * @param {number} latitude - 纬度（可选，不传则查询全部）
 * @param {boolean} loadAllForMap - 是否加载全部点位到地图（true时不限制距离）
 */
const loadReserveCentersAndPresets = async (longitude,
  latitude,
  loadAllForMap = false) => {
  try {
    // 构建请求参数
    const params = {};

    if (!loadAllForMap && longitude !== undefined && latitude !== undefined) {
      // 正常模式：传递经纬度和距离限制
      params.longitude = longitude;
      params.latitude = latitude;
      params.maxDistance = disasterData.forcePreset.value.searchRadius;
    }
    // loadAllForMap 为 true 时，不传任何参数，获取全部数据

    const response = await request({
      url: `/snow-ops-platform/yhYjll/list`,
      method: "GET",
      params,
    });

    if (response?.data && Array.isArray(response.data)) {
      console.log(
        "[index.vue] 储备中心和预置点数据加载成功:",
        response.data?.length,
        "个点位"
      );

      // 1. 转换数据为标准 stations 格式
      const transformedStations = disasterData.transformReserveDataToStations(
        response.data,
        { longitude, latitude }
      );

      // 2. 仅在非"全部加载"模式下更新 forcePreset.stations（用于 station-list 显示）
      if (!loadAllForMap && transformedStations.length > 0) {
        disasterData.forcePreset.value.stations = transformedStations;
        console.log(
          "[index.vue] 已更新 forcePreset.stations:",
          transformedStations.length,
          "个"
        );
      }
      // 3. 添加地图标记（全部或范围内）
      if (mapStore.viewer) {
        console.log("[index.vue] 添加储备中心和预置点地图标记...");
        clearReserveCenterMarkers(mapStore.viewer);
        await addReserveCenterMarkers(
          mapStore.viewer,
          response.data,
          {
            heightOffset: 10,
          },
          { longitude, latitude }
        );
      } else {
        console.warn("[index.vue] 地图viewer未就绪，跳过标记更新");
      }
    } else {
      console.warn("[index.vue] 储备中心和预置点接口返回数据为空");
    }

    return response;
  } catch (error) {
    console.error("[index.vue] 加载储备中心和预置点数据失败:", error);
    ElMessage.warning({
      message: "储备中心和预置点数据加载失败",
      duration: 3000,
    });
    return null;
  }
}

/**
 * 加载储备中心和预置点数据 以及加载应急力量统计数据
 * @param {number} longitude - 经度（可选，不传则查询全部）
 * @param {number} latitude - 纬度（可选，不传则查询全部）
 * @param {boolean} loadAllForMap - 是否加载全部点位到地图（true时不限制距离）
 */
const loadReserveCentersAndPresetsAndStatistics = async (
  longitude,
  latitude,
  loadAllForMap = false
) => {
  try {
    // 构建请求参数
    const params = {};

    if (!loadAllForMap && longitude !== undefined && latitude !== undefined) {
      // 正常模式：传递经纬度和距离限制
      params.longitude = longitude;
      params.latitude = latitude;
      params.maxDistance = disasterData.forcePreset.value.searchRadius;
    }
    // loadAllForMap 为 true 时，不传任何参数，获取全部数据

    const response = await request({
      url: `/snow-ops-platform/yhYjll/listWithStatistics`,
      method: "GET",
      params,
    });

    if (response?.data && Array.isArray(response.data?.list)) {
      console.log(
        "[index.vue] 储备中心和预置点数据加载成功:",
        response.data?.list.length,
        "个点位"
      );

      // 1. 转换数据为标准 stations 格式
      const transformedStations = disasterData.transformReserveDataToStations(
        response.data.list,
        { longitude, latitude }
      );

      // 2. 仅在非"全部加载"模式下更新 forcePreset.stations（用于 station-list 显示）
      if (!loadAllForMap && transformedStations.length > 0) {
        disasterData.forcePreset.value.stations = transformedStations;
        console.log(
          "[index.vue] 已更新 forcePreset.stations:",
          transformedStations.length,
          "个"
        );
      }

      // 3.更新应急力量统计列表
      if (response?.data?.statistics) {
        // 保存统计数据到状态 (仅更新统计,不更新stations)
        disasterData.updateForcePreset(response.data.statistics, { onlyStatistics: true });
        console.log("[index.vue] 应急统计数据加载成功:", response.data.statistics);
      } else {
        console.warn("[index.vue] 应急统计数据接口返回数据为空");
      }

      // 4. 添加地图标记（全部或范围内）
      if (mapStore.viewer) {
        console.log("[index.vue] 添加储备中心和预置点地图标记...");
        clearReserveCenterMarkers(mapStore.viewer);
        await addReserveCenterMarkers(
          mapStore.viewer,
          response.data.list,
          {
            heightOffset: 10,
          },
          { longitude, latitude }
        );
      } else {
        console.warn("[index.vue] 地图viewer未就绪，跳过标记更新");
      }
    } else {
      console.warn("[index.vue] 储备中心和预置点接口返回数据为空");
    }

    return response;
  } catch (error) {
    console.error("[index.vue] 加载储备中心和预置点数据失败:", error);
    ElMessage.warning({
      message: "储备中心和预置点数据加载失败",
      duration: 3000,
    });
    return null;
  }
};

/**
 * 加载应急基地与预置点、应急装备、应急物资、应急人员的统计数量
 * /snow-ops-platform/yhYjll/statistics
 */
const loadEmergencyBaseAndPreset = async (longitude, latitude) => {
  try {
    const response = await request({
      url: `/snow-ops-platform/yhYjll/statistics`,
      method: "GET",
      params: {
        longitude,
        latitude,
        maxDistance: disasterData.forcePreset.value.searchRadius,
      },
    });

    if (response?.data) {
      // 保存统计数据到状态 (仅更新统计,不更新stations)
      disasterData.updateForcePreset(response.data, { onlyStatistics: true });
      console.log("[index.vue] 应急统计数据加载成功:", response.data);
    } else {
      console.warn("[index.vue] 应急统计数据接口返回数据为空");
    }

    return response;
  } catch (error) {
    console.error("[index.vue] 加载应急统计数据失败:", error);
    ElMessage.warning({
      message: "应急统计数据加载失败",
      duration: 3000,
    });
    return null;
  }
};

/**
 * 查询应急装备和应急物资列表 /snow-ops-platform/yhYjll/listMaterials
 */
const loadEmergencyEquipmentAndMaterial = async (longitude, latitude) => {
  try {
    const response = await request({
      url: `/snow-ops-platform/yhYjll/listMaterials`,
      method: "GET",
      params: {
        longitude,
        latitude,
        maxDistance: disasterData.forcePreset.value.searchRadius,
      },
    });
    if (response?.data) {
      console.log("[index.vue] 应急装备和应急物资列表加载成功:", response.data);
    } else {
      console.warn("[index.vue] 应急装备和应急物资列表接口返回数据为空");
    }
    return response;
  } catch (error) {
    console.error("[index.vue] 查询应急装备和应急物资列表失败:", error);
    ElMessage.warning({
      message: "应急装备和应急物资列表数据加载失败",
      duration: 3000,
    });
    return null;
  }
};
loadEmergencyEquipmentAndMaterial(DISASTER_CENTER.lon, DISASTER_CENTER.lat)
  .then((response) => {
    console.log("[index.vue] 应急装备和应急物资列表加载成功:", response.data);
  })
  .catch((error) => {
    console.error("[index.vue] 查询应急装备和应急物资列表失败:", error);
  });

// ====================
// 场景初始化函数
// ====================

/**
 * 初始化场景
 */
const initializeScene = async () => {
  const viewer = mapStore.viewer;
  if (!viewer) {
    console.error("[index.vue] viewer 未就绪");
    return;
  }

  console.log("[index.vue] 开始初始化场景...");

  // 1. 启用模型对比功能（界面立即呈现，模型延迟加载）
  try {
    console.log("[index.vue] 启用模型对比功能（不加载左侧模型）...");
    await toggleCompareMode(true, viewer, { skipLeftModelLoad: true });
    console.log("[index.vue] 模型对比界面已启用");
  } catch (error) {
    console.error("[index.vue] 启用模型对比功能失败:", error);
  }

  // 2. 定位相机到目标位置
  console.log("[index.vue] 设置相机到目标位置...");
  viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(
      DEFAULT_CAMERA_POSITION.lon,
      DEFAULT_CAMERA_POSITION.lat,
      DEFAULT_CAMERA_VIEW.height
    ),
    orientation: {
      heading: Cesium.Math.toRadians(DEFAULT_CAMERA_VIEW.heading),
      pitch: Cesium.Math.toRadians(DEFAULT_CAMERA_VIEW.pitch),
      roll: DEFAULT_CAMERA_VIEW.roll,
    },
  });

  // 3. 添加模拟点位（人员和设备）- 已移至步骤10.5（地形就绪后）
  // 原因：在地形加载前添加会导致相机飞行时标记悬浮
  // const allMockPoints = mockDataService.getAllMockPoints()
  // allMockPoints.forEach((point) => {
  //   const config =
  //     point.type === 'soldier'
  //       ? mockDataService.createPersonnelEntityConfig(point, soldierIcon)
  //       : mockDataService.createDeviceEntityConfig(point, deviceIcon)
  //   viewer.entities.add(config)
  // })
  // console.log(`[index.vue] 已添加 ${allMockPoints.length} 个模拟点位`)

  // 4. 添加路径起点标记（用于"一键启动"）- 已移至步骤10.5（地形就绪后）
  // 原因：在地形加载前添加会导致相机飞行时标记悬浮
  // const allPaths = mockDataService.getAllAnimationPaths()
  // Object.entries(allPaths).forEach(([pathId, path]) => {
  //   const icon = path.metadata.type === 'soldier' ? soldierIcon : deviceIcon
  //   const config = mockDataService.createPathStartMarkerConfig(
  //     { ...path, id: pathId },
  //     icon
  //   )
  //   viewer.entities.add(config)
  // })
  // console.log('[index.vue] 已添加 3 个路径起点标记')

  // 5. 设置地图点击事件监听
  mapClickHandler.setupClickHandler(
    viewer,
    registerEventHandler,
    registerPostRenderListener
  );

  // 6. 加载右侧 3D Tiles（灾后模型）
  try {
    console.log("[index.vue] 开始加载3D模型...");
    const afterTileset = await load3DTileset(viewer, "after", false);

    if (afterTileset) {
      console.log("[index.vue] 等待3D模型完全就绪...");
      await waitForTilesetReady(afterTileset);
      console.log("[index.vue] 3D模型已完全就绪");

      // 等待地形数据准备就绪
      await new Promise((resolve) => setTimeout(resolve, 2000));

      // 添加中心点标记
      console.log("[index.vue] 添加中心点标记...");
      console.log(
        "[index.vue] 中心点标记位置:",
        DISASTER_CENTER.lon,
        DISASTER_CENTER.lat
      );
      viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(
          DISASTER_CENTER.lon,
          DISASTER_CENTER.lat,
          0
        ),
        billboard: {
          image: eventIcon,
          width: 60,
          height: 60,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
        },
      });
      console.log("[index.vue] 中心点标记已添加");

      // 绘制坍塌边界红色实线
      console.log("[index.vue] 绘制坍塌边界红色实线...");
      drawCollapseBoundary(viewer);
      console.log("[index.vue] 坍塌边界红色实线已添加");
    }
  } catch (error) {
    console.error("[index.vue] 3D模型加载失败:", error);
  }

  // 7. 延迟加载左侧 3D Tiles（灾前模型）
  try {
    console.log("[index.vue] 开始加载左侧灾前模型...");
    await toggleCompareMode(true, viewer, { loadLeftModel: true });
    console.log("[index.vue] 左侧灾前模型加载完成");

    // 在左侧地图绘制红色虚线边界
    // const leftContainer = document.getElementById('leftCesiumContainer')
    // if (leftContainer) {
    //   console.log('[index.vue] 绘制左侧坍塌边界红色虚线...')
    //   drawCollapseBoundaryLeft(leftContainer)

    //   console.log('[index.vue] 左侧坍塌边界红色虚线已添加')
    // }
  } catch (error) {
    console.error("[index.vue] 左侧模型加载失败:", error);
  }

  // 8. 初始化地图标记
  // try {
  //   console.log("[index.vue] 开始初始化地图标记...");
  //   await initializeMarkers(viewer, {
  //     useSampledHeights: true,
  //     heightOffset: 100,
  //   });
  //   console.log("[index.vue] 地图标记初始化完成");
  // } catch (error) {
  //   console.error("[index.vue] 地图标记初始化失败:", error);
  // }

  // 9. 创建范围圈
  createOrUpdateRangeCircle(
    viewer,
    disasterData.forcePreset.value.searchRadius
  );

  // 默认隐藏范围圈(等待快速匹配激活)
  hideRangeCircle();
  console.log("[index.vue] 已隐藏范围圈(等待快速匹配激活)");

  // 10. 额外等待确保地形完全就绪（避免标记悬浮）
  console.log("[index.vue] 等待地形完全就绪...");
  await new Promise((resolve) => setTimeout(resolve, 1000));

  // 10.5. 添加模拟点位和路径起点标记（在地形就绪后）
  console.log("[index.vue] 添加模拟点位...");
  const allMockPoints = mockDataService.getAllMockPoints();
  allMockPoints.forEach((point) => {
    const config =
      point.type === "soldier"
        ? mockDataService.createPersonnelEntityConfig(point, soldierIcon)
        : mockDataService.createDeviceEntityConfig(point, deviceIcon);
    viewer.entities.add(config);
  });
  console.log(`[index.vue] 已添加 ${allMockPoints.length} 个模拟点位`);

  // 添加路径起点标记（用于"一键启动"）
  const allPaths = mockDataService.getAllAnimationPaths();
  Object.entries(allPaths).forEach(([pathId, path]) => {
    const icon = path.metadata.type === "soldier" ? soldierIcon : deviceIcon;
    const config = mockDataService.createPathStartMarkerConfig(
      { ...path, id: pathId },
      icon
    );
    viewer.entities.add(config);
  });
  console.log("[index.vue] 已添加 3 个路径起点标记");

  // 触发立即渲染，确保 CLAMP_TO_GROUND 生效
  viewer.scene.requestRender();

  // 默认隐藏模拟点位(等待快速匹配点击时显示)
  viewer.entities.values.forEach((entity) => {
    if (entity.properties) {
      const props = entity.properties;
      // 隐藏模拟点位(soldier/device)和路径起点标记
      if (
        props.type?.getValue() === "soldier" ||
        props.type?.getValue() === "device" ||
        props.isPathStartMarker?.getValue()
      ) {
        entity.show = false;
      }
    }
  });
  console.log("[index.vue] 已隐藏模拟点位(等待快速匹配激活)");

  // 11. 加载应急资源数据（在地形就绪后）
  console.log("[index.vue] 加载应急资源数据...");
  // await loadEmergencyResources(DISASTER_CENTER.lon, DISASTER_CENTER.lat)

  // 默认隐藏接口标记(等待快速匹配激活)
  hideMarkers();
  console.log("[index.vue] 已隐藏应急资源标记(等待快速匹配激活)");

  // // 12. 加载储备中心和预置点数据 并且 加载应急统计数据（新增）
  // console.log("[index.vue] 加载储备中心和预置点数据...");
  // await loadReserveCentersAndPresetsAndStatistics(DISASTER_CENTER.lon, DISASTER_CENTER.lat);

  // 12. 加载应急统计数据
  console.log("[index.vue] 加载应急统计数据...");
  await loadEmergencyBaseAndPreset(DISASTER_CENTER.lon, DISASTER_CENTER.lat);

  // 13. 加载储备中心和预置点数据
  console.log("[index.vue] 加载储备中心和预置点数据...");
  await loadReserveCentersAndPresets(DISASTER_CENTER.lon, DISASTER_CENTER.lat);

  cesiumViewer.value = viewer;
  console.log("[index.vue] 场景初始化完成");
};

// ====================
// 生命周期钩子
// ====================

/**
 * 组件挂载
 * 统一的初始化入口
 */
onMounted(() => {
  // 等待地图就绪后初始化场景（数据加载已在 initializeScene 中完成）
  mapStore.onReady(async () => {
    console.log("[index.vue] 3D态势感知地图已就绪");

    // 初始化场景（包含所有数据加载）
    await initializeScene();
  });
});

/**
 * 组件卸载
 * 清理所有资源
 */
onUnmounted(() => {
  console.log("[index.vue] 组件卸载，开始清理资源...");

  const viewer = mapStore.viewer;
  const leftContainer = document.getElementById("leftCesiumContainer");

  // 清理范围圈
  if (viewer) {
    clearRangeCircle(viewer);
    // 清理坍塌边界线（包括左右两侧）
    clearCollapseBoundary(viewer, leftContainer);
  }

  // 清理地图点击处理器
  mapClickHandler.destroy();

  // 清理所有 Cesium 资源（由 useCesiumLifecycle 自动执行）
  cleanup();

  console.log("[index.vue] 资源清理完成");
});

// ====================
// 防御性watch - 确保状态始终一致
// ====================

// 作为保险机制,确保即使有新入口直接操作useDualMapCompare,状态也能保持一致
watch(
  isCompareMode,
  (newValue) => {
    if (!newValue && activeToolKey.value === COMPARE_TOOL_KEY) {
      console.warn("[index.vue] 检测到对比模式被外部关闭,同步更新工具状态");
      activeToolKey.value = null;
    }
  },
  { immediate: false }
);

// ====================
// Provide 给子组件
// ====================

provide("disasterData", disasterData);
provide("onDistanceChange", handleDistanceChange);
// 提供 viewer 和动画方法
provide("cesiumViewer", cesiumViewer);
provide("triggerJump", (duration = 5, height = 30) => {
  triggerJumpAnimation(cesiumViewer.value, duration, height, disasterData);
});

// 将传入的token保存到本地
import { useRoute, useRouter } from "vue-router";
const route = useRoute();
const token = route.query.token;
const router = useRouter();
if (token) {
  localStorage.setItem("token", token);
  router.replace({ path: route.path }).then(() => {
    window.location.reload();
  });
}
</script>
<style scoped lang="scss">
@use "@/styles/mixins.scss" as *;
@use "./assets/styles/common.scss" as *;

.situational-awareness {
  // 容器查询设置，用于嵌入场景的自适应缩放
  container-name: situational-awareness;
  container-type: size;

  // 为旧版浏览器提供视口单位回退，封顶 1920×1080
  --cq-inline-100: clamp(0px, 100vw, 1920px);
  --cq-block-100: clamp(0px, 100vh, 1080px);

  // 当支持容器单位时覆盖为容器单位，同样封顶
  @supports (width: 1cqw) {
    --cq-inline-100: min(100cqw, 1920px);
  }

  @supports (height: 1cqh) {
    --cq-block-100: min(100cqh, 1080px);
  }

  // 可配置的布局变量（使用 calc 直接计算，避免函数嵌套）
  --sa-left-width: calc(464 / 1920 * var(--cq-inline-100, 100vw));
  --sa-right-width: calc(486 / 1920 * var(--cq-inline-100, 100vw));
  --sa-gap: calc(16 / 1920 * var(--cq-inline-100, 100vw));
  --sa-padding: calc(16 / 1920 * var(--cq-inline-100, 100vw));
  --sa-header-height: calc(131 / 1080 * var(--cq-block-100, 100vh)); // Header 高度
  --sa-min-width: 1280px;
  --sa-min-height: 720px;

  position: relative;
  width: 100%;
  height: 100%;
  // max-width: 1920px;
  // max-height: 1080px;
  min-width: var(--sa-min-width);
  min-height: var(--sa-min-height);
  background-color: var(--bg-dark);
  overflow-x: hidden;
  overflow-y: auto; // 当宿主尺寸 < 最小尺寸时允许滚动，达到上限时不放大

  // PageHeader 浮在顶部
  > :first-child {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 10;
  }

  &__main {
    position: absolute;
    inset: 0; // 铺满整个容器
    background: url(./assets/images/main-bg.png) center/cover no-repeat;
    overflow: hidden;
  }

  // 地图底层 - 填满整个容器
  &__map-layer {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: flex;

    // 默认单地图模式
    &:not(.is-compare-mode) {
      .situational-awareness__right-map {
        width: 100%;
      }

      .situational-awareness__left-map {
        width: 0;
        opacity: 0;
        pointer-events: none;
        overflow: hidden;
      }
    }

    // 双地图对比模式
    &.is-compare-mode {
      .situational-awareness__left-map {
        width: 50%;
        opacity: 1;
        pointer-events: auto;
        transition: width 0.3s ease, opacity 0.3s ease;
      }

      .situational-awareness__right-map {
        width: 50%;
        transition: width 0.3s ease;
      }
    }
  }

  // 左侧地图容器（灾前场景 - 对比时显示）
  &__left-map {
    position: relative;
    height: 100%;
    background: #000;
  }

  // 右侧地图容器（灾后场景 - 主地图）
  &__right-map {
    position: relative;
    height: 100%;
  }

  // 中间分割线
  &__center-divider {
    position: absolute;
    left: 50%;
    top: 0;
    bottom: 0;
    width: 2px;
    background: linear-gradient(to bottom,
        rgba(255, 255, 255, 0.1),
        rgba(255, 255, 255, 0.5),
        rgba(255, 255, 255, 0.1));
    z-index: 1;
    pointer-events: none;
  }

  // 地图遮罩层 - 覆盖在地图之上，增强视觉效果
  &__map-mask {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none; // 不阻挡交互
    // 使用 cockpit 的遮罩层图片，保持视觉一致性
    background: url(@/views/cockpit/assets/img/遮罩层.png) center/cover no-repeat;
  }

  // 场景标签层 - 显示在遮罩层和面板层之上
  &__scene-labels-layer {
    position: absolute;
    inset: 0;
    z-index: 10;
    pointer-events: none; // 标签不阻挡交互

    .situational-awareness__sync-btn {
      position: absolute;
      left: 32%;
      top: calc(var(--sa-header-height));
      height: 31px;

      pointer-events: auto; // 恢复按钮的交互能力
    }
  }

  // 浮动面板层 - 使用绝对定位固定面板位置
  &__panels-layer {
    position: absolute;
    inset: 0;
    z-index: 2;
    height: 100%;
    pointer-events: none; // 容器不拦截事件，让中间区域透明
  }

  // 左右面板列 - 浮动卡片样式
  &__panel-column {
    position: absolute;
    // top: var(--sa-header-height); // 从 header 下方开始
    // bottom: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sa-gap); // 列内子面板之间的间距
    min-width: 0; // 防止在窄容器中溢出
    min-height: 0; // 允许 flex 子元素收缩并启用滚动
    pointer-events: auto; // 恢复面板的交互能力
    height: 100%;

    // 左侧面板固定在左边
    &--left {
      left: 0;
      width: var(--sa-left-width);
    }

    // 右侧面板固定在右边
    &--right {
      right: 0;
      width: var(--sa-right-width);
    }
  }

  // 中间占位区域 - 透明且不可交互，点击穿透到地图
  &__center-spacer {
    pointer-events: none;
  }

  // 折叠按钮层 - 独立层级，放置在屏幕两侧
  &__collapse-buttons-layer {
    position: absolute;
    inset: 0;
    z-index: 11; // 高于场景标签层
    pointer-events: none; // 容器不拦截事件
    padding-top: var(--sa-header-height); // 预留 Header 高度
  }

  // 折叠按钮
  &__collapse-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: transparent;
    border: none;
    cursor: pointer;
    pointer-events: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s ease;
    z-index: 11;
    padding: 0;

    &:hover {
      opacity: 0.8;
    }

    &:active {
      transform: translateY(-50%) scale(0.95);
    }

    .collapse-arrow {
      width: vw(30);
      height: auto;
      transition: all 0.3s ease;
    }

    // 左侧按钮 - 固定在屏幕最左侧
    &--left {
      left: 0;
    }

    // 右侧按钮 - 固定在屏幕最右侧
    &--right {
      right: 0;
    }
  }

  // 面板滑动动画 - 左侧
  .panel-slide-left-enter-active,
  .panel-slide-left-leave-active {
    transition: all 0.3s ease;
  }

  .panel-slide-left-enter-from {
    transform: translateX(-100%);
    opacity: 0;
  }

  .panel-slide-left-leave-to {
    transform: translateX(-100%);
    opacity: 0;
  }

  // 面板滑动动画 - 右侧
  .panel-slide-right-enter-active,
  .panel-slide-right-leave-active {
    transition: all 0.3s ease;
  }

  .panel-slide-right-enter-from {
    transform: translateX(100%);
    opacity: 0;
  }

  .panel-slide-right-leave-to {
    transform: translateX(100%);
    opacity: 0;
  }

  // 地图控件层 - 高于遮罩和面板，用于放置地图控制工具
  &__controls-layer {
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none; // 容器不拦截事件
    display: flex;
    justify-content: center;
    align-items: flex-end;
    padding-bottom: 30px; // 临时使用固定值，确保控件显示
  }

  // 控件容器 - 恢复交互能力
  &__controls {
    pointer-events: auto;
    position: relative;
    // 调试：确保控件容器可见
    min-height: 56px; // MapControls 的高度
  }

  // 地图 Tooltip 层 - 覆盖地图和面板，仅 Tooltip 自身可交互
  &__tooltip-layer {
    position: absolute;
    inset: 0;
    z-index: 4; // 高于控件层
    pointer-events: none; // 容器不拦截事件，点击穿透到地图
  }

  // 加载动画层 - 一键启动后显示
  &__loading-layer {
    position: absolute;
    top: calc(var(--sa-header-height) + vh(40));
    left: 0;
    right: 0;
    // bottom: 0;
    z-index: 5; // 高于 Tooltip 层
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none; // 不阻止点击穿透
  }

  // 加载 GIF 图片
  &__loading-gif {
    width: auto;
    height: auto;
    max-width: 320px;
    max-height: 55px;
    object-fit: contain;
  }
}

// Tooltip 内容字段样式
// 用于在 Tooltip 插槽中展示字段列表
.tooltip-field-item {
  display: flex;
  align-items: baseline;
  gap: vw(8);
  padding: vh(6) 0;

  .tooltip-field-label {
    color: var(--text-gray);
    font-size: fs(13);
    font-family: SourceHanSansCN-Regular, sans-serif;
    white-space: nowrap;
    flex-shrink: 0;
  }

  .tooltip-field-value {
    color: var(--text-white);
    font-size: fs(13);
    font-family: SourceHanSansCN-Medium, sans-serif;
    font-weight: 500;
    flex: 1;
    word-break: break-all;
  }
}

// Tooltip 操作按钮样式
// 用于"连线"、"联动"等交互按钮
.tooltip-action-btn {
  min-width: vw(100);
  height: vh(36);
  padding: 0 vw(24);
  background: url("./assets/images/地图tooltip-button.png") no-repeat center/100% 100%;
  border: none;
  color: var(--text-white);
  font-size: fs(14);
  font-family: SourceHanSansCN-Medium, sans-serif;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;

  &:hover {
    filter: brightness(1.2);
    transform: translateY(vh(-2));
  }

  &:active {
    filter: brightness(0.9);
    transform: translateY(0);
  }
}

// 窄容器嵌入的紧凑布局（<1100px 宽度）
.situational-awareness.is-compact {
  --sa-left-width: calc(380 / 1920 * var(--cq-inline-100, 100vw));
  --sa-right-width: calc(400 / 1920 * var(--cq-inline-100, 100vw));
  --sa-gap: calc(12 / 1920 * var(--cq-inline-100, 100vw));
  --sa-padding: calc(12 / 1920 * var(--cq-inline-100, 100vw));
}

// 嵌入模式 - 使用更保守的最小尺寸
.situational-awareness.is-embedded {
  --sa-min-width: 1024px;
  --sa-min-height: 600px;
}
</style>
