<template>
  <div class="flow-container">
    <div class="toolbar">
      <el-button-group>
        <el-button @click="addStartNode">开始节点</el-button>
        <el-button @click="addProcessNode">流程节点</el-button>
        <el-button @click="addEndNode">结束节点</el-button>
      </el-button-group>
      <el-divider direction="vertical" />
      <el-button-group>
        <el-button @click="saveGraph">保存</el-button>
        <el-button @click="exportGraph">导出</el-button>
        <el-button @click="importGraph">导入</el-button>
        <el-button @click="clearGraph">清空</el-button>
      </el-button-group>
      <el-divider direction="vertical" />
      <el-button-group>
        <el-button @click="undo" :disabled="!canUndo">撤销</el-button>
        <el-button @click="redo" :disabled="!canRedo">重做</el-button>
      </el-button-group>
    </div>

    <div ref="container" class="graph-container"></div>

    <el-dialog
      title="编辑节点"
      :visible.sync="editModalVisible"
      @close="handleEditCancel"
      width="600px"
    >
      <el-form :model="editForm" label-width="100px">
        <el-form-item label="节点名称">
          <el-input v-model="editForm.label"></el-input>
        </el-form-item>

        <el-form-item label="节点类型">
          <el-select v-model="editForm.type" placeholder="请选择节点类型">
            <el-option label="审批节点" value="approval"></el-option>
            <el-option label="条件节点" value="condition"></el-option>
            <el-option label="执行节点" value="action"></el-option>
          </el-select>
        </el-form-item>

        <el-form-item label="节点描述">
          <el-input
            type="textarea"
            v-model="editForm.description"
            :rows="3"
          ></el-input>
        </el-form-item>

        <!-- 属性列表 -->
        <el-form-item label="节点属性">
          <div
            v-for="(prop, index) in editForm.properties"
            :key="index"
            class="property-item"
          >
            <el-input
              v-model="prop.key"
              placeholder="属性名"
              style="width: 200px"
            ></el-input>
            <el-input
              v-model="prop.value"
              placeholder="属性值"
              style="width: 200px"
            ></el-input>
            <el-button type="text" @click="removeProperty(index)"
              >删除</el-button
            >
          </div>
          <el-button type="text" @click="addProperty">添加属性</el-button>
        </el-form-item>

        <!-- 条件设置（当节点类型为条件节点时显示） -->
        <template v-if="editForm.type === 'condition'">
          <el-form-item label="条件设置">
            <div
              v-for="(condition, index) in editForm.conditions"
              :key="index"
              class="condition-item"
            >
              <el-input
                v-model="condition.expression"
                placeholder="条件表达式"
                style="width: 300px"
              ></el-input>
              <el-input
                v-model="condition.description"
                placeholder="条件描述"
                style="width: 200px"
              ></el-input>
              <el-button type="text" @click="removeCondition(index)"
                >删除</el-button
              >
            </div>
            <el-button type="text" @click="addCondition">添加条件</el-button>
          </el-form-item>
        </template>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="handleEditCancel">取 消</el-button>
        <el-button type="primary" @click="handleEditOk">确 定</el-button>
      </span>
    </el-dialog>

    <el-dialog
      title="编辑连线标签"
      :visible.sync="edgeLabelModalVisible"
      @close="handleEdgeLabelCancel"
      width="400px"
    >
      <el-form :model="edgeLabelForm" label-width="80px">
        <el-form-item label="标签文本">
          <el-input v-model="edgeLabelForm.label"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handleEdgeLabelCancel">取 消</el-button>
        <el-button type="primary" @click="handleEdgeLabelOk">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { Graph, Shape, Addon } from "@antv/x6";
import { Message } from "element-ui";

export default {
  name: "FlowEditor",
  data() {
    return {
      graph: null,
      selectedNode: null,
      editModalVisible: false,
      editForm: {
        label: "",
        description: "",
        type: "",
        properties: [],
        conditions: [],
      },
      history: null,
      dnd: null,
      selectedEdge: null,
      edgeLabelModalVisible: false,
      edgeLabelForm: {
        label: ''
      }
    };
  },
  computed: {
    canUndo() {
      return this.history?.canUndo() || false;
    },
    canRedo() {
      return this.history?.canRedo() || false;
    },
  },
  mounted() {
    // 确保DOM加载完成后再初始化
    this.$nextTick(() => {
      this.initGraph();
      this.bindEvents();
    });
  },
  methods: {
    initGraph() {
      // 注册自定义节点
      this.registerCustomNodes();

      // 初始化画布
      this.graph = new Graph({
        container: this.$refs.container,
        width: "100%",
        height: 600,
        grid: {
          type: "mesh",
          size: 10,
          visible: true,
        },
        connecting: {
          snap: true,
          allowBlank: false,
          allowLoop: false,
          highlight: true,
          connector: "normal",
          anchor: "center",
          // 使用 manhattan 路由实现直角连线
          router: {
            name: "manhattan",
            args: {
              padding: 20,
              startDirections: ["bottom"],
              endDirections: ["top"],
            },
          },
          connectionPoint: {
            name: "boundary",
            args: {
              sticky: true,
            },
          },
          validateMagnet() {
            return true;
          },
          createEdge() {
            return this.createEdge({
              attrs: {
                line: {
                  stroke: "#333",
                  strokeWidth: 2,
                  targetMarker: {
                    name: "classic",
                    size: 8,
                  },
                },
              },
              labels: [{
                attrs: {
                  text: {
                    text: '',
                    fill: '#333',
                    fontSize: 12,
                    textAnchor: 'middle',
                    textVerticalAnchor: 'middle',
                  },
                  rect: {
                    fill: '#fff',
                    stroke: '#333',
                    strokeWidth: 1,
                    rx: 3,
                    ry: 3,
                    refWidth: '100%',
                    refHeight: '100%',
                    refX: 0,
                    refY: 0,
                  }
                },
                position: {
                  distance: 0.5,
                  options: {
                    absoluteDistance: true,
                    reverseDistance: true,
                    keepGradient: true,
                    ensureLegibility: true,
                  }
                }
              }]
            });
          },
          validateConnection: ({ sourceCell, targetCell }) => {
            if (targetCell.shape === "flow-start") return false;
            if (sourceCell.shape === "flow-end") return false;
            return true;
          },
          defaultEdge: {
            attrs: {
              line: {
                stroke: "#333",
                strokeWidth: 2,
                targetMarker: {
                  name: "classic",
                  size: 8,
                },
              },
            },
            router: {
              name: "manhattan",
              args: {
                padding: 20,
                startDirections: ["bottom"],
                endDirections: ["top"],
              },
            },
            interactive: true,
            vertices: true,
            vertexAddable: true,
            vertexMovable: true,
            vertexRemovable: true,
          },
        },
        highlighting: {
          magnetAvailable: {
            name: "stroke",
            args: {
              padding: 4,
              attrs: {
                strokeWidth: 4,
                stroke: "#31d0c6",
              },
            },
          },
        },
        panning: true,
        mousewheel: {
          enabled: true,
          modifiers: ["ctrl", "meta"],
        },
        selecting: {
          enabled: true,
          multiple: true,
          rubberband: true,
          showNodeSelectionBox: true,
        },
        snapline: true,
        history: true,
        clipboard: true,
        interacting: {
          nodeMovable: true,
          edgeMovable: true,
          edgeLabelMovable: false,
          vertexMovable: true,
          vertexAddable: true,
          vertexDeletable: true,
        },
      });
      // 添加边线双击事件
      this.graph.on('edge:contextmenu', ({ edge }) => {
        this.selectedEdge = edge;
        const currentLabel = edge.getLabels()?.[0]?.attrs?.text?.text || '';
        this.edgeLabelForm.label = currentLabel;
        this.edgeLabelModalVisible = true;
      });
      // 修改双击事件绑定
      this.graph.on("cell:dblclick", ({ node, e }) => {
        console.log("Node double clicked:", node);
        this.selectedNode = node;
        const nodeData = node.getData() || {};

        // 获取节点数据
        this.editForm = {
          label: node.attr("label/text") || "",
          description: nodeData.description || "",
          type: nodeData.type || "",
          properties: Array.isArray(nodeData.properties)
            ? nodeData.properties
            : [],
          conditions: Array.isArray(nodeData.conditions)
            ? nodeData.conditions
            : [],
        };

        this.editModalVisible = true;
      });
      
      // 添加单击事件用于测试事件绑定
      this.graph.on("node:click", ({ node }) => {
        console.log("Node clicked:", node);
      });

      // 连线完成事件
      this.graph.on("edge:connected", ({ edge }) => {
        edge.attr({
          line: {
            stroke: "#333",
            strokeWidth: 2,
            targetMarker: {
              name: "classic",
              size: 8,
            },
          },
        });
      });

      // 快捷键支持
      this.graph.bindKey(["meta+c", "ctrl+c"], () => {
        const cells = this.graph.getSelectedCells();
        if (cells.length) {
          this.graph.copy(cells);
        }
        return false;
      });

      this.graph.bindKey(["meta+v", "ctrl+v"], () => {
        if (!this.graph.isClipboardEmpty()) {
          const cells = this.graph.paste({ offset: 32 });
          this.graph.cleanSelection();
          this.graph.select(cells);
        }
        return false;
      });

      this.graph.bindKey(["meta+z", "ctrl+z"], () => {
        if (this.canUndo) {
          this.undo();
        }
        return false;
      });

      this.graph.bindKey(["meta+shift+z", "ctrl+shift+z"], () => {
        if (this.canRedo) {
          this.redo();
        }
        return false;
      });
      // 初始化历史记录
      this.history = this.graph.history;

      // 初始化拖拽
      this.dnd = new Addon.Dnd({ target: this.graph });
    },

    registerCustomNodes() {
      // 注册开始节点
      Graph.registerNode("flow-start", {
        inherit: "circle",
        width: 60,
        height: 60,
        attrs: {
          body: {
            fill: "#2ecc71",
            stroke: "#27ae60",
            magnet: true,
          },
          label: {
            text: "开始",
            fill: "#fff",
            fontSize: 14,
          },
        },
        markup: [
          {
            tagName: "circle",
            selector: "body",
          },
          {
            tagName: "text",
            selector: "label",
          },
        ],
      });

      // 注册流程节点
      Graph.registerNode("flow-process", {
        inherit: "rect",
        width: 120,
        height: 60,
        attrs: {
          body: {
            fill: "#fff",
            stroke: "#333",
            strokeWidth: 2,
            rx: 8,
            ry: 8,
            magnet: true,
          },
          label: {
            fontSize: 14,
            fill: "#333",
          },
        },
        markup: [
          {
            tagName: "rect",
            selector: "body",
          },
          {
            tagName: "text",
            selector: "label",
          },
        ],
      });

      // 注册结束点
      Graph.registerNode("flow-end", {
        inherit: "circle",
        width: 60,
        height: 60,
        attrs: {
          body: {
            fill: "#e74c3c",
            stroke: "#c0392b",
            magnet: true,
          },
          label: {
            text: "结束",
            fill: "#fff",
            fontSize: 14,
          },
        },
        markup: [
          {
            tagName: "circle",
            selector: "body",
          },
          {
            tagName: "text",
            selector: "label",
          },
        ],
      });
    },

    addStartNode() {
      const node = this.graph.addNode({
        shape: "flow-start",
        x: 100,
        y: 100,
      });
    },

    addProcessNode() {
      const node = this.graph.addNode({
        shape: "flow-process",
        x: 200,
        y: 200,
        attrs: {
          body: {
            fill: "#fff",
            stroke: "#333",
            strokeWidth: 2,
            rx: 8,
            ry: 8,
            magnet: true,
          },
          label: {
            text: "流程节点",
            fontSize: 14,
            fill: "#333",
          },
        },
        data: {
          type: "",
          description: "",
          properties: [],
          conditions: [],
        },
        interactive: true,
        selectable: true,
      });
    },

    addEndNode() {
      const node = this.graph.addNode({
        shape: "flow-end",
        x: 300,
        y: 300,
      });
    },

    bindEvents() {
      // 修改双击事件绑定
      this.graph.on("cell:dblclick", ({ node, e }) => {
        console.log("Node double clicked:", node);
        this.selectedNode = node;
        const nodeData = node.getData() || {};

        // 获取节点数据
        this.editForm = {
          label: node.attr("label/text") || "",
          description: nodeData.description || "",
          type: nodeData.type || "",
          properties: Array.isArray(nodeData.properties)
            ? nodeData.properties
            : [],
          conditions: Array.isArray(nodeData.conditions)
            ? nodeData.conditions
            : [],
        };

        this.editModalVisible = true;
      });

      // 添加单击事件用于测试事件绑定
      this.graph.on("node:click", ({ node }) => {
        console.log("Node clicked:", node);
      });

      // 连线完成事件
      this.graph.on("edge:connected", ({ edge }) => {
        edge.attr({
          line: {
            stroke: "#333",
            strokeWidth: 2,
            targetMarker: {
              name: "classic",
              size: 8,
            },
          },
        });
      });

      // 快捷键支持
      this.graph.bindKey(["meta+c", "ctrl+c"], () => {
        const cells = this.graph.getSelectedCells();
        if (cells.length) {
          this.graph.copy(cells);
        }
        return false;
      });

      this.graph.bindKey(["meta+v", "ctrl+v"], () => {
        if (!this.graph.isClipboardEmpty()) {
          const cells = this.graph.paste({ offset: 32 });
          this.graph.cleanSelection();
          this.graph.select(cells);
        }
        return false;
      });

      this.graph.bindKey(["meta+z", "ctrl+z"], () => {
        if (this.canUndo) {
          this.undo();
        }
        return false;
      });

      this.graph.bindKey(["meta+shift+z", "ctrl+shift+z"], () => {
        if (this.canRedo) {
          this.redo();
        }
        return false;
      });

      // 添加边线双击事件
      this.graph.on('edge:dblclick', ({ edge }) => {
        this.selectedEdge = edge;
        this.edgeLabelForm.label = edge.getLabels()?.[0]?.attrs?.text || '';
        this.edgeLabelModalVisible = true;
      });
    },

    handleEditOk() {
      if (this.selectedNode) {
        // 更新节点文本
        this.selectedNode.attr("label/text", this.editForm.label);

        // 更新节点数据
        this.selectedNode.setData({
          description: this.editForm.description,
          type: this.editForm.type,
          properties: this.editForm.properties,
          conditions: this.editForm.conditions,
        });
      }
      this.editModalVisible = false;
    },

    handleEditCancel() {
      this.editModalVisible = false;
    },

    saveGraph() {
      const data = this.graph.toJSON();
      localStorage.setItem("flowData", JSON.stringify(data));
      message.success("保存成功");
    },

    exportGraph() {
      const data = this.graph.toJSON();
      const dataStr = JSON.stringify(data, null, 2);
      const blob = new Blob([dataStr], { type: "application/json" });
      const url = URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.download = "flow.json";
      link.href = url;
      link.click();
    },

    importGraph() {
      const input = document.createElement("input");
      input.type = "file";
      input.accept = ".json";
      input.onchange = (e) => {
        const file = e.target.files[0];
        const reader = new FileReader();
        reader.onload = (event) => {
          try {
            const data = JSON.parse(event.target.result);
            this.graph.fromJSON(data);
            message.success("导入成功");
          } catch (error) {
            message.error("导入失败：无效的文件格式");
          }
        };
        reader.readAsText(file);
      };
      input.click();
    },

    clearGraph() {
      this.graph.clearCells();
    },

    undo() {
      this.history.undo();
    },

    redo() {
      this.history.redo();
    },

    addProperty() {
      this.editForm.properties.push({
        key: "",
        value: "",
      });
    },

    removeProperty(index) {
      this.editForm.properties.splice(index, 1);
    },

    addCondition() {
      this.editForm.conditions.push({
        expression: "",
        description: "",
      });
    },

    removeCondition(index) {
      this.editForm.conditions.splice(index, 1);
    },

    handleEdgeLabelOk() {
      if (this.selectedEdge) {
        this.selectedEdge.setLabels([{
          attrs: {
            text: {
              text: this.edgeLabelForm.label,
              fill: '#333',
              fontSize: 12,
              textAnchor: 'middle',
              textVerticalAnchor: 'middle',
            },
            rect: {
              fill: '#fff',
              stroke: '#333',
              strokeWidth: 1,
              rx: 3,
              ry: 3,
              refWidth: '100%',
              refHeight: '100%',
              refX: 0,
              refY: 0,
            }
          },
          position: {
            distance: 0.5,
            options: {
              absoluteDistance: true,
              reverseDistance: true,
              keepGradient: true,
              ensureLegibility: true,
            }
          }
        }]);
      }
      this.edgeLabelModalVisible = false;
    },

    handleEdgeLabelCancel() {
      this.edgeLabelModalVisible = false;
    }
  },
};
</script>

<style scoped>
.flow-container {
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.graph-container {
  flex: 1;
  background-color: #f5f5f5;
  position: relative;
}

.toolbar {
  padding: 8px;
  border-bottom: 1px solid #ddd;
  background: #fff;
}

.property-item,
.condition-item {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  gap: 10px;
}

.el-form-item {
  margin-bottom: 22px;
}
</style>
