<template>
  <div class="vis-network-container">
    <div v-if="isEdit" class="toolbar">
      说明：双击节点可以进行操作
      <el-button type="primary" @click="addNode">添加子节点</el-button>
      <el-button type="danger" @click="deleteNode">删除</el-button>
    </div>
    <div ref="network" class="network">
      <p class="noData">{{ loadingTitle }}</p>
    </div>
    <el-dialog
      title="编辑"
      :visible.sync="showEditModal"
      width="30%"
      :close-on-click-modal="false"
      :append-to-body="true"
    >
      <el-form :model="editForm" label-width="80px">
        <el-form-item label="所属层级">
          <el-input v-model="editForm.fullPath" type="textarea" disabled />
        </el-form-item>
        <el-form-item label="节点名称">
          <el-input v-model="editForm.label" type="textarea" placeholder="请输入节点名称" />
        </el-form-item>

        <el-form-item v-if="false" label="节点类型">
          <select v-model="editForm.type" class="form-select">
            <option value="0">章节</option>
            <option value="3">资源类型</option>
            <option value="4">具体文件</option>
          </select>
        </el-form-item>
      </el-form>

      <!-- 按钮区域 -->
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="cancelEdit">取消</el-button>
        <el-button type="success" @click="saveEdit">保存</el-button>
        <el-button type="danger" @click="deleteNode">删除</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { DataSet } from 'vis-data';
import { Network } from 'vis-network';
import { GetBookKnowledgeGraph } from '@/api/book';
export default {
  name: 'VisNetwork',
  props: {
    isEdit: {
      type: Boolean,
      default: false,
    },
    bookId: {
      type: String,
      required: true,
    },
  },
  data() {
    return {
      loadingTitle: '数据加载中...',
      network: null,
      nodes: null,
      edges: null,
      selectedNode: null,
      showEditModal: false,
      editingNode: null,
      positions: {},
      jsonData: {},
      hasData: false,
      editForm: {
        label: '',
        type: '0',
        fullPath: '',
      },
    };
  },
  computed: {},
  created() {
    this.hasData = false;
    this.getBookVisNetWork();
  },
  mounted() {},
  beforeDestroy() {
    this.destroyNetwork();
  },
  methods: {
    /**
     * 得到教材知识图谱
     * @param {string} id - 教材ID
     */
    getBookVisNetWork() {
      GetBookKnowledgeGraph({ book_id: this.bookId })
        .then((res) => {
          this.convertToVisNetworkData(res);
        })
        .catch(() => {
          this.loadingTitle = '数据未生成';
        });
    },
    init() {
      this.destroyNetwork();
      this.initNetwork(this.jsonData.nodes, this.jsonData.edges);
    },
    destroyNetwork() {
      if (this.network) {
        this.network.destroy();
      }
      this.positions = {};
    },
    initNetwork(nodeData, edgeData) {
      this.nodes = new DataSet(nodeData);
      this.edges = new DataSet(edgeData);
      const data = {
        nodes: this.nodes,
        edges: this.edges,
      };

      // 创建网络图
      const container = this.$refs.network;

      let options = {
        nodes: {
          shape: 'box',
          margin: 10,
          size: 20,
          font: {
            size: 14,
          },
          borderWidth: 2,
        },
        edges: {
          width: 2,
          color: { color: '#848484' },
          smooth: {
            type: 'continuous',
          },
        },
        groups: {
          default: {
            color: { background: '#97C2FC', border: '#6AA6F8' },
            borderWidth: 2,
            font: { color: '#FFFFFF' },
          },
          type0: {
            color: { background: '#97C2FC', border: '#84B7FD' },
            borderWidth: 3,
          },
          type1: {
            color: { background: '#FFA807', border: '#FDA400' },
            borderWidth: 2,
          },
          type2: {
            color: { background: '#2ECC71', border: '#0BCC5D' },
            borderWidth: 2,
          },
          type3: {
            color: { background: '#FB7E81', border: '#F85C5F' },
            borderWidth: 2,
          },
        },
        physics: {
          enabled: true,
          stabilization: {
            iterations: 100,
          },
        },
        interaction: {
          hover: true,
          tooltipDelay: 200,
        },
      };

      this.network = new Network(container, data, options);

      // 添加事件监听
      this.network.on('click', (params) => {
        if (params.nodes.length > 0) {
          const nodeId = params.nodes[0];
          if (!this.isEdit) {
            this.$emit('child-click', nodeId);
            return;
          }
          this.selectedNode = this.nodes.get(nodeId);
          this.editingNode = nodeId;
        } else {
          this.selectedNode = null;
        }
      });

      this.network.on('doubleClick', (params) => {
        if (!this.isEdit) return;
        if (params.nodes.length > 0) {
          const nodeId = params.nodes[0];
          this.handleNodeDoubleClick(nodeId);
        }
      });

      this.network.on('oncontext', (params) => {
        params.event.preventDefault();
      });
      this.network.on('hoverNode', (params) => {});
    },

    // 树形数据转换工具
    convertToVisData(treeData) {
      const nodes = [];
      const edges = [];
      let x = 0;
      let y = 0;

      const traverse = (node, parentId = null, level = 0, parentPath = '') => {
        const nodeId = node.data.uid;

        // 创建节点
        nodes.push({
          id: nodeId,
          label: node.data.text,
          type: node.data.type,
          level,
          fullPath: parentPath, // 保存所有父级路径，用->分隔
          group: `type${node.data.type || 0}`,
        });
        // 创建边（如果有父节点）
        if (parentId) {
          edges.push({
            from: parentId,
            to: nodeId,
            arrows: 'to',
            smooth: { type: 'cubicBezier' },
          });
        }

        // 递归处理子节点
        if (node.children && node.children.length > 0) {
          // 构建当前节点的完整路径
          const currentPath = parentPath ? `${parentPath}->${node.data.text}` : node.data.text;

          node.children.forEach((child, index) => {
            if (level < 3) traverse(child, nodeId, level + 1, currentPath);
          });
        }
      };

      // 调用时传入空字符串作为初始路径
      traverse(treeData.root, null, 0, '');
      return { nodes, edges };
    },

    handleNodeDoubleClick(nodeId) {
      const node = this.nodes.get(nodeId);
      console.info(node);
      if (node) {
        this.editingNode = nodeId;
        this.editForm = {
          label: node.label,
          type: node.type,
          fullPath: node.fullPath,
        };
        this.showEditModal = true;
      }
    },
    addOrUpdate(data) {
      if (!data) return;
      let oldNodes = this.nodes.get();
      let oldEdges = this.edges.get();
      const node = this.nodes.get(data.id);
      if (node) {
        oldNodes = oldNodes.filter((x) => x.id !== node.id);
        let newData = Object.assign({}, node, data);
        oldNodes.push(newData);
      } else {
        oldNodes.push(data);
      }

      this.positions = this.network.getPositions() || {};
      oldNodes.map((x) => {
        if (x.id && this.positions[x.id]) {
          let tmpPosition = this.positions[x.id];
          x.x = tmpPosition.x;
          x.y = tmpPosition.y;
        }
      });
      console.info('oldNodes', oldNodes);
      this.initNetwork(oldNodes, oldEdges);
    },
    addNode() {
      if (!this.selectedNode) {
        this.$message.error('请先选择父节点!');
        return;
      }
      let newId = this.generateUniqueId();
      const newNode = Object.assign(
        {},
        {
          id: newId,
          label: '新增节点',
          fullPath: `${this.selectedNode.fullPath}->${this.selectedNode.label}`,
          type: (this.selectedNode.type || 0) + 1,
          level: (this.selectedNode.level || 0) + 1,
        },
      );
      newNode.group = `type${newNode.type}`;

      newId = this.generateUniqueId();
      this.edges.add({
        id: newId,
        from: this.selectedNode.id,
        to: newNode.id,
        arrows: 'to',
      });

      // this.nodes.add(newNode);
      this.addOrUpdate(newNode);
    },

    // 保存编辑
    saveEdit() {
      if (!this.editingNode) return;

      const updatedNode = {
        id: this.editingNode,
        label: this.editForm.label,
        type: parseInt(this.editForm.type),
      };

      // this.nodes.update(updatedNode);
      // this.$emit('node-updated', updatedNode);
      this.addOrUpdate(updatedNode);
      this.cancelEdit();
    },

    // 取消编辑
    cancelEdit() {
      this.showEditModal = false;
      this.editingNode = null;
      this.editForm = { label: '', type: '0' };
    },

    // 删除节点
    deleteNode() {
      if (!this.editingNode) return;
      this.$confirm('确定要删除此节点吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.nodes.remove({ id: this.editingNode });
          this.$emit('node-deleted', this.editingNode);
          this.cancelEdit();
        })
        .catch(() => {});
    },
    saveData() {
      if (!this.hasData) return null;
      let nodes = this.nodes.get();
      let edges = this.edges.get();
      this.positions = this.network.getPositions() || {};
      nodes.map((x) => {
        if (x.id && this.positions[x.id]) {
          let tmpPosition = this.positions[x.id];
          x.x = tmpPosition.x;
          x.y = tmpPosition.y;
        }
      });
      return { nodes, edges };
    },
    generateUniqueId() {
      return Date.now() + Math.random().toString(36).substr(2, 9);
    },

    convertToVisNetworkData(res) {
      if (res && res.status === 1) {
        this.loadingTitle = '数据渲染中...';
        if (res.content_node && res.content_edge) {
          let nodes = (JSON.parse(res.content_node) || {}).nodes;
          let edges = (JSON.parse(res.content_edge) || {}).edges;
          nodes.map((x) => (x.group = `type${x.type || 0}`));
          // nodes=nodes.filter(x=>x.level<4)
          this.jsonData = {
            nodes,
            edges,
          };
          this.hasData = true;
          this.init();
        }
      }
      this.loadingTitle = '数据未生成';
    },
  },
};
</script>

<style scoped>
.vis-network-container {
  width: 100%;
  padding: 1px;
}

.network {
  width: 100%;
  height: calc(100vh - 280px);
  margin-bottom: 5px;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
}

.noData {
  display: flex;
  align-items: center; /* 垂直居中 */
  justify-content: center; /* 水平居中 */
  height: calc(100vh - 250px);
}
</style>
