<template>
  <div
    class="flex-1 h-full w-full bg-base-200 relative overflow-hidden diagram-container flex flex-col select-none"
    ref="canvasContainer"
    @mousedown="handleCanvasMouseDown"
    @mousedown.middle.prevent="startMiddleDrag"
    @wheel.prevent="onZoom"
    @contextmenu.prevent="handleContextMenu"
  >
    <!-- 工具栏 -->
    <div class="absolute top-2 right-2 flex gap-2 z-30">
      <button class="btn btn-sm btn-primary" @click="openDiagramFileSelector">
        <FolderOpen class="h-4 w-4 mr-1" />
        导入
      </button>
      <button class="btn btn-sm btn-primary" @click="exportDiagram">
        <Download class="h-4 w-4 mr-1" />
        导出
      </button>
      <button class="btn btn-sm btn-primary" @click="emit('open-components')">
        <Plus class="h-4 w-4 mr-1" />
        添加组件
      </button>
      <button class="btn btn-sm btn-primary" @click="emit('toggle-doc-panel')">
        <FileText class="h-4 w-4 mr-1" />
        {{ props.showDocPanel ? "属性面板" : "文档" }}
      </button>
    </div>

    <!-- 隐藏的文件输入 -->
    <input
      type="file"
      ref="fileInput"
      class="hidden"
      accept=".json"
      @change="handleFileSelected"
    />

    <div
      ref="canvas"
      class="diagram-canvas relative select-none"
      :style="{
        transform: `translate(${componentManager.canvasPosition.x}px, ${componentManager.canvasPosition.y}px) scale(${componentManager.canvasScale.value})`,
      }"
    >
      <!-- 渲染连线 -->
      <svg
        class="wires-layer absolute top-0 left-0 w-full h-full z-50"
        width="10000"
        height="10000"
      >
        <!-- 已完成的连线 -->
        <WireComponent
          v-for="(wire, index) in wireItems"
          :key="wire.id"
          :id="wire.id"
          :start-x="wire.startX"
          :start-y="wire.startY"
          :end-x="wire.endX"
          :end-y="wire.endY"
          :stroke-color="wire.color || '#4a5568'"
          :stroke-width="wire.strokeWidth"
          :is-active="false"
          :start-component-id="wire.startComponentId"
          :start-pin-id="wire.startPinId"
          :end-component-id="wire.endComponentId"
          :end-pin-id="wire.endPinId"
          :routing-mode="wire.routingMode"
          :path-commands="wire.pathCommands"
        />

        <!-- 正在创建的连线 -->
        <WireComponent
          v-if="isCreatingWire"
          id="temp-wire"
          :start-x="creatingWireStart.x"
          :start-y="creatingWireStart.y"
          :end-x="mousePosition.x"
          :end-y="mousePosition.y"
          stroke-color="#3182ce"
          :stroke-width="2"
          :is-active="true"
        />
      </svg>

      <!-- 渲染画布上的组件 -->
      <div
        v-for="component in diagramParts"
        :key="component.id"
        class="component-wrapper absolute p-0 inline-block overflow-visible select-none"
        :class="{
          'component-hover': hoveredComponent === component.id,
          'component-selected': selectedComponentId === component.id,
          'cursor-not-allowed grayscale-70 opacity-60': !component.isOn,
          'component-hidepins': component.hidepins,
        }"
        :style="{
          top: component.y + 'px',
          left: component.x + 'px',
          zIndex: component.index ?? 0,
          transform: component.rotate
            ? `rotate(${component.rotate}deg)`
            : 'none',
          opacity: component.isOn ? 1 : 0.6,
          display: 'block',
        }"
        @mousedown.left.stop="startComponentDrag($event, component)"
        @mouseover="hoveredComponent = component.id"
        @mouseleave="hoveredComponent = null"
      >
        <!-- 动态渲染组件 -->
        <component
          :is="componentManager.getComponentDefinition(component.type)"
          v-if="
            componentManager.componentModules.value[component.type] &&
            componentManager.getComponentDefinition(component.type)
          "
          v-bind="
            componentManager.prepareComponentProps(
              component.attrs || {},
              component.id,
              props.examId,
            )
          "
          @update:bindKey="
            (value: string) =>
              updateComponentProp(component.id, 'bindKey', value)
          "
          @pin-click="
            (pinInfo: any) =>
              handlePinClick(component.id, pinInfo, pinInfo.originalEvent)
          "
          :ref="(el: any) => componentManager.setComponentRef(component.id, el)"
        />

        <!-- Fallback if component module not loaded yet -->
        <div
          v-else
          class="p-2 text-xs text-gray-400 border border-dashed border-gray-400 flex items-center justify-center"
        >
          <div class="flex flex-col items-center">
            <div class="loading loading-spinner loading-xs mb-1"></div>
            <span>Loading {{ component.type }}...</span>
            <small class="mt-1 text-xs">{{
              componentManager.componentModules.value[component.type]
                ? "Module loaded but invalid"
                : "Module not found"
            }}</small>
          </div>
        </div>
      </div>
    </div>

    <!-- 加载指示器 -->
    <div
      v-if="isLoading"
      class="absolute inset-0 bg-black bg-opacity-30 flex items-center justify-center z-50"
    >
      <div class="loading loading-spinner loading-lg text-primary"></div>
    </div>

    <!-- 缩放指示器 -->
    <div
      class="absolute bottom-4 right-4 bg-base-100 px-3 py-1.5 rounded-md shadow-md z-20"
      style="opacity: 0.9"
    >
      <span class="text-sm font-medium"
        >{{ Math.round(componentManager?.canvasScale.value * 100) }}%</span
      >
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  ref,
  reactive,
  onMounted,
  computed,
  provide,
} from "vue";
import { useEventListener } from "@vueuse/core";
import { FolderOpen, Download, Plus, FileText } from "lucide-vue-next";
import WireComponent from "@/components/equipments/Wire.vue";
import { useAlertStore } from "@/components/Alert";

// 导入 diagram 管理器
import {
  loadDiagramData,
  updatePartPosition,
  updatePartAttribute,
  parseConnectionPin,
  connectionArrayToWireItem,
  validateDiagramData,
} from "./composable/diagramManager";

import type {
  DiagramData,
  DiagramPart,
  ConnectionArray,
  WireItem,
} from "./composable/diagramManager";

import { CanvasCurrentSelectedComponentID } from "../InjectKeys";
import { useComponentManager } from "./composable/componentManager";

// 右键菜单处理函数
function handleContextMenu(e: MouseEvent) {
  e.preventDefault();
}

// 定义组件发出的事件
const emit = defineEmits(["toggle-doc-panel", "open-components"]);

// 定义组件接受的属性
const props = defineProps<{
  showDocPanel?: boolean; // 添加属性接收文档面板的显示状态
  examId?: string; // 新增examId属性
}>();

// 获取componentManager实例
const componentManager = useComponentManager();
if (!componentManager) {
  throw new Error(
    "DiagramCanvas must be used within a component manager provider",
  );
}

// 获取Alert store实例
const alertStore = useAlertStore();

// --- 画布状态 ---
const canvasContainer = ref<HTMLElement | null>(null);
const canvas = ref<HTMLElement | null>(null);
const isDragging = ref(false);
const isMiddleDragging = ref(false);
const dragStart = reactive({ x: 0, y: 0 });
const selectedComponentId = ref<string | null>(null);
const hoveredComponent = ref<string | null>(null);
const draggingComponentId = ref<string | null>(null);
const componentDragOffset = reactive({ x: 0, y: 0 });

// Provide and Inject
provide(CanvasCurrentSelectedComponentID, selectedComponentId);

// Diagram 数据
const diagramData = ref<DiagramData>({
  version: 1,
  author: "admin",
  editor: "me",
  parts: [],
  connections: [],
});

// 计算属性：从 diagramData 中提取组件列表，并按index属性排序
const diagramParts = computed<DiagramPart[]>(() => {
  // 克隆原始数组以避免直接修改原始数据
  const parts = [...diagramData.value.parts];

  // 按照index属性进行排序，index值大的排在后面（显示在上层）
  // 如果没有定义index则默认为0
  return parts.sort((a, b) => {
    const indexA = a.index ?? 0;
    const indexB = b.index ?? 0;
    return indexA - indexB;
  });
});

// 计算属性：转换连接为 WireItem 列表以供渲染
const wireItems = computed<WireItem[]>(() => {
  // 检查组件是否仍然挂载
  if (!document.body.contains(canvasContainer.value)) {
    return []; // 如果组件已经卸载，返回空数组
  }

  return diagramData.value.connections.map((conn, index) => {
    const [startPin, endPin] = conn;
    const { componentId: startCompId, pinId: startPinId } =
      parseConnectionPin(startPin);
    const { componentId: endCompId, pinId: endPinId } =
      parseConnectionPin(endPin);

    // 查找对应的组件位置
    const startComp = diagramParts.value.find((p) => p.id === startCompId);
    const endComp = diagramParts.value.find((p) => p.id === endCompId);

    // 默认位置（如果找不到组件）
    const startPos = { x: 0, y: 0 };
    const endPos = { x: 0, y: 0 };

    // 如果找到组件，设置连线端点位置
    if (startComp) {
      startPos.x = startComp.x;
      startPos.y = startComp.y;

      // 尝试获取引脚精确位置（如果有实现）
      const startCompRef = componentManager?.getComponentRef(startCompId);
      if (startCompRef && typeof startCompRef.getPinPosition === "function") {
        try {
          const pinPos = startCompRef.getPinPosition(startPinId);
          console.log(
            `线路${index} - 起点引脚位置(来自${startCompId}):`,
            pinPos,
          );

          if (pinPos) {
            // 正确合并组件位置与引脚相对位置
            startPos.x = startComp.x + pinPos.x;
            startPos.y = startComp.y + pinPos.y;
            console.log(`线路${index} - 计算后的起点位置:`, startPos);
          }
        } catch (error) {
          // console.error(`获取引脚位置出错:`, error);
        }
      }
    }

    if (endComp) {
      endPos.x = endComp.x;
      endPos.y = endComp.y;

      // 尝试获取引脚精确位置
      const endCompRef = componentManager?.getComponentRef(endCompId);
      if (endCompRef && typeof endCompRef.getPinPosition === "function") {
        try {
          const pinPos = endCompRef.getPinPosition(endPinId);
          console.log(`线路${index} - 终点引脚位置(来自${endCompId}):`, pinPos);

          if (pinPos) {
            // 正确合并组件位置与引脚相对位置
            endPos.x = endComp.x + pinPos.x;
            endPos.y = endComp.y + pinPos.y;
            console.log(`线路${index} - 计算后的终点位置:`, endPos);
          }
        } catch (error) {
          console.error(`获取引脚位置出错:`, error);
        }
      }
    }

    return connectionArrayToWireItem(conn, index, startPos, endPos);
  });
});

// 连线创建状态
const isCreatingWire = ref(false);
const creatingWireStart = reactive({ x: 0, y: 0 });
const creatingWireStartInfo = reactive({
  componentId: "",
  pinId: "",
  constraint: "",
});
const mousePosition = reactive({ x: 0, y: 0 });

// 加载状态
const isLoading = ref(false);

// 文件选择引用
const fileInput = ref<HTMLInputElement | null>(null);

// VueUse事件监听器状态管理
const isDragEventActive = ref(false);
const isComponentDragEventActive = ref(false);
const isWireCreationEventActive = ref(false);

// 使用VueUse设置事件监听器
// 画布拖拽事件
useEventListener(document, "mousemove", (e: MouseEvent) => {
  if (isDragEventActive.value) {
    onCanvasDrag(e);
  }
  if (isComponentDragEventActive.value) {
    onComponentDrag(e);
  }
  if (isWireCreationEventActive.value) {
    onCreatingWireMouseMove(e);
  }
});

useEventListener(document, "mouseup", () => {
  if (isDragEventActive.value) {
    stopDrag();
  }
  if (isComponentDragEventActive.value) {
    stopComponentDrag();
  }
});

// 键盘事件
useEventListener(window, "keydown", handleKeyDown);

// --- 缩放功能 ---
const MIN_SCALE = 0.2;
const MAX_SCALE = 10.0;

function onZoom(e: WheelEvent) {
  e.preventDefault();

  if (!canvasContainer.value) return;

  // 获取容器的位置
  const containerRect = canvasContainer.value.getBoundingClientRect();

  // 计算鼠标在容器内的相对位置
  const mouseX = e.clientX - containerRect.left;
  const mouseY = e.clientY - containerRect.top;

  // 计算缩放值
  const zoomFactor = 1.1; // 每次放大/缩小10%
  const direction = e.deltaY > 0 ? -1 : 1;
  const finalZoomFactor = direction > 0 ? zoomFactor : 1 / zoomFactor;

  // 使用componentManager的缩放方法
  componentManager?.zoomAtPosition(mouseX, mouseY, finalZoomFactor);
}

// --- 画布交互逻辑 ---
function handleCanvasMouseDown(e: MouseEvent) {
  // 如果是直接点击画布（而不是元器件），清除选中状态
  if (e.target === canvasContainer.value || e.target === canvas.value) {
    if (selectedComponentId.value !== null) {
      selectedComponentId.value = null;
      // 直接通过componentManager选择组件
      if (componentManager) {
        componentManager.selectComponent(null);
      }
    }
  }

  // 左键拖拽画布逻辑
  if (
    e.button === 0 &&
    (e.target === canvasContainer.value || e.target === canvas.value)
  ) {
    startDrag(e);
  }
}

// 左键拖拽画布
function startDrag(e: MouseEvent) {
  if (e.button !== 0 || draggingComponentId.value) return;

  isDragging.value = true;
  isMiddleDragging.value = false;
  const currentPosition = componentManager?.getCanvasPosition();
  if (!currentPosition) return;
  dragStart.x = e.clientX - currentPosition.x;
  dragStart.y = e.clientY - currentPosition.y;

  isDragEventActive.value = true;
  e.preventDefault();
}

// 中键拖拽画布
function startMiddleDrag(e: MouseEvent) {
  if (e.button !== 1) return;

  isMiddleDragging.value = true;
  isDragging.value = false;
  draggingComponentId.value = null;

  const currentPosition = componentManager?.getCanvasPosition();
  if (!currentPosition) return;
  dragStart.x = e.clientX - currentPosition.x;
  dragStart.y = e.clientY - currentPosition.y;

  isDragEventActive.value = true;
  e.preventDefault();
}

// 拖拽画布过程
function onCanvasDrag(e: MouseEvent) {
  if (!isDragging.value && !isMiddleDragging.value) return;

  const newX = e.clientX - dragStart.x;
  const newY = e.clientY - dragStart.y;

  // 使用componentManager设置画布位置
  componentManager?.setCanvasPosition(newX, newY);
}

// 停止拖拽画布
function stopDrag() {
  isDragging.value = false;
  isMiddleDragging.value = false;
  isDragEventActive.value = false;
}

// --- 组件拖拽交互 ---
function startComponentDrag(e: MouseEvent, component: DiagramPart) {
  const target = e.target as HTMLElement;

  // 检查点击的是否为交互元素 (如按钮、开关等)
  const isInteractiveElement =
    target.tagName === "rect" ||
    target.tagName === "circle" ||
    target.tagName === "path" ||
    target.hasAttribute("fill-opacity") ||
    (typeof target.className === "string" &&
      (target.className.includes("glow") ||
        target.className.includes("interactive")));

  // 仍然选中组件，无论是否为交互元素
  if (selectedComponentId.value !== component.id) {
    selectedComponentId.value = component.id;
    // 直接通过componentManager选择组件
    if (componentManager) {
      componentManager.selectComponent(component);
    }
  }

  // 如果组件锁定位置或是交互元素，则不启动拖拽
  if (component.positionlock || isInteractiveElement || e.button !== 0) {
    return;
  }

  // 阻止事件冒泡
  e.stopPropagation();

  console.debug(`Start Drag Component: ${component.type}:${component.id}`);

  // 设置拖拽状态
  draggingComponentId.value = component.id;
  isDragging.value = false;
  isMiddleDragging.value = false;

  // 获取容器位置
  if (!canvasContainer.value) return;
  const containerRect = canvasContainer.value.getBoundingClientRect();

  // 使用componentManager的屏幕坐标转画布坐标方法
  const mouseCanvasPos = componentManager?.screenToCanvas(
    e.clientX - containerRect.left,
    e.clientY - containerRect.top,
  );
  if (!mouseCanvasPos) return;

  // 计算鼠标相对于组件左上角的偏移量
  componentDragOffset.x = mouseCanvasPos.x - component.x;
  componentDragOffset.y = mouseCanvasPos.y - component.y;

  // 激活组件拖拽事件监听
  isComponentDragEventActive.value = true;
}

// 拖拽组件过程
function onComponentDrag(e: MouseEvent) {
  if (!draggingComponentId.value || !canvasContainer.value) return;

  // 防止触发组件内部的事件
  e.stopPropagation();
  e.preventDefault();

  const containerRect = canvasContainer.value.getBoundingClientRect();

  // 使用componentManager的屏幕坐标转画布坐标方法
  const mouseCanvasPos = componentManager?.screenToCanvas(
    e.clientX - containerRect.left,
    e.clientY - containerRect.top,
  );
  if (!mouseCanvasPos) return;

  // 计算组件新位置
  const newX = mouseCanvasPos.x - componentDragOffset.x;
  const newY = mouseCanvasPos.y - componentDragOffset.y;

  // 获取当前拖动的组件
  const draggedComponent = diagramParts.value.find(
    (p) => p.id === draggingComponentId.value,
  );
  if (!draggedComponent) return;

  // 如果组件属于组，移动组内所有其他组件
  if (draggedComponent.group) {
    const deltaX = Math.round(newX) - draggedComponent.x;
    const deltaY = Math.round(newY) - draggedComponent.y;

    // 找出属于同一组但不是当前拖动组件的其他组件
    const groupComponents = diagramParts.value.filter(
      (p) =>
        p.group === draggedComponent.group &&
        p.id !== draggingComponentId.value,
    );

    // 更新这些组件的位置
    for (const groupComp of groupComponents) {
      diagramData.value = updatePartPosition(
        diagramData.value,
        groupComp.id,
        groupComp.x + deltaX,
        groupComp.y + deltaY,
      );
    }
  }

  // 通知componentManager位置已更新
  if (componentManager) {
    componentManager.moveComponent({
      id: draggingComponentId.value,
      x: Math.round(newX),
      y: Math.round(newY),
    });
  }
}

// 停止拖拽组件
function stopComponentDrag() {
  // 如果有组件被拖拽，仅清除拖拽状态（不保存）
  if (draggingComponentId.value) {
    draggingComponentId.value = null;
  }

  isComponentDragEventActive.value = false;
  // 移除自动保存功能 - 不再自动保存到localStorage
}

// 更新组件属性
function updateComponentProp(
  componentId: string,
  propName: string,
  value: any,
) {
  // 直接通过componentManager更新组件属性
  if (componentManager) {
    componentManager.updateComponentProp(componentId, propName, value);
  } else {
    // 后备方案：直接更新数据
    diagramData.value = updatePartAttribute(
      diagramData.value,
      componentId,
      propName,
      value,
    );
  }
}

// --- 连线操作 ---
// 更新鼠标位置
function updateMousePosition(e: MouseEvent) {
  if (!canvasContainer.value) return;
  const containerRect = canvasContainer.value.getBoundingClientRect();

  // 使用componentManager的屏幕坐标转画布坐标方法
  const canvasPos = componentManager?.screenToCanvas(
    e.clientX - containerRect.left,
    e.clientY - containerRect.top,
  );
  if (!canvasPos) return;

  mousePosition.x = canvasPos.x;
  mousePosition.y = canvasPos.y;
}

// 处理引脚点击
function handlePinClick(componentId: string, pinInfo: any, event: MouseEvent) {
  if (!canvasContainer.value) return;
  updateMousePosition(event);

  if (!pinInfo || !pinInfo.label) {
    console.error("无效的针脚信息:", pinInfo);
    return;
  }

  // 获取引脚ID
  const pinId = pinInfo.label;

  console.log("----引脚点击详情开始----");
  console.log("组件ID:", componentId);
  console.log("引脚ID:", pinId);
  console.log("引脚原始信息:", pinInfo);
  console.log("鼠标位置:", mousePosition);

  if (!isCreatingWire.value) {
    // 获取初始位置信息
    let pinPosition = pinInfo.position;
    console.log("Pin信息:", pinInfo);
    console.log("Pin初始位置:", pinPosition);
    console.log("组件ID:", componentId);
    console.log("引脚ID:", pinId);

    // 从组件引用中获取组件实例
    const component = componentManager?.getComponentRef(componentId);
    console.log("组件引用:", component);

    // 查找组件部件对象以获取组件位置
    const componentPart = diagramParts.value.find((p) => p.id === componentId);
    if (!componentPart) {
      console.error("找不到组件部件对象:", componentId);
    }

    // 重新设置引脚位置（初始化）
    pinPosition = { x: 0, y: 0 };

    // 如果组件实例存在且有 getPinPosition 方法
    if (
      component &&
      typeof component.getPinPosition === "function" &&
      componentPart
    ) {
      try {
        console.log("尝试从组件获取引脚位置");
        console.log("组件部件位置:", componentPart.x, componentPart.y);
        const pinRelativePos = component.getPinPosition(pinId);
        console.log("组件返回的引脚相对位置:", pinRelativePos);

        if (pinRelativePos) {
          // 计算引脚的绝对位置 = 组件位置 + 引脚相对位置
          pinPosition = {
            x: componentPart.x + pinRelativePos.x,
            y: componentPart.y + pinRelativePos.y,
          };
          console.log("计算的引脚绝对位置:", pinPosition);
        } else {
          // 如果没有找到引脚位置，使用组件位置
          pinPosition = {
            x: componentPart.x,
            y: componentPart.y,
          };
          console.log("使用组件位置:", pinPosition);
        }
      } catch (error) {
        console.error(`获取引脚位置出错:`, error);
      }
    } else if (componentPart) {
      // 如果组件不存在或没有 getPinPosition 方法，使用组件的位置
      pinPosition = {
        x: componentPart.x,
        y: componentPart.y,
      };
      console.log("使用组件位置:", pinPosition);
    }

    console.log("最终使用的引脚位置:", pinPosition);

    // 使用最终的引脚位置作为连线起点
    setWireCreationStart(
      pinPosition.x,
      pinPosition.y,
      componentId,
      pinId,
      pinInfo.constraint,
    );
    isWireCreationEventActive.value = true;
  } else {
    // 完成连线创建
    if (
      componentId === creatingWireStartInfo.componentId &&
      pinId === creatingWireStartInfo.pinId
    ) {
      // 如果点击的是同一个引脚，取消连线创建
      cancelWireCreation();
      return;
    }

    // 获取终点引脚位置
    let endPosition = { x: 0, y: 0 };
    const componentPart = diagramParts.value.find((p) => p.id === componentId);
    const endComponent = componentManager?.getComponentRef(componentId);

    console.log("终点组件部件:", componentPart);
    console.log("终点组件引用:", endComponent);

    // 如果找到组件，设置终点位置
    if (componentPart) {
      endPosition.x = componentPart.x;
      endPosition.y = componentPart.y;

      // 如果组件实现了getPinPosition方法，使用它
      if (endComponent && typeof endComponent.getPinPosition === "function") {
        try {
          const pinPos = endComponent.getPinPosition(pinId);
          console.log("终点组件返回的引脚位置:", pinPos);

          if (pinPos) {
            // 正确合并组件位置与引脚相对位置
            endPosition = {
              x: componentPart.x + pinPos.x,
              y: componentPart.y + pinPos.x,
            };
            console.log("终点引脚位置(来自组件方法):", endPosition);
          }
        } catch (error) {
          console.error(`获取终点引脚位置出错:`, error);
        }
      } else {
        // 对于没有提供引脚精确位置的组件，使用组件位置
        console.log("终点组件没有提供引脚位置方法，使用组件位置");
      }
    } else {
      console.error("找不到终点组件部件对象:", componentId);
    }

    console.log("最终使用的终点位置:", endPosition);
    console.log("线路从", creatingWireStartInfo, "到", { componentId, pinId });
    console.log("----引脚点击详情结束----");

    // 创建新的连线
    const newConnection: ConnectionArray = [
      `${creatingWireStartInfo.componentId}:${creatingWireStartInfo.pinId}`,
      `${componentId}:${pinId}`,
      2, // 线宽
      ["right10", "*", "left10"], // 默认路径
    ];

    // 更新图表数据
    diagramData.value = {
      ...diagramData.value,
      connections: [...diagramData.value.connections, newConnection],
    };

    // 重置连线创建状态
    resetWireCreation();
    isWireCreationEventActive.value = false;
  }
}

// 开始创建连线
function setWireCreationStart(
  x: number,
  y: number,
  componentId: string,
  pinId: string,
  constraint?: string,
) {
  isCreatingWire.value = true;
  creatingWireStart.x = x;
  creatingWireStart.y = y;
  creatingWireStartInfo.componentId = componentId;
  creatingWireStartInfo.pinId = pinId;
  creatingWireStartInfo.constraint = constraint || "";
}

// 重置连线创建状态
function resetWireCreation() {
  isCreatingWire.value = false;
  creatingWireStart.x = 0;
  creatingWireStart.y = 0;
  creatingWireStartInfo.componentId = "";
  creatingWireStartInfo.pinId = "";
  creatingWireStartInfo.constraint = "";
}

// 取消连线创建
function cancelWireCreation() {
  resetWireCreation();
  isWireCreationEventActive.value = false;
}

// 连线创建过程中的鼠标移动
function onCreatingWireMouseMove(e: MouseEvent) {
  updateMousePosition(e);
}

// 删除组件
function deleteComponent(componentId: string) {
  // 直接通过componentManager删除组件
  if (componentManager) {
    componentManager.deleteComponent(componentId);
  }

  // 清除选中状态
  if (selectedComponentId.value === componentId) {
    selectedComponentId.value = null;
  }
}

// --- 文件操作功能 ---
// 打开文件选择器
function openDiagramFileSelector() {
  if (fileInput.value) {
    fileInput.value.click();
  }
}

// 处理文件选择
function handleFileSelected(event: Event) {
  const target = event.target as HTMLInputElement;
  const file = target.files?.[0];

  if (!file) {
    return;
  }

  // 设置加载状态
  isLoading.value = true;

  const reader = new FileReader();
  reader.onload = (e) => {
    try {
      // 检查组件是否仍然挂载
      if (!document.body.contains(canvasContainer.value)) {
        return; // 如果组件已经卸载，不执行后续操作
      }

      const content = e.target?.result as string;
      const parsed = JSON.parse(content);

      // 使用验证函数检查文件格式
      const validation = validateDiagramData(parsed);

      if (!validation.isValid) {
        alertStore?.show(
          `不是有效的diagram.json格式: ${validation.errors.join("; ")}`,
          "error",
        );
        isLoading.value = false;
        return;
      }

      // 更新画布数据
      diagramData.value = parsed as DiagramData;

      alertStore?.show(`成功导入diagram文件`, "success");
    } catch (error) {
      console.error("解析JSON文件出错:", error);
      if (document.body.contains(canvasContainer.value)) {
        alertStore?.show("解析文件出错，请确认是有效的JSON格式", "error");
      }
    } finally {
      // 检查组件是否仍然挂载
      if (document.body.contains(canvasContainer.value)) {
        // 结束加载状态
        isLoading.value = false;
      }

      // 清除文件输入，以便同一文件可以再次导入
      target.value = "";
    }
  };
  reader.onerror = () => {
    // 检查组件是否仍然挂载
    if (document.body.contains(canvasContainer.value)) {
      alertStore?.show("读取文件时出错", "error");
      isLoading.value = false;
    }
    // 清除文件输入
    target.value = "";
  };

  reader.readAsText(file);
}

// 导出当前diagram数据
function exportDiagram() {
  try {
    isLoading.value = true;

    // 创建一个Blob对象
    const jsonString = JSON.stringify(diagramData.value, null, 2);
    const blob = new Blob([jsonString], { type: "application/json" });

    // 创建一个下载链接
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "diagram.json";
    a.click();
    // 释放URL对象
    setTimeout(() => {
      URL.revokeObjectURL(url);
      // 检查组件是否仍然挂载
      if (document.body.contains(canvasContainer.value)) {
        isLoading.value = false;
        alertStore?.show("成功导出diagram文件", "success");
      }
    }, 100);
  } catch (error) {
    console.error("导出diagram文件时出错:", error);
    alertStore?.show("导出diagram文件时出错", "error");
    isLoading.value = false;
  }
}

// --- 生命周期钩子 ---
onMounted(async () => {
  // 加载图表数据
  try {
    // 传入examId参数，让diagramManager处理动态加载
    diagramData.value = await loadDiagramData(props.examId);

    // 预加载所有组件模块
    const componentTypes = new Set<string>();
    diagramData.value.parts.forEach((part) => {
      componentTypes.add(part.type);
    });

    console.log(
      "DiagramCanvas: Requesting component modules:",
      Array.from(componentTypes),
    );

    // 直接通过componentManager预加载组件模块
    if (componentManager) {
      await componentManager.preloadComponentModules(
        Array.from(componentTypes),
      );
    }
  } catch (error) {
    console.error("加载图表数据失败:", error);
  }

  // 初始化中心位置 - 使用componentManager设置
  if (canvasContainer.value && componentManager) {
    // 修改为将画布中心点放在容器中心点
    const centerX = canvasContainer.value.clientWidth / 2 - 5000; // 画布宽度的一半
    const centerY = canvasContainer.value.clientHeight / 2 - 5000; // 画布高度的一半
    componentManager.setCanvasPosition(centerX, centerY);
  }
});

// 处理键盘事件
function handleKeyDown(e: KeyboardEvent) {
  // 如果当前有选中的组件，并且按下了Delete键
  if (selectedComponentId.value && e.key === "Delete") {
    // 触发删除组件事件
    deleteComponent(selectedComponentId.value);
  }

  // 如果当前正在创建连线，并且按下了ESC键
  if (isCreatingWire.value && e.key === "Escape") {
    // 取消连线创建
    cancelWireCreation();
  }
}

// 无加载动画的数据更新方法
function updateDiagramDataDirectly(data: DiagramData) {
  // 检查组件是否仍然挂载
  if (!document.body.contains(canvasContainer.value)) {
    return; // 如果组件已经卸载，不执行后续操作
  }

  diagramData.value = data;
}

// 暴露方法给父组件
defineExpose({
  // 基本数据操作
  getDiagramData: () => diagramData.value,
  updateDiagramDataDirectly,
});
</script>

<style scoped>
/* 基础容器样式 - 使用 Tailwind 类替代 */
.diagram-container {
  background-size:
    20px 20px,
    20px 20px,
    100px 100px,
    100px 100px;
  background-position: 0 0;
}

/* 画布样式 - 部分保留自定义属性 */
.diagram-canvas {
  width: 10000px;
  height: 10000px;
  transform-origin: 0 0;
}

/* 连线层样式 */
.wires-layer {
  pointer-events: auto;
  overflow: visible;
}

.wires-layer path {
  pointer-events: stroke;
  cursor: pointer;
}

/* 组件容器样式 */
.component-wrapper {
  box-sizing: content-box;
  cursor: move;
}

/* 悬停状态 */
.component-hover {
  outline: 2px dashed #3498db;
  outline-offset: 2px;
}

/* 选中状态 */
.component-selected {
  outline: 3px dashed;
  outline-color: #e74c3c #f39c12 #3498db #2ecc71;
  outline-offset: 3px;
}

/* SVG 交互样式 */
.component-wrapper :deep(svg) {
  pointer-events: auto;
}

.component-wrapper
  :deep(
    svg
      *:not([class*="interactive"]):not(rect.glow):not(
        circle[fill-opacity]
      ):not([fill-opacity])
  ) {
  pointer-events: none;
}

.component-wrapper :deep(svg circle[fill-opacity]),
.component-wrapper :deep(svg rect[fill-opacity]),
.component-wrapper :deep(svg rect[class*="glow"]),
.component-wrapper :deep(svg rect.glow),
.component-wrapper :deep(svg [class*="interactive"]),
.component-wrapper :deep(button),
.component-wrapper :deep(input) {
  pointer-events: auto !important;
}

.wire-active {
  stroke: #0099ff !important;
  filter: drop-shadow(0 0 4px #0099ffcc);
}
</style>
