<template>
  <splitpanes class="default-theme">
    <pane min-size="50" size="100" max-size="100">
              <!-- :nodes-draggable="isSelectMode"
        :nodes-connectable="isSelectMode ? false : true" -->
      <VueFlow
        ref="vueFlowRef"
        v-model:nodes="nodes"
        v-model:edges="edges"
        :class="{ dark }"
        class="basic-flow"
        :default-viewport="{ zoom: 1.5 }"
        :min-zoom="0.2"
        :max-zoom="2.5"
        :multi-selection-key-code="'Control'" 
        :selection-key-code="'Shift'"
        :nodes-draggable="!props.isSelectMode"
        :nodes-connectable="props.isSelectMode ? false : true"
        @drop="customOnDrop"
        @node-contextmenu="onNodeContextMenu"
        @dragover="onDragOver"
        @dragleave="onDragLeave"
        @edge-click="onEdgeClick"
        @node-double-click="onNodeDoubleClick"
        @node-click="onNodeClick"
        @edge-double-click="onEdgeDoubleClick"
        @node-drag="onNodeDrag"
        @nodes-selection-change="onNodesSelectionChange"
        @edges-selection-change="onEdgesSelectionChange"
      >
        <!-- 自定义节点类型为default的节点 -->
        <template #node-default="props">
          <defaultnode :node="props" :key="props.data.idCodeser || props.id" />
        </template>

        <template #node-point-only="props">
          <PointOnlyNode
            :node="props"
            :key="props.data.idCodeser || props.id"
          />
        </template>

        <Background
          :variant="showGrid ? 'dots' : 'none'"
          pattern-color="#aaa" 
          :gap="20" 
        />
      </VueFlow>
    </pane>
    <pane
      v-if="showPanel"
      min-size="20"
      :size="30"
      max-size="50"
      class="flow-panel"
    >
      <asideData ref="asideDataref" @close="closePanel" />
    </pane>
  </splitpanes>
</template>

<script setup>
import { VueFlow, useVueFlow, MarkerType } from "@vue-flow/core"
import {
  ElMessage,
  ElMessageBox
} from "element-plus"
import { DeleteFilled } from "@element-plus/icons-vue"
import { onBeforeRouteLeave } from "vue-router"
import { request, uploadFile, getImageBase64 } from "@/utils/request"
import { Background } from "@vue-flow/background"
import "./main.css" //重置样式
import defaultnode from "./defaultnode.vue"
import PointOnlyNode from "./pointonlynode.vue"
import useDragAndDrop from "./useDnD"
import { useProjectStore } from "@/store/project"
import { useClipboardStore } from '@/store/clipboard'
import emitter from "@/utils/emitter"
import { onMounted, onUnmounted, onBeforeUnmount, nextTick } from "vue"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
import asideData from "./aside/asideData.vue"
import { copyNodes, cutNodes, pasteNodes  } from "./utils/clipboardUtils";
import node from "@/assets/img/node.png"
import nodePoint from "@/assets/img/node.png"
import tempic from "@/assets/img/temp.png"

import { debounce } from 'lodash-es'

// 常量定义
const GRID_SIZE = 10
const DEBOUNCE_DELAY = 1000
const DEFAULT_LINE_COLOR = "#2267B1"
const DEFAULT_LINE_WIDTH = 1

// 定义一个新的 ref 用于存储边的选择状态
const edgeSelectionState = ref({}); // 格式: { [edgeId]: { class: string, style: object } }

// 获取路由实例
const router = useRouter()

const {
  onInit,
  onNodeDragStop,
  onConnect,
  addEdges,
  setViewport,
  toObject,
  addNodes,
  updateEdgeData,
  onConnectStart,
  updateNode,
  updateNodeInternals,
  onNodeDrag,
  snapToGrid,
  snapGrid,
  setInteractive,
  removeNodes,
  removeEdges,
  selectedNodes: vueFlowSelectedNodes,
  selectedEdges: vueFlowSelectedEdges,
} = useVueFlow()
const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop()

const dark = ref(false)
const vueFlowRef = ref()
const iconcolor = ref("#000")
const edges = ref([])
const nodes = ref([])
const mergedObj = ref("")
const selectedNodes = ref([]); // 选中节点
const selectedEdges = ref([]); // 选中边

// 选中状态
const selectedNode = ref(null)
const selectedEdge = ref(null)
const previousEdge = ref(null)
const lineColor = ref(DEFAULT_LINE_COLOR)
const lineWidth = ref(DEFAULT_LINE_WIDTH)
const midNodeCounter = 0

const projectStore = useProjectStore()
const clipboardStore = useClipboardStore();
const pid = computed(() => projectStore.pid || "")

// 删除组件和边的列表
const pendingDelete = ref({ nodes: [], edges: [] });
const isCutting = ref(false);

const showPanel = ref(false)
const asideDataref = ref()

const props = defineProps({
  jobId: { type: String, default: "" },
  showGrid: { type: Boolean, default: false },
  fixedGrid: { type: Boolean, default: false },
  isSelectMode: { type: Boolean, default: true }
})

// 保存项目
const saveproject = async () => {
  try {
    const activeProject = projectStore.getActiveProject();
    if (!activeProject) {
      throw new Error("当前没有激活的项目");
    }

    const obj = {
      nodes: toObject().nodes.map((node) => ({
        ...node,
        data: { ...node.data, image: undefined },
      })),
      edges: toObject().edges,
    };

    mergedObj.value = JSON.stringify(obj);

    const params = {
      transCode: "ES0002",
      pid: pid.value,
      flow: mergedObj.value,
      name: activeProject.projectName || "",
      remark: activeProject.remark || "",
      keywords: activeProject.keywords || "",
    };

    // 保存前处理待删除的组件和边
    for (const { pcId } of pendingDelete.value.nodes) {
      await comdelete(pcId);
    }
    for (const { npcId, pcId } of pendingDelete.value.edges) {
      await comlinedelete(npcId, pcId);
    }
    pendingDelete.value = { nodes: [], edges: [] }; // 清空待删除列表

    await request(params);

    projectStore.updateProjectInfo(projectStore.activeProjectId, {
      ...activeProject,
      flow: mergedObj.value,
    });

    ElMessage.success("保存成功");
  } catch (error) {
    console.error("保存失败:", error);
    ElMessage.error("保存失败，请稍后重试");
  }
};

const debouncedSave = debounce(saveproject, DEBOUNCE_DELAY)

let prevNodes = []
let prevEdges = []
let isInitializing = ref(true)

// 合并的 watch：监听节点和边变化
watch(
  [nodes, edges],
  ([newNodes, newEdges]) => {
    if (isInitializing.value) {
      prevNodes = [...newNodes];
      prevEdges = [...newEdges];
      isInitializing.value = false;
      return;
    }

    if (isCutting.value) {
      // 剪切时不触发保存，仅记录删除
      const deletedNodes = prevNodes.filter((n) => !newNodes.some((nn) => nn.id === n.id));
      if (deletedNodes.length > 0) {
        pendingDelete.value.nodes.push(...deletedNodes.map((node) => ({ pcId: node.data.pcId })));
      }

      const deletedEdges = prevEdges.filter((e) => !newEdges.some((ne) => ne.id === e.id));
      if (deletedEdges.length > 0) {
        deletedEdges.forEach((edge) => {
          const sourceNode = prevNodes.find((n) => n.id === edge.source);
          const targetNode = prevNodes.find((n) => n.id === edge.target);
          if (!sourceNode || !targetNode) return;

          let npcId = "",
            pcId = "";
          if (sourceNode.data?.comId === "3") {
            npcId = sourceNode.data.pcId;
            pcId = targetNode.data?.pcId;
          } else if (targetNode.data?.comId === "3") {
            npcId = targetNode.data.pcId;
            pcId = sourceNode.data?.pcId;
          }

          if (npcId && pcId) {
            pendingDelete.value.edges.push({ npcId, pcId });
          }
        });
      }

      prevNodes = [...newNodes];
      prevEdges = [...newEdges];
      debouncedSave.cancel();
      return; // 阻止 debouncedSave
    }

    // 其他操作（如添加、删除）触发保存
    const deletedNodes = prevNodes.filter((n) => !newNodes.some((nn) => nn.id === n.id));
    if (deletedNodes.length > 0) {
      pendingDelete.value.nodes.push(...deletedNodes.map((node) => ({ pcId: node.data.pcId })));
    }

    const deletedEdges = prevEdges.filter((e) => !newEdges.some((ne) => ne.id === e.id));
    if (deletedEdges.length > 0) {
      deletedEdges.forEach((edge) => {
        const sourceNode = prevNodes.find((n) => n.id === edge.source);
        const targetNode = prevNodes.find((n) => n.id === edge.target);
        if (!sourceNode || !targetNode) return;

        let npcId = "",
          pcId = "";
        if (sourceNode.data?.comId === "3") {
          npcId = sourceNode.data.pcId;
          pcId = targetNode.data?.pcId;
        } else if (targetNode.data?.comId === "3") {
          npcId = targetNode.data.pcId;
          pcId = sourceNode.data?.pcId;
        }

        if (npcId && pcId) {
          pendingDelete.value.edges.push({ npcId, pcId });
        }
      });
    }

    prevNodes = [...newNodes];
    prevEdges = [...newEdges];
    debouncedSave();
  },
  { deep: false }
);

// 网格固定
watch(
  () => props.fixedGrid,
  (newValue) => {
    snapToGrid.value = newValue
    snapGrid.value = newValue ? [GRID_SIZE, GRID_SIZE] : [1, 1] // 禁用吸附时用 [1, 1]
  },
  { immediate: true }
)

onMounted(() => {
  flowInit()
  // 点击画布取消边选中
  if (vueFlowRef.value) {
    vueFlowRef.value.$el.addEventListener("click", (event) => {
      if (selectedEdge.value && !event.target.closest(".vue-flow__edge")) {
        cleanEdgeSelect();
        selectedNodes.value = [];
        selectedEdges.value = [];
      }
    })
  }
  console.log('Binding keydown event listener');
  window.addEventListener('keydown', handleKeyDown)
  window.addEventListener('beforeunload', handleBeforeUnload) // 绑定页面关闭事件
})

onBeforeUnmount(() =>{
  saveproject();
  
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
  window.removeEventListener('beforeunload', handleBeforeUnload) // 移除页面关闭事件
})

// 在路由切换前保存
onBeforeRouteLeave((to, from, next) => {
  console.log('onBeforeRouteLeave triggered, saving project')
  debouncedSave.flush() // 立即执行任何待保存的操作
  saveproject().then(() => {
    console.log('Save completed before route leave')
    next()
  }).catch((error) => {
    console.error('Save failed before route leave:', error)
    ElMessage.error('保存失败，请检查网络后重试')
    next() // 即使保存失败，也允许路由切换
  })
})

const handleBeforeUnload = (event) => {
  console.log('beforeunload triggered, saving project')
  debouncedSave.flush() // 立即执行待保存操作
  // 注意：beforeunload 中无法等待异步 saveproject 完成
  event.preventDefault()
  event.returnValue = '项目尚未保存，确定要离开吗？' // 提示用户
}

// 新增：监听节点选择变化（包括 Ctrl+点击和框选）
const onNodesSelectionChange = (event) => {
  selectedNodes.value = Array.from(vueFlowSelectedNodes.value);
};

// 新增：监听边选择变化
const onEdgesSelectionChange = (event) => {
  selectedEdges.value = Array.from(vueFlowSelectedEdges.value);
};

// 网格吸附逻辑
onNodeDrag(({ node }) => {
  if (!props.fixedGrid || node.type !== 'point-only') return
  // 仅对 point-only 节点禁用吸附效果
  const newPosition = {
    x: node.position.x, // 保留原始位置
    y: node.position.y,
  }
  updateNode(node.id, { position: newPosition })
})

// 键盘事件：Backspace 删除选中节点
const handleKeyDown = (event) => {
  if (event.ctrlKey) {
    if (event.key === 'c') {
      event.preventDefault(); // 阻止默认行为
      event.stopPropagation(); // 阻止事件冒泡
      copyNodes(selectedNodes.value, selectedEdges.value, edges.value, nodes.value, pid.value);
    } else if (event.key === 'x') {
      event.preventDefault(); // 阻止默认行为
      event.stopPropagation(); // 阻止事件冒泡
      isCutting.value = true;
      cutNodes(selectedNodes.value, selectedEdges.value, nodes.value, edges.value, saveproject, removeNodes, removeEdges, clearSelection )
      .finally(() => {
        isCutting.value = false; // 重置标志
      });
    } else if (event.key === 'v') {
      event.preventDefault(); // 阻止默认行为
      event.stopPropagation(); // 阻止事件冒泡
      pasteNodes(pid.value, nodes.value, edges.value, saveproject, createEdge, addNodes, addEdges, updateNodeInternals);
    }
  } else if (event.key === 'Backspace' && selectedNodes.value.length > 0) {
    event.preventDefault(); // 阻止默认行为
    event.stopPropagation(); // 阻止事件冒泡
    removeNodes(selectedNodes.value.map((n) => n.id));
    selectedNodes.value = [];
  }
};

const clearSelection = () => {
  selectedNodes.value = [];
  selectedEdges.value = [];
};


const resetTransform = () => {
  setViewport({ x: 0, y: 0, zoom: 1 })
}

const toggleDarkMode = () => {
  dark.value = !dark.value
  iconcolor.value = dark.value ? "#fff" : "#000"
}



const removeNode = () => {
  if (!selectedNode.value) {
    ElMessage.warning("未选中任何节点")
    return
  }

  vueFlowRef.value.removeNodes(selectedNode.value.id)
  selectedNode.value = null
  debouncedSave();
}

const removeEdge = () => {
  if (!selectedEdge.value) {
    ElMessage.warning("请先选择要删除的连线")
    return
  }

  vueFlowRef.value.removeEdges(selectedEdge.value.id)
  selectedEdge.value = null
  debouncedSave();
}

const confirmDelete = () => {
  ElMessageBox.confirm("确定要删除所有节点和连线吗？此操作不可恢复！", "警告", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(() => {
      vueFlowRef.value.removeNodes(nodes.value)
      vueFlowRef.value.removeEdges(edges.value)
      ElMessage.success("所有节点和连线已删除")
      debouncedSave();
    })
    .catch(() => {
      ElMessage.info("已取消删除")
    })
}

const comdelete = async (pcId) => {
  try {
    const params = { transCode: "ES0005", pcId }
    await request(params)
  } catch (err) {
    ElMessage.error(err.returnMsg || "组件删除失败")
  }
}

const comlinedelete = async (npcId, pcId) => {
  try {
    const params = { transCode: "ES0007", npcId, pcId, type: 0 }
    await request(params)
  } catch (err) {
    ElMessage.error(err.returnMsg || "连线删除失败")
  }
}

const customOnDrop = async (event) => {
  await onDrop(event)
  debouncedSave();
}

const onNodeContextMenu = (e) => {
  console.log("右键点击", e)
}

const getChainFromEdge = (edge) => {
  const chainNodes = new Set(); // 用 Set 避免重复
  const chainEdges = new Set(); // 用 Set 避免重复

  // 添加当前边
  chainEdges.add(edge);

  // 获取源和目标节点
  let currentSource = vueFlowRef.value.getNode(edge.source);
  let currentTarget = vueFlowRef.value.getNode(edge.target);

  chainNodes.add(currentSource);
  chainNodes.add(currentTarget);

  // 如果源是中间节点，向前扩展（找出源的输入边）
  if (currentSource.data?.comId === '3') {
    const inputEdges = edges.value.filter(e => e.target === currentSource.id);
    inputEdges.forEach(inputEdge => {
      chainEdges.add(inputEdge);
      const prevNode = vueFlowRef.value.getNode(inputEdge.source);
      chainNodes.add(prevNode);
    });
  }

  // 如果目标是中间节点，向后扩展（找出目标的输出边）
  if (currentTarget.data?.comId === '3') {
    const outputEdges = edges.value.filter(e => e.source === currentTarget.id);
    outputEdges.forEach(outputEdge => {
      chainEdges.add(outputEdge);
      const nextNode = vueFlowRef.value.getNode(outputEdge.target);
      chainNodes.add(nextNode);
    });
  }

  // 如果链条两端不是大节点，继续递归扩展（但假设单中间节点，此处简化）
  // 如果有多个中间节点，可递归调用 getChainFromEdge 于新边

  return {
    nodes: Array.from(chainNodes),
    edges: Array.from(chainEdges)
  };
};

// 边点击事件
const onEdgeClick = (e) => {
  // 恢复上一个选中边样式（原有逻辑）
  if (previousEdge.value) {
    edges.value = edges.value.map(edge => {
      if (edge.id === previousEdge.value.id) {
        return {
          ...edge,
          class: edge.class ? edge.class.replace("selected", "").trim() : "",
          style: {
            ...edge.style,
            stroke: previousEdge.value.originalColor || DEFAULT_LINE_COLOR,
            strokeWidth: previousEdge.value.originalWidth || DEFAULT_LINE_WIDTH
          }
        };
      }
      return edge;
    });
  }

  // 设置当前选中边（原有逻辑）
  selectedEdge.value = { ...e.edge };
  selectedEdge.value.originalColor = e.edge.style?.stroke || DEFAULT_LINE_COLOR;
  selectedEdge.value.originalWidth = e.edge.style?.strokeWidth || DEFAULT_LINE_WIDTH;

  // 更新 selectedEdges.value（原有逻辑，支持 Ctrl 多选）
  if (e.event.ctrlKey) {
    const index = selectedEdges.value.findIndex((edge) => edge.id === e.edge.id);
    if (index === -1) {
      selectedEdges.value.push(e.edge);
    } else {
      selectedEdges.value.splice(index, 1); // 取消选择
    }
  } else {
    selectedEdges.value = [e.edge];
    selectedNodes.value = []; // 清空节点选择
  }

  // 新增：获取完整链条，并自动更新 selectedNodes 和 selectedEdges
  const chain = getChainFromEdge(e.edge);
  selectedNodes.value = chain.nodes; // 自动选中相关节点
  selectedEdges.value = [...selectedEdges.value, ...chain.edges.filter(ce => ce.id !== e.edge.id)]; // 添加其他相关边

  ElMessage.success('已自动选中边的相关节点、边和链条');

  // 可选：如果需要立即保存项目
  // saveproject();

  // 更新边样式（原有逻辑，稍作调整以支持多边选中）
  selectedEdges.value.forEach(selEdge => {
    const isDefault = selEdge.data?.type === "default";
    const newStyle = {
      ...selEdge.style,
      stroke: isDefault ? "#2267B1" : "rgba(255, 255, 0, 0.3)",
      strokeWidth: isDefault ? 2 : 6
    };

    edges.value = edges.value.map(edge => {
      if (edge.id === selEdge.id) {
        return {
          ...edge,
          class: edge.class ? `${edge.class} selected` : "selected",
          style: newStyle
        };
      }
      return edge;
    });
  });

  previousEdge.value = { ...selectedEdge.value, style: { ...selectedEdge.value.style } };
};

// 点击节点
const onNodeClick = (event) => {

  if (event.event.ctrlKey) {
    // 支持多选节点
    const index = selectedNodes.value.findIndex((n) => n.id === event.node.id);
    if (index === -1) {
      selectedNodes.value.push(event.node);
    } else {
      selectedNodes.value.splice(index, 1); // 取消选择
    }
  } else {
    // 单选节点，清空边选择
    selectedNodes.value = [event.node];
    selectedEdges.value = [];
  }
};

const onNodeDoubleClick = (event) => {
  showPanel.value = true
  const pcId = event.node.data.pcId
  nextTick(() => {
    if (asideDataref.value) {
      asideDataref.value.getcomdata(pcId)
      if (props.jobId) {
        asideDataref.value.getresultData(props.jobId)
      }
    }
  })
}

const onEdgeDoubleClick = (event) => {
  selectedNode.value = event.node
}

// 连接开始：取消边选中
onConnectStart(() => cleanEdgeSelect())

// 方向计算工具函数
const getDirectionFromPoint = (point) => {
  if (!isNaN(parseInt(point))) {
    const angle = ((parseInt(point) * 30) % 360 + 360) % 360
    if (angle >= 315 || angle < 45) return "right"
    if (angle >= 45 && angle < 135) return "bottom"
    if (angle >= 135 && angle < 225) return "left"
    if (angle >= 225 && angle < 315) return "top"
  }
  return point
}

const getOppositeDirection = (point) => {
  if (!isNaN(parseInt(point))) {
    const oppositePoint = (parseInt(point) + 6) % 12
    return getDirectionFromPoint(oppositePoint.toString())
  }
  return point === "top" ? "bottom" :
         point === "bottom" ? "top" :
         point === "left" ? "right" :
         point === "right" ? "left" : point
}

// 连接验证工具函数
const validateConnection = (connection, sourceNode, targetNode) => {
  if (connection.source === connection.target) {
    ElMessage.warning("禁止节点自连")
    return false
  }
  if (sourceNode.data.comId === "3" && targetNode.data.comId === "3") {
    ElMessage.warning("禁止连接两个中间节点")
    return false
  }
  const hasDuplicate = edges.value.some(edge =>
    (edge.source === connection.source && edge.target === connection.target) ||
    (edge.source === connection.target && edge.target === connection.source)
  )
  if (hasDuplicate) {
    ElMessage.warning("禁止重复连接：起点和终点已连接")
    return false
  }
  const isDuplicateViaMiddle = edges.value.some(edge1 => {
    if (edge1.source === connection.source || edge1.target === connection.source) {
      const middleId = edge1.source === connection.source ? edge1.target : edge1.source
      const middleNode = vueFlowRef.value.getNode(middleId)
      if (!middleNode || middleNode.data.comId !== "3") return false
      return edges.value.some(edge2 =>
        (edge2.source === middleId && edge2.target === connection.target) ||
        (edge2.target === middleId && edge2.source === connection.target)
      )
    }
    return false
  })
  if (isDuplicateViaMiddle) {
    ElMessage.warning("禁止重复连接：这两个节点已经通过中间组件连接过了")
    return false
  }
  return true
}

const lineType = ref("default")

onConnect(async (connection) => {
  const sourceNode = vueFlowRef.value.getNode(connection.source)
  const targetNode = vueFlowRef.value.getNode(connection.target)
  if (!validateConnection(connection, sourceNode, targetNode)) return

  const isCom3 = sourceNode.data.comId === "3" || targetNode.data.comId === "3"

  if (isCom3) {
    await handleDirectConnection(connection, sourceNode, targetNode)
  } else {
    await handleIndirectConnection(connection, sourceNode, targetNode)
  }

  debouncedSave();
})

const handleDirectConnection = async (connection, sourceNode, targetNode) => {
  const edgeId = `${lineType.value}-${connection.source}-${connection.sourceHandle}-${connection.target}-${connection.targetHandle}`
  connection.id = edgeId
  connection.type = "smoothstep"
  connection.color = lineColor.value
  connection.style = { strokeWidth: lineWidth.value, stroke: lineColor.value }

  const sameEdge = edges.value.find(e => e.id === edgeId)
  if (sameEdge) {
    await deleteflow(sameEdge.data?.wid)
  }

  addEdges(connection)
  selectedEdge.value = null

  const pcId1 = sourceNode.data.comId === "3" ? targetNode.data.pcId : sourceNode.data.pcId
  const npcId = sourceNode.data.comId === "3" ? sourceNode.data.pcId : targetNode.data.pcId

  try {
    const { pccId1 } = await createEdge(pid.value, 0, npcId, pcId1)
    updateEdgeData(connection.id, {
      pcid: pccId1,
      type: lineType.value,
      frompcId: sourceNode.data.pcId,
      topcId: targetNode.data.pcId
    })
  } catch (error) {
    console.error("保存流程失败:", error)
  }
}

const handleIndirectConnection = async (connection, sourceNode, targetNode) => {
  const pointNodeId = `point-${connection.source}-${connection.target}`
  const sourceCenterX = sourceNode.position.x + 60 / 2
  const sourceCenterY = sourceNode.position.y + 58 / 2
  const targetCenterX = targetNode.position.x + 60 / 2
  const targetCenterY = targetNode.position.y + 58 / 2

  const midX = (sourceCenterX + targetCenterX) / 2
  const midY = (sourceCenterY + targetCenterY) / 2

  const dxSource = sourceNode.position.x - midX
  const dySource = sourceNode.position.y - midY
  const dxTarget = targetNode.position.x - midX
  const dyTarget = targetNode.position.y - midY

  const isSourceHorizontal = Math.abs(dxSource) > Math.abs(dySource)
  const sourceDirection = isSourceHorizontal
    ? dxSource < 0 ? "left" : "right"
    : dySource < 0 ? "top" : "bottom"

  const isTargetHorizontal = Math.abs(dxTarget) > Math.abs(dyTarget)
  const targetDirection = isTargetHorizontal
    ? dxTarget < 0 ? "left" : "right"
    : dyTarget < 0 ? "top" : "bottom"

  // 添加 point-only 节点
  nodes.value.push({
    id: pointNodeId,
    type: "point-only",
    position: { x: midX, y: midY },
    data: {
      comId: "3",
      label: "节点",
      image: node,
      imageIdentify: "point-only"
    }
  })

  try {
    const { pcId: npcId, ser, idCode } = await createCom3(pid.value)
    updateNode(pointNodeId, node => ({
      ...node,
      data: {
        ...node.data,
        pcId: npcId,
        idCodeser: `${idCode}${ser}`
      }
    }))
    updateNodeInternals(pointNodeId)

    // edge1: source -> pointNode
    const edgeId1 = `${lineType.value}-${connection.source}-${connection.sourceHandle}-${pointNodeId}`
    const edge1 = {
      id: edgeId1,
      source: connection.source,
      sourceHandle: connection.sourceHandle,
      target: pointNodeId,
      targetHandle: `source-${sourceDirection}`,
      type: "smoothstep",
      color: lineColor.value,
      style: { strokeWidth: lineWidth.value, stroke: lineColor.value }
    }

    // edge2: pointNode -> target
    const edgeId2 = `${lineType.value}-${pointNodeId}-${connection.targetHandle}-${connection.target}`
    const edge2 = {
      id: edgeId2,
      source: pointNodeId,
      sourceHandle: `source-${targetDirection}`,
      target: connection.target,
      targetHandle: connection.targetHandle,
      type: "smoothstep",
      color: lineColor.value,
      style: { strokeWidth: lineWidth.value, stroke: lineColor.value }
    }

    addEdges([edge1, edge2])

    const { pccId1, pccId2 } = await createEdge(pid.value, 0, npcId, sourceNode.data.pcId, targetNode.data.pcId)

    updateEdgeData(edgeId1, {
      pcid: pccId1,
      type: lineType.value,
      frompcId: sourceNode.data.pcId,
      topcId: npcId
    })

    updateEdgeData(edgeId2, {
      pcid: pccId2,
      type: lineType.value,
      frompcId: npcId,
      topcId: targetNode.data.pcId
    })
  } catch (err) {
    console.error("中间点处理失败:", err)
    // 回滚：移除添加的节点
    nodes.value = nodes.value.filter(n => n.id !== pointNodeId)
  }
}

const createEdge = async (pid, type, npcId, pcId1, pcId2 = "") => {
  const params = {
    transCode: "ES0006",
    pid: pid || "",
    type: type || 0,
    npcId: npcId || "",
    pcId1: pcId1 || "",
    pcId2: pcId2 || ""
  }

  try {
    const res = await request(params)
    return { pccId1: res.pccId1, pccId2: res.pccId2 }
  } catch (err) {
    ElMessage.error(err.returnMsg || "保存流程失败")
    throw err
  }
}

const createCom3 = async (pid) => {
  try {
    const params = { transCode: "ES0004", pid: pid || "", comId: "3" }
    const res = await request(params)
    return { pcId: res.pcId, ser: res.ser, idCode: res.idCode }
  } catch (err) {
    ElMessage.error(err.returnMsg || "创建中间组件失败")
    throw err
  }
}

const flowInit = async () => {
  try {
    const activeProject = projectStore.getActiveProject()
    if (!activeProject) {
      throw new Error('当前没有激活的项目')
    }

    let flow
    // 检查 activeProject.flow 的类型
    if (typeof activeProject.flow === 'string') {
      // 如果是字符串，尝试解析
      try {
        flow = JSON.parse(activeProject.flow || '{"nodes":[], "edges":[] }')
      } catch (error) {
        console.error('解析 flow 数据失败:', activeProject.flow, error)
        flow = { nodes: [], edges: [] }
      }
    } else if (typeof activeProject.flow === 'object' && activeProject.flow !== null) {
      // 如果已经是对象，直接使用
      flow = activeProject.flow
    } else {
      // 其他情况使用默认值
      flow = { nodes: [], edges: [] }
    }

    const updatedNodes = await Promise.all(
      flow.nodes.map(async (node) => {
        if (node.data?.imageIdentify) {
          if (node.data.imageIdentify === 'point-only') {
            return { ...node, data: { ...node.data, image: nodePoint } }
          }
          try {
            const imageData = await getImageBase64(node.data.imageIdentify)
            return { ...node, data: { ...node.data, image: imageData || tempic } }
          } catch (err) {
            console.error(`获取图片 ${node.data.imageIdentify} 失败:`, err.message)
            return { ...node, data: { ...node.data, image: tempic } }
          }
        }
        return node
      })
    )

    nodes.value = updatedNodes
    edges.value = flow.edges
    prevNodes = [...updatedNodes]
    prevEdges = [...flow.edges]
    isInitializing.value = true
  } catch (error) {
    console.error('加载项目失败:', error)
    ElMessage.error('加载项目失败，请检查项目数据')
  }
}

const cleanEdgeSelect = () => {
  if (selectedEdge.value) {
    edges.value = edges.value.map(edge => {
      if (edge.id === selectedEdge.value.id) {
        return {
          ...edge,
          class: edge.class ? edge.class.replace("selected", "").trim() : "",
          style: {
            ...edge.style,
            stroke: selectedEdge.value.originalColor || DEFAULT_LINE_COLOR,
            strokeWidth: selectedEdge.value.originalWidth || DEFAULT_LINE_WIDTH
          }
        };
      }
      return edge;
    });
    selectedEdge.value = null;
    previousEdge.value = null;
  }
};

const closePanel = () => {
  nextTick(() => {
    showPanel.value = false
  })
}

// 暴露方法
defineExpose({
  resetTransform,
  toggleDarkMode,
  saveproject,
  removeNode,
  removeEdge,
  confirmDelete,
  asideDataref,
  copyNodes: () => copyNodes(selectedNodes.value, selectedEdges.value, edges.value, nodes.value, pid.value),
  cutNodes: () => cutNodes(selectedNodes.value, selectedEdges.value, nodes.value, edges.value, saveproject, removeNodes, removeEdges, clearSelection)
    .finally(() => {
      isCutting.value = false;
    }),
  pasteNodes: () => pasteNodes(pid.value, nodes.value, edges.value, saveproject, createEdge, addNodes, addEdges, updateNodeInternals),
  flowInit,
  refreshFlow: flowInit
})
</script>

<style scoped>
.vue-flow__edge:focus .vue-flow__edge-path,
.vue-flow__edge:focus-visible .vue-flow__edge-path {
  stroke: #555 !important;
}
.vue-flow__edge {
  text-align: left;
}

.vue-flow__edge-text {
  transform: translateY(-10px);
  background: transparent !important;
  font-size: 8px;
  font-family: "Microsoft YaHei";
  color: #333333;
}

.vue-flow__edge-textbg {
  fill: transparent !important;
}

.vue-flow__node-default.selectable:hover,
.vue-flow__node-input.selectable:hover,
.vue-flow__node-output.selectable:hover {
  box-shadow: none;
}

.remove {
  background: #fff;
  color: #666;
  margin: 0 10px;
  font-size: 12px;
}
.vue-flow__node-default,
.vue-flow__node-input,
.vue-flow__node-output {
  border: none;
  background-color: rgba(0, 0, 0, 0);
}
.node-content {
  cursor: move;
}
.vue-flow__node {
  cursor: move;
}

/* 禁用文本选中效果 */
.left_main * {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
.lableaniu {
  font-size: 12px;
  background-color: #ddd;
  padding: 4px 16px;
  margin-left: 5px;
  margin-top: 0px;
  border-radius: 1px;
}
.vue-flow__controls-button svg {
  max-width: 16px;
  max-height: 16px;
}
.field {
  display: flex;
}
</style>

<!-- 用于侧栏pane -->
<style scoped>
.flow-panel {
  font-size: 14px;
}
</style>