import { FLOW_APP_TYPE, FLOW_NODE_TYPE_ENUM } from '@/utils/enum/flow';
import { ElMessage } from 'element-plus';
import { useNodeAttribute } from './nodeEvents';

/**
 * 校验流程合理性
 * @param cells
 */
export const getRelationNodeAndVerifyFlowFun = (cells: any, templateName: string, uuid: string) => {
  const { drawerVisible } = useNodeAttribute();
  // 关闭配置弹窗
  drawerVisible.value = false;
  // 清空选中工具效果
  for (let index = 0; index < cells.length; index++) {
    if (cells[index].shape === 'custom-app-vue-node') {
      cells[index].removeTools();
    }
  }
  const nodeArr = [];
  const edgeArr = [];
  for (let index = 0; index < cells.length; index++) {
    if (cells[index].shape === 'edge' || cells[index].shape === 'agent-edge') {
      edgeArr.push({
        target: cells[index].target.cell,
        source: cells[index].source.cell,
        id: cells[index].id,
      });
    }
    if (
      cells[index].shape === 'custom-app-vue-node' ||
      cells[index].shape === 'custom-local-vue-node'
    ) {
      nodeArr.push({
        ...cells[index].data,
        id: cells[index].id,
        shape: cells[index].shape,
      });
    }
  }
  if (!checkStartEndNode(nodeArr)) {
    return false;
  }
  const relationNode = sortNodeAndEdge(nodeArr, edgeArr);
  if (!relationNode) {
    return false;
  }
  const formatElementArr = formatNodeAndEdge(edgeArr, nodeArr);
  const formatElementOjb = {
    process: {
      id: uuid,
      name: templateName,
    },
    flowElements: formatElementArr,
  };
  return formatElementOjb;
};
const sortNodeAndEdge = (nodeArr: any, edgeArr: any) => {
  try {
    const startNode = nodeArr.find((item: any) => item.nodeType === FLOW_NODE_TYPE_ENUM.START);
    if (!startNode) {
      ElMessage.error('没有开始节点，无法闭环！');
      return;
    }
    // const endNode = nodeArr.find((item: any) => item.nodeType === FLOW_NODE_TYPE_ENUM.END);
    getNodeRelation(startNode, [startNode.id], nodeArr, edgeArr);
    const relationNode = startNode;

    const repeatNodeObj: any = {};
    for (let index = 0; index < edgeArr.length; index++) {
      if (!repeatNodeObj[edgeArr[index].target]) {
        repeatNodeObj[edgeArr[index].target] = [];
      }
      for (let j = 0; j < edgeArr.length; j++) {
        if (index !== j) {
          if (edgeArr[index].target === edgeArr[j].target) {
            repeatNodeObj[edgeArr[index].target].push(edgeArr[j].source);
          }
        }
      }
    }
    // 获取需要处理前置条件的节点，即多个节点指向当前节点
    const repeatNodeArr = [];

    for (const key in repeatNodeObj) {
      if (repeatNodeObj[key].length > 0) {
        repeatNodeArr.push({
          selfId: key,
          repeatIds: repeatNodeObj[key],
        });
      }
    }
    insertRepeatToNode([relationNode], repeatNodeArr, nodeArr);

    const includeIds: string[] = [];
    if (!verifyEndNode([relationNode], includeIds)) {
      return false;
    }
    if (includeIds.length !== nodeArr.length) {
      ElMessage.error('存在连接不完整的节点！');

      return false;
    }
    return relationNode;
  } catch {
    ElMessage.error('拖拽的流程存在循环，不符合规则！');
    return false;
  }
};

/**
 * 生成一个树结构的节点数据
 * @param preNode 上一个节点
 * @param includeNode 已包含的节点
 * @param nodeArr
 * @param edgeArr
 */
const getNodeRelation = (preNode: any, includeId: any, nodeArr: any, edgeArr: any) => {
  preNode.children = [];
  for (let index = 0; index < edgeArr.length; index++) {
    if (edgeArr[index].source === preNode.id) {
      const nextNode = nodeArr.find((item: any) => item.id === edgeArr[index].target);
      includeId.push(nextNode.id);
      getNodeRelation(nextNode, includeId, nodeArr, edgeArr);
      preNode.children.push(nextNode);
    }
  }
};

const insertRepeatToNode = (relationNode: any, repeatNodeArr: any, nodeArr: any) => {
  for (let index = 0; index < relationNode.length; index++) {
    for (let j = 0; j < repeatNodeArr.length; j++) {
      if (relationNode[index].id === repeatNodeArr[j].selfId) {
        relationNode[index].preNode = repeatNodeArr[j].repeatIds.map((item: any) => {
          return { ...nodeArr.find((node: any) => node.id === item), children: [] };
        });
      }
    }
    if (relationNode[index].children.length > 0) {
      insertRepeatToNode(relationNode[index].children, repeatNodeArr, nodeArr);
    }
  }
};

const verifyEndNode = (nodeArr: any, includeIds: string[]): boolean => {
  let isEnd = true;
  for (let index = 0; index < nodeArr.length; index++) {
    if (!includeIds.includes(nodeArr[index].id)) {
      includeIds.push(nodeArr[index].id);
    }
    if (nodeArr[index].children.length > 0) {
      if (isEnd) {
        isEnd = verifyEndNode(nodeArr[index].children, includeIds);
      }
    } else {
      if (nodeArr[index].nodeType !== FLOW_NODE_TYPE_ENUM.END) {
        ElMessage.error('拖拽的流程节点未形成闭环，不符合规则！');
        return false;
      }
    }
  }
  return isEnd;
};

const checkStartEndNode = (nodeArr: any) => {
  let startNum = 0;
  let endNum = 0;
  for (let index = 0; index < nodeArr.length; index++) {
    if (nodeArr[index].nodeType === FLOW_NODE_TYPE_ENUM.START) {
      startNum++;
    }
    if (nodeArr[index].nodeType === FLOW_NODE_TYPE_ENUM.END) {
      endNum++;
    }
  }
  if (startNum > 1 || endNum > 1) {
    ElMessage.error('开始或结束的节点数量不符合规则！');
    return false;
  }
  return true;
};

const formatNodeAndEdge = (edgeArr: any[], nodeArr: any[]) => {
  const edgeFormatArr: any = [];
  const nodeFormatArr: any = [];
  edgeArr.forEach((item: any) => {
    edgeFormatArr.push({
      id: item.id,
      type: 'sequenceFlow',
      sourceRef: item.source,
      targetRef: item.target,
    });
  });
  nodeArr.forEach((node: any) => {
    const formatItem: any = {
      id: node.id,
      type: node.type,
      nodeType: node.nodeType,
      name: node.label,
    };
    edgeArr.forEach((edge: any) => {
      if (node.id === edge.source) {
        formatItem['outgoingFlows'] = [edge.id];
      }
      if (node.id === edge.target) {
        formatItem['incomingFlows'] = [edge.id];
      }
    });
    formatItem['extensionElements'] = { executeConfig: {} };
    formatItem['extensionElements']['executeConfig'] = {
      type: '',
      inputFormat: node.inputFormat,
      outputFormat: node.outputFormat,
      beforeNodeId: node.beforeNodeId,
      // 默认是and条件
      nodeCondition: node.nodeCondition ? node.nodeCondition : 'and',
      exeCommand: node.exeCommand,
      // 默认是本地应用
      executeType: 'localApp',
      postScripts: node.postScripts,
      preScripts: node.preScripts,
      uuid: node.uuid,
      exeMethod: node.exeMethod,
    };

    if (node.nodeTypeValue === FLOW_APP_TYPE.LOCAL) {
      formatItem['extensionElements']['executeConfig'].type = 'localApp';
      formatItem['extensionElements']['executeConfig'].executeType = 'localApp';
    }
    if (node.nodeTypeValue === FLOW_APP_TYPE.CLOUD) {
      formatItem['extensionElements']['executeConfig'].type = 'cloudApp';
      formatItem['extensionElements']['executeConfig'].executeType = 'cloudApp';
    }
    if (node.nodeTypeValue === FLOW_APP_TYPE.HPC) {
      formatItem['extensionElements']['executeConfig'].type = 'HPC';
      formatItem['extensionElements']['executeConfig'].executeType = 'HPC';
      formatItem['extensionElements']['executeConfig'].waitUser = node.exeMethod !== 'serviceTask';
      formatItem['extensionElements']['executeConfig'].asyncCallback = true;
    } else {
      formatItem['extensionElements']['executeConfig'].asyncCallback = false;
    }
    if (node.nodeTypeValue === FLOW_APP_TYPE.SCRIPT_NODE) {
      formatItem['extensionElements']['executeConfig'].type = 'scriptNode';
      formatItem['extensionElements']['executeConfig'].executeType = 'exportWordScript';
    }

    if (node.nodeTypeValue === FLOW_APP_TYPE.HPC) {
      // HPC节点异步回调为true
      // formatItem.asyncCallback = true;
      // formatItem.waitUser = node.exeMethod === 'serviceTask';
      // HPC节点type为serviceTask
      formatItem.type = 'serviceTask';
    } else {
      // 非HPC节点异步回调为false
      // formatItem.asyncCallback = false;
      // 非HPC节点type为userTask
      formatItem.type = 'userTask';
    }

    if (node.nodeTypeValue === FLOW_APP_TYPE.SCRIPT_NODE) {
      formatItem.type = 'serviceTask';
    }

    delete formatItem['extensionElements']['executeConfig']['iconUrl'];
    delete formatItem['extensionElements']['executeConfig']['children'];
    delete formatItem['extensionElements']['executeConfig']['children'];

    if (formatItem.nodeType === FLOW_NODE_TYPE_ENUM.START) {
      formatItem.type = 'startEvent';
      delete formatItem['extensionElements'];
    }
    if (formatItem.nodeType === FLOW_NODE_TYPE_ENUM.END) {
      formatItem.type = 'endEvent';
      delete formatItem['extensionElements'];
    }

    delete formatItem.iconUrl;
    delete formatItem.pageConfigList;
    delete formatItem.children;
    delete formatItem.preNode;
    delete formatItem.nodeType;
    nodeFormatArr.push(formatItem);
  });
  return [...nodeFormatArr, ...edgeFormatArr];
};
