<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { VueFlow, Handle, Position, type Node, Edge } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import { post, get } from "@/utils/request";
import { GET_STRUCT_BY_TABLE_NAME, GET_ALL_BUS_TABLE, GET_RELATE_TABLE_BY_FROM_COLUMN, GET_RELATE_BUS_TABLE_BY_FROM_TABLE } from "../api"

import '@vue-flow/core/dist/style.css';
import '@vue-flow/core/dist/theme-default.css';

interface selectedNode {
  id: string;
  data: any
}
const FixedConfiguration = {
  type: 'custom',
  style: {
    width: '120px', padding: '5px 20px', fontSize: '14px',
    border: '1px solid #dcdfe6', borderRadius: '8px'
  },
  sourcePosition: Position.Right,
  targetPosition: Position.Left,
  hidden: false
}
const fixedLabel = {
  selected: false, // 是否选中
}
const connectionType = 'step'
const nodes = ref<Node[]>([])
const edges = ref<Edge[]>([])
const clickedNodes = ref<selectedNode[]>([]) // 记录点击的节点
const selectNodes = ref<any[]>([]) // 记录选中的节点

const businessTableList = ref<optionType[]>([])
const businessObject = ref<any>({})

async function onNodeClick(event: any) {
  const { x, y } = event.node.position // 点击的位置
  const nodeId = event.node.id

  // 点击的节点Id
  const clickedNodesStr = clickedNodes.value.map(node => node.id)
  // 选中的节点Id
  const selectNodeIdList = selectNodes.value.map(node => node.id)
  // 点击长度相同的节点Id
  const clickedNodesLengthStr = clickedNodesStr.filter(strId => strId.length == nodeId.length)

  if (clickedNodesStr.includes(nodeId)) {
    if (selectNodeIdList.includes(nodeId)) {
      for (let i in selectNodeIdList) {
        if (nodeId !== selectNodeIdList[i] && nodeId.length === selectNodeIdList[i].length) {
          expandNode(selectNodeIdList[i], true)
        } else if (nodeId == selectNodeIdList[i]) {
          expandNode(nodeId, false)
        }
      }

      const notSelectedToDelete = clickedNodesLengthStr.filter(item => !selectNodeIdList.includes(item));
      for (let i in notSelectedToDelete) {
        deteleData(notSelectedToDelete[i])
      }
    }
  } else {
    clickedNodes.value.push({ id: nodeId, data: event.node.data })
    clickedNodesStr.push(nodeId)

    // 隐藏和删除其他节点
    const hiddenNode = clickedNodesLengthStr.filter(item => selectNodeIdList.includes(item))
    const deleteNode = clickedNodesLengthStr.filter(item => !selectNodeIdList.includes(item))

    hiddenNode.forEach(item => expandNode(item, true))
    deleteNode.forEach(item => deteleData(item))

    const eventData = event.node.data
    // console.log(eventData.id, '<==== id')
    // if(eventData.id) {
    const addData = await post(GET_RELATE_BUS_TABLE_BY_FROM_TABLE, { tableName: eventData.tblName })
    const fieldList = addData.data || []
    AddData(fieldList, x, y, nodeId)
    // }
    
    // if(!eventData.id) {
    //   const tableName = eventData.tblName
    //   const columnName = eventData.columnName
    //   const addData = await post(GET_RELATE_TABLE_BY_FROM_COLUMN, { tableName, columnName })
    //   console.log(addData, '<===== 返回的数据')
    // }
  }
}

// 处理级之间的联动勾选
function processSelectedNodes(nodeId: string) {
  const item = nodes.value.find(item => item.id === nodeId)
  if (item?.data?.selected) { // 选中状态将之前的节点选中
    const selectNodes = item.id.split('-').map((_: any, index: number, arr: any) => arr.slice(0, index + 1).join('-'));
    nodes.value = nodes.value.map(node => {
      if (selectNodes.includes(node.id)) {
        return {
          ...node,
          data: { ...node.data, selected: true }
        }
      } else {
        return node
      }
    })
  }

  if(!item?.data?.selected) {
    const cancelSelectNodes = nodes.value.filter(node => (node.id + '').indexOf((item?.id + '')) !== -1).map(node => node.id)
    nodes.value = nodes.value.map(node => {
      if (cancelSelectNodes.includes(node.id)) {
        return {
          ...node,
          data: { ...node.data, selected: false }
        }
      } else {
        return node
      }
    })
  }
  switchColors()
  changeEdgeStyle()
}

// 更改连线样式
function changeEdgeStyle() {
  const selectNodeIdList = selectNodes.value.map(node => node.id)
  edges.value = edges.value.map(edge => {
    const { source, target } = edge
    const isSelected = selectNodeIdList.includes(source) && selectNodeIdList.includes(target)
    return {
      ...edge,
      style: {
        ...edge.style,
        strokeWidth: isSelected ? 4 : 1,
        stroke: isSelected ? '#01517f' : '',
        class: isSelected ? 'high-z-index' : ''
      },
    }
  })
}

// 设置选中背景色
function switchColors() {
  selectNodes.value = nodes.value.filter(node => node.data.selected)
  nodes.value = nodes.value.map(node => ({
    ...node,
    style: {
      ...node.style,
      backgroundColor: node.data.selected ? '#01517f' : '#fff',
    },
  }))
}

// 添加节点和连线数据
function AddData(list: any[], x: number, y: number, nodeId: string) {
  const newNodes: Node[] = []
  const newEdges = [...edges.value]

  const spacing = 80
  const startY = y - (list.length * spacing) / 2

  list.forEach((item, index) => {
    const newNodeId = `${nodeId}-${index + 1}` // 生成唯一 ID
    const newY = startY + index * spacing

    newNodes.push({
      id: newNodeId,
      data: { label: item.fromColBusName, tblName: item.toTbl, ...item, ...fixedLabel, },
      position: { x: x + 240, y: newY },
      ...FixedConfiguration,
    })

    newEdges.push({
      id: `e${nodeId}-${newNodeId}`,
      source: nodeId,
      target: newNodeId,
      type: connectionType
    })
  })

  nodes.value = [...nodes.value, ...newNodes]
  edges.value = newEdges
}

// 删除节点和连线数据
function deteleData(nodeId: string) {
  clickedNodes.value = clickedNodes.value.filter(item => (item.id + '').indexOf(nodeId) === -1)
  nodes.value = nodes.value.filter(node => (node.id.indexOf(nodeId) > 0 || (node.id.indexOf(nodeId) === -1 || node.id === nodeId)))
  edges.value = edges.value.filter(edge => edge.source !== nodeId && edge.source.indexOf(nodeId) === -1)
}

// 展开收起节点
function expandNode(nodeId: string, val: boolean) {
  const filterNodes = nodes.value.filter(node => !(node.id.indexOf(nodeId) > 0 || (node.id.indexOf(nodeId) === -1 || node.id === nodeId))).map(item => item.id)
  nodes.value = nodes.value.map(node => {
    if (filterNodes.includes(node.id)) {
      return {
        ...node,
        hidden: val
      }
    } else {
      return node
    }
  })
}

// 获取所有业务对象
function getAllBusTable() {
  post(GET_ALL_BUS_TABLE, {}).then(res => {
    businessTableList.value = (res.data || []).map((item: any) => {
      return {
        label: item.name,
        value: item.id,
        ...item
      }
    })
  })
}

// 切换事件
function businessObjectSwitching(val: any) {
  const row = businessTableList.value.find((item: any) => item.id === val)
  nodes.value = [{ id: '1', data: { ...row, ...fixedLabel }, position: { x: 100, y: 50 },  ...FixedConfiguration }]
  edges.value = []
  clickedNodes.value = []
  selectNodes.value = []
}

// 新建初始化数据
function initData(row: any) {
  businessObject.value = row.id
  nodes.value = [{ id: '1', data: { ...row, ...fixedLabel }, position: { x: 100, y: 50 },  ...FixedConfiguration }]
  edges.value = []
  clickedNodes.value = []
  selectNodes.value = []
}

onMounted(() => {
  getAllBusTable()
})

// 向外暴露方法
defineExpose({
  initData,
});
</script>

<template>
  <div style="width: 100%; height: 100%;" class="relative">
    <!-- <div class="flex items-center absolute top-0 left-2 z-10">
      <div class="mr-2">业务对象：</div>
      <el-select v-model="businessObject" placeholder="请选择" style="width: 200px;" @change="businessObjectSwitching">
        <el-option v-for="item in businessTableList" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
    </div> -->
    <VueFlow :nodes="nodes" :edges="edges" @node-click="onNodeClick" fit-view-on-init :edge-updater-layer="true">
      <template #node-custom="{ data, id }">
        <div class="flex flex-row">
          <Handle class="handle left-handle" type="target" :position="Position.Left" :id="`${id}`" />
          <div class="flex items-center">
            <el-checkbox v-model="data.selected" size="large" @change="processSelectedNodes(id)" @click.stop
              class="pr-2 tops"></el-checkbox>
            <span :class="{ 'text-white': data.selected }">{{ data.label }}</span>
          </div>
          <Handle class="handle right-handle" type="source" :position="Position.Right" :id="`${id}`" />
        </div>
      </template>
      <Background />
    </VueFlow>
  </div>
</template>

<style lang='scss' scoped>
.tops {
  top: 2px
}

::deep(.vue-flow__node-custom) {
  position: relative;
}

.high-z-index {
  position: relative;
  z-index: 9999 !important;
  /* 提高连线层级 */
}
</style>