<template>
  <div>
    <!-- <div id="graph-container">
      <div v-if="isLoading">Loading data from Neo4j...</div>
      <div v-if="errorMessage">{{ errorMessage }}</div>
    </div> -->
    <div ref="myPage" class="my-graph" style="height: calc(100vh - 184px);">
      <RelationGraph
        ref="graphRef"
        :options="graphOptions"
        :on-node-click="onNodeClick"
        :on-canvas-click="onCanvasClick"
      >
        <template #node="{node}">
          <div @mouseover="showNodeTips(node, $event)" @mouseout="hideNodeTips(node, $event)">
            <div class="c-my-rg-node" :style="{'height': node.width + 'px', 'line-height': node.width + 'px'}">
              {{ node.text }}
            </div>
          </div>
        </template>
        <template #graph-plug>
          <div v-if="isShowNodeTipsPanel" :style="{left: nodeMenuPanelPosition.x + 'px', top: nodeMenuPanelPosition.y + 'px' }" style="z-index: 999;padding:10px;background-color: #ffffff;border:#eeeeee solid 1px;box-shadow: 0px 0px 8px #cccccc;position: absolute;">
            <div style="line-height: 25px;color: #888888;font-size: 12px;">节点类型：{{ currentNode.typeText }}</div>
            <div style="line-height: 25px;color: #888888;font-size: 12px;">节点名称：{{ currentNode.text }}</div>
          </div>
        </template>
      </RelationGraph>
    </div>
  </div>
</template>

<script>
// import { getGraphData } from '../../../neo4j.js'
import RelationGraph from 'relation-graph'
import { FetchInitShowByCategory } from '@/api/ai/ai'

export default {
  name: 'Demo',
  components: { RelationGraph },
  props: {
  },
  data() {
    return {
      graphData: {},
      isShowCodePanel: false,
      isShowNodeTipsPanel: false,
      nodeMenuPanelPosition: { x: 0, y: 0 },
      currentNode: {},
      graphOptions: {
        useAnimationWhenExpanded: true,
        useAnimationWhenRefresh: true,
        placeOtherGroup: true,
        disableNodeclickEffect: true,
        reLayoutWhenExpandedOrCollapsed: true,
        defaultExpandHolderPosition: 'bottom',
        zoomToFitWhenRefresh: true,
        layout: {
          layoutName: 'force',
          'force_line_elastic': 0.5
        },
        allowSwitchLineShape: true,
        allowSwitchJunctionPoint: true,
        defaultLineColor: 'rgba(0,0,0,0.5)',
        defaultNodeBorderWidth: 0,
        defaultNodeBorderColor: 'transpanret',
        defaultNodeFontColor: '#fff',
        defaultFocusRootNode: false
      },
      isLoading: false,
      errorMessage: '',
      nodes: [],
      edges: [],
      allData: { 'nodes': [], 'lines': [] }
    }
  },
  watch: {
    // 'graphData': {
    //   handler(val) {
    //     setTimeout(() => {
    //       this.setData()
    //     }, 100)
    //   },
    //   immediate: true,
    //   deep: true
    // }
  },
  mounted() {
    this.resizeTimer = setInterval(async() => {
      // const graphInstance = this.$refs.graphRef.getInstance();
      // await graphInstance.zoomToFit();
    }, 3000)
    // this.allData.nodes = []
    // this.allData.lines = []
    // const query = "MATCH path = (target:Archives {id: '0047B3542CE88B895E41DE'})-[rels:HAS_KEYWORD*1..4]-(related:Archives) WHERE target <> related UNWIND relationships(path) AS r WITH startNode(r) AS n, r, endNode(r) AS m, length(path)/2 AS depth RETURN DISTINCT n, r, m;"
    // this.fetchData(query)
    // this.showGraph()
  },
  beforeDestroy() {
    clearInterval(this.resizeTimer)
  },
  methods: {
    resetAllData() {
      this.allData = { 'nodes': [], 'lines': [] }
    },
    getOrigionGraphData(nodeId, id, tableName) {
      const parmas = {
        'searchKey': 'id',
        'searchValue': id,
        'tableName': tableName, // 节点名称
        'querySize': 10
      }
      FetchInitShowByCategory(parmas).then((res) => {
        this.graphData = res
        this.setData(this.graphData, nodeId)
      }).catch(err => {
        console.log(err)
      })
    },
    setData(data, selectedNodeId = null) {
      const { nodes, lines } = data
      // 档案Archives、档案门类Category、档案分类CategoryClass、全宗Fonds、关键词Keywords、保管期限Retention、保密期限SecrecyPeriod、密级SecurityClass
      const typeToTextMap = {
        Archives: '档案',
        Category: '档案门类',
        CategoryClass: '档案分类',
        Fonds: '全宗',
        Keywords: '关键词',
        Retention: '保管期限',
        SecrecyPeriod: '保密期限',
        SecurityClass: '密级'
      }
      const newNodes = nodes.map(item => {
        const newItem = {
          ...item,
          id: String(item.id),
          originId: item.properties.id,
          text: item.properties.title,
          type: item.labels[0]
        }
        const typeToColorMap = {
          Archives: '#0348F3',
          Category: '#14C9C9',
          CategoryClass: '#F8B722',
          Fonds: '#722ED1',
          Keywords: '#F4647B',
          Retention: '#018BFF',
          SecrecyPeriod: '#FEBD98',
          SecurityClass: '#B1EBDF'
        }

        const defaultColor = '#000000' // 默认颜色
        if (typeToColorMap[item.labels[0]]) {
          newItem.color = typeToColorMap[item.labels[0]]
          newItem.borderColor = typeToColorMap[item.labels[0]]
        } else {
          newItem.color = defaultColor
          newItem.borderColor = defaultColor
        }
        // 根据 type 给 newItem 加上 typeText
        newItem.typeText = typeToTextMap[newItem.type]

        return newItem
      })

      const newEdges = lines.map(item => {
        return {
          ...item,
          from: String(item.source),
          to: String(item.target),
          text: item.type
        }
      })

      const existingNodeIds = new Set(this.allData.nodes.map(node => node.id))
      const allNodesExist = newNodes.every(node => existingNodeIds.has(node.id))

      let validNewEdges = []
      let uniqueNewNodes = []
      if (!allNodesExist) {
        uniqueNewNodes = newNodes.filter(node => !existingNodeIds.has(node.id))
        const existingLineKeys = new Set(this.allData.lines.map(line => `${line.from}-${line.to}-${line.text}`))

        // 过滤掉 to 为选中节点及其关联节点的边
        if (selectedNodeId) {
          const relatedNodeIds = [selectedNodeId, ...this.getRelatedNodeIds(selectedNodeId)]
          validNewEdges = newEdges.filter(edge => {
            return !relatedNodeIds.includes(edge.to) && !existingLineKeys.has(`${edge.from}-${edge.to}-${edge.text}`)
          })
        } else {
          validNewEdges = newEdges.filter(edge => !existingLineKeys.has(`${edge.from}-${edge.to}-${edge.text}`))
        }
      }

      const originalNodesLength = this.allData.nodes.length
      const originalLinesLength = this.allData.lines.length

      this.allData.nodes = [...this.allData.nodes, ...uniqueNewNodes]
      this.allData.lines = [...this.allData.lines, ...validNewEdges]

      this.allData.nodes.sort((a, b) => {
        return parseInt(a.id) - parseInt(b.id)
      })

      // 判断数据是否有变化
      if (this.allData.nodes.length > originalNodesLength || this.allData.lines.length > originalLinesLength) {
        this.showGraph()
      } else {
        console.log('数据无变化，不更新图表')
      }
    },
    getRelatedNodeIds(nodeId) {
      return this.allData.lines
        .filter(line => line.from === nodeId || line.to === nodeId)
        .map(line => line.from === nodeId ? line.to : line.from)
    },
    async showGraph() {
      console.log('this.allData', this.allData)
      // const rootId = this.allData.nodes[0].id
      // this.allData.rootId = rootId

      const graphInstance = this.$refs.graphRef.getInstance()
      // await this.stopForceIfNeed()
      await graphInstance.setJsonData(this.allData)

      // setTimeout(async() => {
      //   await graphInstance.setZoom(100)
      //   await graphInstance.moveToCenter()
      //   await graphInstance.zoomToFit()
      // }, 1800)
    },
    async stopForceIfNeed() {
      const graphInstance = this.$refs.graphRef.getInstance()
      await graphInstance.stopAutoLayout()
    },
    async updateLayouterOptions() {
      await this.stopForceIfNeed()
      const graphInstance = this.$refs.graphRef.getInstance()
      graphInstance.layouter.maxLayoutTimes = this.graphOptions.layout.maxLayoutTimes
      graphInstance.layouter.force_node_repulsion = this.graphOptions.layout.force_node_repulsion
      graphInstance.layouter.force_line_elastic = this.graphOptions.layout.force_line_elastic
      setTimeout(async() => {
        await graphInstance.startAutoLayout()
      }, 500)
    },
    onNodeClick(nodeObject, $event) {
      console.log('this.allData', this.allData)
      console.log('节点数据:', nodeObject)
      const nodeId = nodeObject.id
      const targetNode = this.allData.nodes.find(node => node.id === nodeId)
      if (targetNode) {
        const originId = targetNode.originId
        console.log(originId)
        // this.$emit('getGraphData', originId, targetNode.type)
        this.getOrigionGraphData(nodeId, originId, targetNode.type)
      } else {
        console.log('未找到对应的节点')
      }

      // const query = `MATCH (n) WHERE id(n) = ${nodeId} MATCH (n)-[r]-(m) RETURN n, r,m;`
      // this.fetchData(query, nodeId)
      // console.log('query', query)
    },
    onCanvasClick($event) {
      const _all_nodes = this.$refs.graphRef.getInstance().getNodes()
      _all_nodes.forEach((thisNode) => {
        const _isHideThisNode = true
        thisNode.opacity = _isHideThisNode ? 1 : 0.1
      })
    },
    showNodeTips(nodeObject, $event) {
      this.currentNode = nodeObject

      const nodeId = nodeObject.id
      const targetNode = this.allData.nodes.find(node => node.id === nodeId)
      if (!targetNode) {
        console.error(`未找到 ID 为 ${nodeId} 的节点`)
        return
      }

      this.currentNode.typeText = targetNode.typeText

      const _base_position = this.$refs.graphRef.getInstance().options.fullscreen ? { x: 0, y: 0 } : this.$refs.myPage.getBoundingClientRect()
      this.isShowNodeTipsPanel = true
      this.nodeMenuPanelPosition.x = $event.clientX - _base_position.x + 10
      this.nodeMenuPanelPosition.y = $event.clientY - _base_position.y + 10
    },
    hideNodeTips(nodeObject, $event) {
      this.isShowNodeTipsPanel = false
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .rel-toolbar{
  color: #000;
  .c-current-zoom{
    color: #000;
  }
}

.c-my-rg-node {
  font-size: 13px;
  border-radius: 50%;
  cursor: pointer;
  height: 80px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.c-node-menu-item{
  line-height: 30px;
  padding-left: 10px;
  cursor: pointer;
  color: #444444;
  font-size: 14px;
  border-top:#efefef solid 1px;
}

.c-node-menu-item:hover{
  background-color: rgba(66,187,66,0.2);
}

.c-big-style{
  font-size: 30px;
}

::v-deep .c-rg-line-text{
  font-size: 10px !important;
}
</style>
