<template>
  <splitpanes class="default-theme">
    <pane min-size="50" size="100" max-size="100">
      <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"
        @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"
      >
        <!-- 自定义节点类型为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 pattern-color="#aaa" :gap="16" />

        <!-- <Controls position="top-left">
          <ControlButton title="重置" @click="resetTransform">
            <changebak name="reset" />
          </ControlButton>
          <ControlButton title="背景切换" @click="toggleDarkMode">
            <changebak v-if="dark" name="sun" />
            <changebak v-else name="moon" />
          </ControlButton>

          <ControlButton title="保存" @click="saveproject">
            <el-icon :color="iconcolor"><UploadFilled /></el-icon>
          </ControlButton>
          <ControlButton title="删除节点" @click="removeNode()">
            <el-icon :color="iconcolor"><DocumentDelete /></el-icon>
          </ControlButton>
          <ControlButton title="删除线" @click="removeEdge()">
            <el-icon :color="iconcolor"><Crop /></el-icon>
          </ControlButton>
          <ControlButton title="清空全部" @click="confirmDelete()">
            <el-icon :color="iconcolor"><DeleteFilled /></el-icon>
          </ControlButton>
        </Controls> -->
      </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, Panel, useVueFlow, MarkerType } from "@vue-flow/core"
import {
  ElMessage,
  ElButton,
  ElDialog,
  ElSelect,
  ElMessageBox
} from "element-plus"
import {
  DocumentDelete,
  Delete,
  UploadFilled,
  Histogram,
  DeleteFilled,
  Crop,
  Close
} from "@element-plus/icons-vue"

import { request, uploadFile } from "@/utils/request"
import { Background } from "@vue-flow/background"
import { ControlButton, Controls } from "@vue-flow/controls"
import "./main.css" //重置样式
import defaultnode from "./defaultnode.vue"
import PointOnlyNode from "./pointonlynode.vue"
import useDragAndDrop from "./useDnD"
import changebak from "./changebak.vue"
import { useProjectStore } from "@/store/project"
import emitter from "@/utils/emitter"
import { onMounted } from "vue"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
import asideData from "./aside/asideData.vue"

import node from "@/assets/img/node.png"

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

const {
  onInit,
  onNodeDragStop,
  onConnect,
  addEdges,
  setViewport,
  toObject,
  addNodes,
  updateEdgeData,
  onConnectStart,
  updateNode,
  updateNodeInternals,
  onNodeDrag
} = useVueFlow()

const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop()

const dark = ref(false)
let vueFlowRef = ref()
let iconcolor = ref("#000")
const GRID_SIZE = 2;
const edges = ref([])
const nodes = ref([])
let mergedObj = ref("")

// 选中节点
let noid = ref([])
let Edgeid = ref() //选中线段id
let seledge = ref(null)
let previousEdge = null // 用于保存上一个选中的边缘
// 连线颜色
let linecolor = ref("#2267B1")
// 线宽
let linewidth = ref(1)

let midNodeCounter = 0 //储存中间节点的序号

const projectStore = useProjectStore()
let pid = computed(() => projectStore.pid || "")

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

const props = defineProps({
  jobId: {
    type: String,
    default: ""
  }
})


// 处理节点拖动时的网格吸附
onNodeDrag(({ node }) => {
  if (!node) {
    console.error('onNodeDrag 未收到节点数据');
    return;
  }
  console.log('拖动节点:', node.id, node.type, node.position);
  const step = node.type === 'point-only' ? 1 : GRID_SIZE;
  const newPosition = {
    x: Math.round(node.position.x / step) * step,
    y: Math.round(node.position.y / step) * step,
  };
  updateNode(node.id, { position: newPosition });
});

// 旧数据存储
let prevNodes = [...nodes.value]
let prevEdges = [...edges.value]

// 监听节点变化
watch(
  nodes,
  (newNodes) => {
    const deletedNodes = prevNodes.filter(
      (node) => !newNodes.some((n) => n.id === node.id)
    )
    const addedNodes = newNodes.filter(
      (node) => !prevNodes.some((n) => n.id === node.id)
    )

    if (deletedNodes.length > 0) {
      console.log("Deleted Nodes:", deletedNodes)
      deletedNodes.forEach((node) => {
        if (node.data?.pcId) {
          comdelete(node.data.pcId)
        }
      })
    }
    if (addedNodes.length > 0) {
      // console.log('Added Nodes:', addedNodes);
    }

    // 更新快照
    prevNodes = [...newNodes]
  },
  { deep: true }
)

// 监听连线变化
watch(
  edges,
  (newEdges) => {
    const deletedEdges = prevEdges.filter(
      (edge) => !newEdges.some((e) => e.id === edge.id)
    )
    const addedEdges = newEdges.filter(
      (edge) => !prevEdges.some((e) => e.id === edge.id)
    )

    if (deletedEdges.length > 0) {
      console.log("Deleted Edges:", deletedEdges)
      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 = ""
        let pcId = ""

        // 判断 source 或 target 是否为中间点 comId === '3'
        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) {
          comlinedelete(npcId, pcId)
        }
      })
    }
    if (addedEdges.length > 0) {
    }

    // 更新快照
    prevEdges = [...newEdges]
  },
  { deep: true }
)

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

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

const saveproject = async () => {
  try {
    let obj = {
      nodes: toObject().nodes,
      edges: toObject().edges
    }
    mergedObj.value = JSON.stringify(obj)

    const params = {
      transCode: "ES0002",
      pid: pid.value,
      flow: mergedObj.value,
      name: projectStore.projectInfo.name || "",
      remark: projectStore.projectInfo.remark || "",
      keywords: projectStore.projectInfo.keywords || ""
    }
    
    await request(params)
    projectStore.setProjectInfo({
      ...projectStore.projectInfo,
      flow: mergedObj.value || ""
    })
    console.log('保存成功')
  } catch (error) {
    console.error("保存失败:", error)
    ElMessage.error("保存失败，请稍后重试")
  }
}

const removeNode = () => {
  if (!noid.value) {
    console.warn("未选中任何节点")
    return
  }

  const nodeIdToRemove = noid.value.id

  vueFlowRef.value.removeNodes(noid.value.id)

  // 清空当前选中
  noid.value = null

  saveproject()
}

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

  vueFlowRef.value.removeEdges(seledge.value) // 移除选中的边
  seledge.value = null // 清空选中状态

  saveproject()
}

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

      ElMessage.success("所有节点和连线已删除")
      saveproject()
    })
    .catch(() => {
      ElMessage.info("已取消删除")
    })
}

const comdelete = (pcId) => {
  const params = {
    transCode: "ES0005",
    pcId: pcId
  }
  request(params)
    .then((res) => {
      console.log("组件删除成功")
    })
    .catch((err) => {
      ElMessage.error(err.returnMsg)
    })
}

const comlinedelete = (npcId, pcId) => {
  const params = {
    transCode: "ES0007",
    npcId: npcId,
    pcId: pcId,
    type: 0
  }
  request(params)
    .then((res) => {
      console.log("组件连线删除成功")
    })
    .catch((err) => {
      ElMessage.error(err.returnMsg)
    })
}

const customOnDrop = async (event) => {
  console.log("自定义拖放事件", event)

  await onDrop(event) // 等待 onDrop 执行完成
  saveproject() // onDrop 执行完之后再保存项目
}

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

const onEdgeClick = (e) => {
  console.log("Edge Click", e.edge)
  // console.log('所有线段：', edges.value);
  // 如果已经有选中的边缘
  if (seledge.value) {
    // 恢复上一个选中边缘的样式
    if (previousEdge) {
      previousEdge.style = {
        ...previousEdge.style,
        stroke: previousEdge.originalColor, // 恢复原始颜色
        strokeWidth: previousEdge.originalWidth // 恢复原始宽度
      }
    }
  }

  // 保存当前点击的边缘为选中边缘
  Edgeid.value = e.edge.id
  seledge.value = e.edge

  // 暂时更改当前选中边缘的样式
  seledge.value.originalColor = seledge.value.style.stroke // 保存当前边缘的原始颜色
  seledge.value.originalWidth = seledge.value.style.strokeWidth // 保存当前边缘的原始宽度

  const isdefault = e.edge.data.type === "default" // 判断是否为默认线
  seledge.value.style = {
    ...seledge.value.style,
    stroke: isdefault ? "#2267B1" : "rgba(255, 255, 0, 0.3)", // 设置选中边缘的颜色
    strokeWidth: isdefault ? 2 : 6 // 设置选中边缘的宽度
  }

  // 保存当前选中的边缘作为上一个选中边缘
  previousEdge = seledge.value
}

const onNodeClick = (event) => {
  noid.value = event.node
}

const onNodeDoubleClick = (event) => {
  console.log("节点被双击:", event)

  showPanel.value = true
  const pcId = event.node.data.pcId
  nextTick(() => {
    console.log("diaoy", pcId)
    if (asideDataref.value) {
      asideDataref.value.getcomdata(pcId)
      if (props.jobId){
        asideDataref.value.getresultData(props.jobId)
      }
    }
  })
}

const onEdgeDoubleClick = (event) => {
  console.log("连线双击:", event)
  noid.value = event.node
}

// 监听连接开始，提前取消选中的线段
onConnectStart(() => {
  cleanEdgeselect()
})

// 线的类型 default
let lineType = ref("default")

onConnect(async (connection) => {
  console.log("线连接", connection)

  if (connection.source === connection.target) {
    console.warn("禁止节点自连")
    return
  }

  const sourceNode = vueFlowRef.value.getNode(connection.source)
  const targetNode = vueFlowRef.value.getNode(connection.target)

  if (sourceNode.data.comId === "3" && targetNode.data.comId === "3") {
    console.warn("禁止连接两个中间节点")
    return
  }

  const hasDuplicateEdge = edges.value.some(
    (edge) =>
      (edge.source === connection.source &&
        edge.target === connection.target) ||
      (edge.source === connection.target && edge.target === connection.source)
  )

  if (hasDuplicateEdge) {
    console.warn("禁止重复连接：起点和终点已连接")
    return
  }

  const isDuplicate = edges.value.some((edge1) => {
    // edge1: source -> 中间节点
    if (
      edge1.source === connection.source ||
      edge1.target === connection.source
    ) {
      const middleNodeId =
        edge1.source === connection.source ? edge1.target : edge1.source

      // 确保 middleNode 是中间组件（comId === '3'）
      const middleNode = vueFlowRef.value.getNode(middleNodeId)
      if (!middleNode || middleNode.data.comId !== "3") return false

      // 查找是否还有另一条边连接 middleNode <-> target
      return edges.value.some(
        (edge2) =>
          (edge2.source === middleNodeId &&
            edge2.target === connection.target) ||
          (edge2.target === middleNodeId && edge2.source === connection.target)
      )
    }
    return false
  })

  if (isDuplicate) {
    console.warn("禁止重复连接：这两个节点已经通过中间组件连接过了")
    return
  }

  // 是否需要中间节点
  const isCom3 = sourceNode.data.comId === "3" || targetNode.data.comId === "3"

  if (isCom3) {
    //（comID == 3）
    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 }
    // connection.markerEnd = lineType.value === 'data'
    //   ? { type: MarkerType.ArrowClosed, width: 6, height: 6, color: linecolor.value }
    //   : MarkerType.ArrowClosed;

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

    addEdges(connection)
    seledge.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)
    }
  } else {
    // 添加 point-only 中间节点
    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

    // 计算 sourceNode 和 targetNode 相对于 pointNode 的位置
    const dxSource = sourceNode.position.x - midX
    const dySource = sourceNode.position.y - midY
    const dxTarget = targetNode.position.x - midX
    const dyTarget = targetNode.position.y - midY

    // 判断 sourceNode 的主要方向（水平 or 垂直）
    const isSourceHorizontal = Math.abs(dxSource) > Math.abs(dySource)
    const sourceDirection = isSourceHorizontal
      ? dxSource < 0
        ? "left"
        : "right"
      : dySource < 0
      ? "top"
      : "bottom"

    // 判断 targetNode 的主要方向
    const isTargetHorizontal = Math.abs(dxTarget) > Math.abs(dyTarget)
    const targetDirection = isTargetHorizontal
      ? dxTarget < 0
        ? "left"
        : "right"
      : dyTarget < 0
      ? "top"
      : "bottom"

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

    try {
      // 创建 comID 为 3 的中间组件
      const { pcId: npcId, ser, idCode } = await createCom3(pid.value)

      const pointNode = nodes.value.find((n) => n.id === pointNodeId)
      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])

      // 保存后端 edge 数据（分别对应两条边）
      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)
    }
  }

  saveproject()
})

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
    } // 返回包含 pccId1 和 pccId2 的对象
  } catch (err) {
    // 处理错误
    ElMessage.error(err.returnMsg || "保存流程失败")
    throw err // 可以选择重新抛出错误以便调用者处理
  }
}

// 创建特殊节点
const createCom3 = async (pid) => {
  const params = {
    transCode: "ES0004",
    pid: pid || "",
    comId: "3" // 节点ID
  }

  try {
    const res = await request(params)
    return {
      pcId: res.pcId,
      ser: res.ser,
      idCode: res.idCode
    }
  } catch (err) {
    ElMessage.error(err.returnMsg)
  }
}

const flowInit = () => {
  let nodesflow = JSON.parse(
    projectStore.projectInfo.flow || '{"nodes":[],"edges":[]}'
  )

  nodes.value = nodesflow.nodes
  edges.value = nodesflow.edges
}

const cleanEdgeselect = () => {
  if (seledge.value) {
    // 恢复选中边缘的原始样式
    seledge.value.style = {
      ...seledge.value.style,
      stroke: seledge.value.originalColor,
      strokeWidth: previousEdge?.originalWidth || 1 // 恢复原始宽度
    }

    // 清空选中的边缘
    seledge.value = null
    Edgeid.value = null
    previousEdge = null
  }
}

onMounted(() => {
  flowInit()

  // 点击其他区域取消线段选中
  if (vueFlowRef.value) {
    vueFlowRef.value.$el.addEventListener("click", (event) => {
      // 确保点击的不是边缘
      if (seledge.value && !event.target.closest(".vue-flow__edge")) {
        cleanEdgeselect()
      }
    })
  }
})

const closePanel = () => {
  setTimeout(() => {
    showPanel.value = false
  }, 100) // 延迟 100ms 销毁组件，避免 Splitpanes 销毁错误
}

// 路由切换前保存
router.beforeEach(async (to, from, next) => {
  if (to.path !== from.path) {
    try {
      await saveproject() // 直接调用 saveproject
      next()
    } catch (error) {
      console.error("路由切换保存失败:", error)
      next() // 即使保存失败也允许切换路由
    }
  } else {
    next()
  }
})

// 组件卸载前保存
onBeforeUnmount(async () => {
  await saveproject() // 直接调用 saveproject
})

defineExpose({
  resetTransform,
  toggleDarkMode,
  saveproject,
  removeNode,
  removeEdge,
  confirmDelete,
  asideDataref
})
</script>

<style scoped>
/* .vue-flow__edge.selected .vue-flow__edge-path, .vue-flow__edge:focus .vue-flow__edge-path, .vue-flow__edge:focus-visible .vue-flow__edge-path {
    stroke: #555 !important;
} */
.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;
  /* 设置edges的左对齐 */
}

.vue-flow__edge-text {
  transform: translateY(-10px); /* 将 label 向上偏移 */
  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 {
  /* width: auto !important; */
  border: none;
  background-color: rgba(0, 0, 0, 0);
}
.node-content {
  cursor: move; /* 更改鼠标光标表示可拖动 */
}
.vue-flow__node {
  cursor: move;
}

/* 禁用文本选中效果 */
.left_main * {
  -webkit-user-select: none; /* Safari */
  -moz-user-select: none; /* Firefox */
  -ms-user-select: none; /* IE10+/Edge */
  user-select: none; /* Standard syntax */
}
.lableaniu {
  font-size: 12px;
  background-color: #ddd;
  padding: 4px 16px;
  /* margin-top: -17px; */
  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>