import { BorderSize, TopicType } from "@/enum";
import { addTopic, buildTopic } from "./render";
import { HierarchyResult, MindMapProjectInfo, TopicItem } from "@/types";
import { Cell, Graph, Node, Edge } from "@antv/x6";
import { message } from "antd";
import { cloneDeep } from "lodash-es";
import { uuid } from "@repo/utils";
import { ContextMenuTool } from "@/utils/contentMenu";
import { MutableRefObject } from "react";
import TopicBorder from "@/components/mindMap/Border";
import SummaryBorder from "@/components/mindMap/SummaryBorder";
import { openInsertImageModal } from "@/components/ImageModal";
import { BatchDeleteMindMapElement } from "@/api/systemDesigner";
import { useMindMapStore } from "./models/mindMapModel";

export const selectTopic = (graph: Graph, topic?: TopicItem) => {
  if (topic?.id) {
    setTimeout(() => {
      graph.resetSelection(topic.id);
      const node = graph.getCellById(topic?.id);
      node?.isNode() && graph.createTransformWidget(node);
    }, 100);
  }
};

export const selectTopics = (graph: Graph, topics?: TopicItem[]) => {
  setTimeout(() => {
    graph.resetSelection(topics?.map((item) => item.id));
    topics?.forEach((item) => {
      const node = graph.getCellById(item.id);
      node?.isNode() && graph.createTransformWidget(node);
    });
  }, 100);
};

/**
 * 添加同级主题
 * @param node
 * @param graph
 */
export const addPeerTopic = (
  node: Cell,
  graph: Graph,
  setMindProjectInfo?: (data: any) => void
) => {
  if (!setMindProjectInfo) return;

  const parentNode =
    node.data.type === TopicType.main || !node.data?.parentId
      ? node
      : graph.getCellById(node.data.parentId);
  const type =
    node.data.type === TopicType.main ? TopicType.branch : node.data.type;
  if (parentNode?.isNode()) {
    const topic = addTopic(type, setMindProjectInfo, graph, parentNode);

    selectTopic(graph, topic);
  }
};

/**
 * 添加子主题
 * @param node
 * @param setMindProjectInfo
 * @param graph
 */
export const addChildrenTopic = (
  node: Node,
  graph: Graph,
  setMindProjectInfo?: (data: any) => void,
) => {
  if (!setMindProjectInfo) return;

  const type =
    node.data?.type === TopicType.main ? TopicType.branch : TopicType.sub;
  const topic = addTopic(type, setMindProjectInfo, graph, node);
  graph && selectTopic(graph, topic);
};

/**
 * 添加父主题
 * @param node
 * @param setMindProjectInfo
 * @param graph
 */
export const addParentTopic = (
  node: Node,
  setMindProjectInfo: (data: any) => void,
  graph: Graph
) => {
  if (!setMindProjectInfo || !node.data?.parentId) return;

  const type =
    node.data?.type === TopicType.branch ? TopicType.branch : TopicType.sub;
  const parentNode = graph?.getCellById(node.data.parentId);
  // 删除原来的数据
  deleteTopics([node.data.id], graph, setMindProjectInfo);
  // 加入新的父主题
  const topic = addTopic(type, setMindProjectInfo, graph, parentNode as Node, {
    children: [
      {
        ...node.data,
      },
    ],
  });
  graph && selectTopic(graph, topic);
};

/**
 * 删除子主题
 * @param ids
 * @param setMindProjectInfo
 */
export const deleteTopics = (
  ids: string[],
  graph: Graph,
  setMindProjectInfo?: (data: any) => void
) => {
  const mindProjectInfo: MindMapProjectInfo = cloneDeep(useMindMapStore.getState().mindProjectInfo);
  if (!mindProjectInfo || !setMindProjectInfo) return;
  const topics = cloneDeep(mindProjectInfo.topics);
  const deleteIds: string[] = [];
  console.log(ids, graph, topics)
  const filterTopics = (list: TopicItem[]): TopicItem[] => {
    const result: TopicItem[] = [];
    for (const item of list) { 
      if(ids.includes(item.id) && item.type === TopicType.main) {
        item.children = [];
      }
      if (!ids.includes(item.id) || item.type === TopicType.main) {
        if (item.children?.length) {
          item.children = filterTopics(item.children);
        }
        result.push(item);
      } else {
        if(!item.parentId && !item.isSummary) {
          // 删除自由主题
          deleteIds.push(item.id);
        }
      }
    }
    return result;
  };

  mindProjectInfo.topics = filterTopics(topics);
  if(deleteIds.length) {
    BatchDeleteMindMapElement({ids: deleteIds});
  }

  setMindProjectInfo({info: mindProjectInfo});
};

/**
 * 删除当前主题
 * @param graph
 * @param nodes
 */
export const handleDeleteCurrentTopic = (graph: Graph, nodes: Node[]) => {
  const mindProjectInfo: MindMapProjectInfo = cloneDeep(useMindMapStore.getState().mindProjectInfo);
  if (!mindProjectInfo) return;

  nodes.forEach((node) => {
    if (node.data.parentId) {
      traverseNode(mindProjectInfo.topics, (topic) => {
        if (topic.id === node.data.parentId) {
          const index = topic.children?.findIndex(
            (item) => item.id === node.id
          );
          if (typeof index === "number" && index >= 0) {
            const newChildren = (node.data.children || []).map(
              (childNode: TopicItem) => {
                return {
                  ...childNode,
                  type:
                    topic.type === TopicType.main
                      ? TopicType.branch
                      : TopicType.sub,
                  parentId: topic.id,
                };
              }
            );
            (topic.children || []).splice(index, 1, ...newChildren);
          }
        }
      });
    }

    // @ts-ignore
    graph?.extendAttr?.setMindProjectInfo?.(mindProjectInfo);
    localStorage.setItem("minMapProjectInfo", JSON.stringify(mindProjectInfo));
  });
};

/**
 * 执行粘贴
 * @param graph
 * @param setMindProjectInfo
 */
export const handleMindmapPaste = (
  graph: Graph,
  setMindProjectInfo: (data: any) => void
) => {
  // 读取剪切板数据
  navigator.clipboard.read().then((items) => {
    console.log("剪切板内容：", items);
    const currentNode = graph.getSelectedCells().find((cell) => cell.isNode());
    if (!currentNode) {
      message.warning("请先选择一个主题");
      return;
    }
    const item = items?.[0];
    if (item) {
      /**读取图片数据 */
      if (item.types[0] === "image/png") {
        item.getType("image/png").then((blob) => {
          const reader = new FileReader();
          reader.readAsDataURL(blob);
          reader.onload = function (event) {
            const dataUrl = event.target?.result as string;
            // 获取图片大小
            const img = new Image();
            img.src = dataUrl;
            img.onload = function () {
              const width = img.width;
              const height = img.height;
              // 插入图片
              currentNode.setData({
                extraModules: {
                  type: "image",
                  data: {
                    imageUrl: dataUrl,
                    width,
                    height,
                  },
                },
              });
            };
          };
        });
      }
      /**读取文本数据 */
      if (item.types[0] === "text/plain") {
        item.getType("text/plain").then((blob) => {
          const reader = new FileReader();
          reader.readAsText(blob);
          reader.onload = function (event) {
            const text = event.target?.result as string;
            // 内部复制方法
            if (text === "  ") {
              const nodes = localStorage.getItem("mindmap-copy-data");
              if (nodes) {
                JSON.parse(nodes)?.forEach((node: Node) => {
                  const data = node.data;
                  // 修改新的数据嵌套
                  data.id = uuid();
                  data.parentId = currentNode.id;
                  if (data.children?.length) {
                    data.children = traverseCopyData(data.children, data.id);
                  }

                  addTopic(
                    currentNode.data?.type === TopicType.main
                      ? TopicType.branch
                      : TopicType.sub,
                    setMindProjectInfo,
                    graph,
                    currentNode,
                    { label: data.label, children: data.children, }
                  );
                });
              }
            } else {
              // 根据空格或者换行切分
              const labels = text.split("\n").map(txt => txt.trim().split(" ")).flat();
              labels.forEach(label => {
                if(label.trim()) {
                  const topic = addTopic(
                    currentNode.data?.type === TopicType.main
                      ? TopicType.branch
                      : TopicType.sub,
                    setMindProjectInfo,
                    graph,
                    currentNode,
                    { label: label.trim() }
                  );
                  selectTopic(graph, topic);
                }
              });
            }
          };
        });
      }
    }
  });
};

const traverseCopyData = (list: TopicItem[], parentId: string): TopicItem[] => {
  return list.map((item) => {
    item.id = uuid();
    item.parentId = parentId;
    if (item.children?.length) {
      item.children = traverseCopyData(item.children, item.id);
    }
    return item;
  });
};

/**
 * 遍历主题树
 * @param topics
 * @param callback
 * @returns
 */
export const traverseNode = (
  topics: TopicItem[],
  callback: (topic: TopicItem, index: number, level?: number) => void,
  level = 0
): TopicItem[] => {
  return topics.map((topic, index) => {
    callback && callback(topic, index, level);
    if (topic.children?.length) {
      topic.children = traverseNode(topic.children, callback, level + 1);
    }
    // 遍历概要
    if (topic?.summary?.topic) {
      topic.summary.topic = traverseNode([topic.summary.topic], callback)[0];
    }
    return topic;
  });
};

// 关联线
const handleCorrelation = (
  e: MouseEvent,
  correlationEdgeRef: MutableRefObject<Edge | undefined>,
  graph: Graph
) => {
  if (correlationEdgeRef.current) {
    const point = graph?.clientToLocal(e.x, e.y);
    point && correlationEdgeRef.current?.setTarget(point);
  }
};
/**
 * 添加关联线
 * @param graph
 * @param correlationEdgeRef
 * @param sourceNode
 */
export const handleCreateCorrelationEdge = (
  graph: Graph,
  correlationEdgeRef: MutableRefObject<Edge | undefined>,
  sourceNode?: Node
) => {
  if (sourceNode) {
    correlationEdgeRef.current = graph?.addEdge({
      source: { cell: sourceNode },
      target: {
        x: sourceNode.position().x,
        y: sourceNode.position().y,
      },
      connector: "normal",
      attrs: {
        line: {
          stroke: "#71cb2d",
          strokeWidth: 2,
          sourceMarker: {
            name: "",
          },
          targetMarker: {
            name: "",
          },
          style: {
            opacity: 0.6,
          },
        },
      },
      data: {
        ignoreDrag: true,
      },
      zIndex: 0,
    });
    document.body.addEventListener("mousemove", (e) =>
      handleCorrelation(e, correlationEdgeRef, graph)
    );
  } else {
    document.body.removeEventListener("mousemove", (e) =>
      handleCorrelation(e, correlationEdgeRef, graph)
    );
    if (correlationEdgeRef.current) {
      graph?.removeCell(correlationEdgeRef.current);
      correlationEdgeRef.current = undefined;
    }
  }
};

export const addBorder = (nodes: Node[]) => {
  // 判断节点是否在当前存在父级以上节点
  nodes.forEach((node) => {
    let hasParent = false;
    traverseNode(node.data.children || [], (child) => {
      if (child.id === node.id) {
        hasParent = true;
      }
    });

    // 添加边框数据
    if (!hasParent && !node.data.border) {
      node.setData({
        border: {
          ...TopicBorder.data,
        },
      });
    }
  });
};

/**
 * 计算当前节点总大小
 * @param topItem 
 * @param children 
 * @returns 
 */
export const cacluculateExtremeValue = (topItem: HierarchyResult, children: HierarchyResult[]) => {
  let minX = topItem.x;
  let minY = topItem.y;
  let maxX = minX + topItem.data.width;
  let maxY = minY + topItem.data.height;
  children.forEach((child) => {
    const childXY = cacluculateExtremeValue(child, child.children);
    minX = Math.min(minX, child.x, childXY.minX);
    minY = Math.min(minY, child.y, childXY.minY);
    maxX = Math.max(maxX, child.x + child.data.width, childXY.maxX);
    maxY = Math.max(maxY, child.y + child.data.height, childXY.maxY);
  });

  return {
    minX,
    minY,
    maxX,
    maxY
  }
};

/**
 * 获取边框位置及大小
 * @param hierarchyItem
 * @returns
 */
export const getBorderPositionAndSize = (hierarchyItem: HierarchyResult) => {
  const firstChild = hierarchyItem?.children?.[0];
  let totalHeigth = hierarchyItem?.totalHeight || 0;
  let totalWidth = hierarchyItem?.totalWidth || 0;
  let x = hierarchyItem?.x || 0;
  let y = hierarchyItem?.y || 0;

  // 是否存在子节点
  if (firstChild) {
    const position = cacluculateExtremeValue(hierarchyItem, hierarchyItem.children || []);
    x = position.minX;
    y = position.minY;
    totalHeigth = position.maxY - position.minY;
    totalWidth = position.maxX - position.minX;
  } else {
    totalWidth = hierarchyItem.data.width;
    totalHeigth = hierarchyItem.data.height;
  }
  return {
    x: x - 10,
    y: y - 10,
    width: totalWidth + 20,
    height: totalHeigth + 20,
  };
};

/**
 * 添加概要
 */
export const addSummary = (nodes: Node[], graph: Graph) => {
  // 判断节点是否在当前存在父级以上节点
  nodes.forEach((node) => {
    let hasParent = false;
    traverseNode(node.data.children || [], (child) => {
      if (child.id === node.id) {
        hasParent = true;
      }
    });
    // 添加边框数据
    if (!hasParent && !node.data.summary) {
      const root = buildTopic(node.data.type, {
        setMindProjectInfo: node.data.setMindProjectInfo,
        type: TopicType.branch,
        label: "概要",
        borderSize: BorderSize.medium,
        isSummary: true,
        summarySource: node.id,
      }, graph);
      node.setData({
        summary: {
          topic: root,
          range: [node.id],
          border: {
            ...SummaryBorder.data,
            origin: root.id,
            summarySource: node.id,
          }
        }
      }, {
        deep: false
      });
    }
  });
}

/**
 * 插入图片
 */
export const insertImage = (node?: Node) => {
  if(!node) return;

  openInsertImageModal((url) => {
    console.log('图片地址：', url);
    node.setData({
      extraModules: {
        type: "image",
        data: {
          imageUrl: url,
          width: 300,
          height: 300
        }
      }
    })
  })
}

/**
 * 右键菜单处理方法
 */
export const mindmapMenuHander = {
  addTopic(tool: ContextMenuTool) {
    const node = tool.cell;
    if (node.isNode())
      addChildrenTopic(node, tool.graph, node.data.setMindProjectInfo,);
  },
  addPeerTopic(tool: ContextMenuTool) {
    const node = tool.cell;
    if (node.isNode())
      addPeerTopic(node, tool.graph, node.data.setMindProjectInfo);
  },
  addParentTopic(tool: ContextMenuTool) {
    const node = tool.cell;
    if (node.isNode())
      addParentTopic(node, node.data.setMindProjectInfo, tool.graph);
  },
  addCorrelationEdge(tool: ContextMenuTool) {
    if (tool.cell.isNode()) {
      // @ts-ignore
      const correlationEdgeRef = tool.graph?.extendAttr?.correlationEdgeRef;
      handleCreateCorrelationEdge(tool.graph, correlationEdgeRef, tool.cell);
    }
  },
  addRemark(tool: ContextMenuTool) {
    // @ts-ignore
    tool.graph?.extendAttr?.setRightToolbarActive("remark");
    selectTopic(tool.graph, tool.cell.data);
  },
  addHref(tool: ContextMenuTool) {
    // @ts-ignore
    tool.cell?.extendAttr?.showHrefConfig?.();
  },
  addTopicLink(tool: ContextMenuTool) {
    // todo
  },
  addImage(tool: ContextMenuTool) {
    const cell = tool.cell;
    cell.isNode() && insertImage(cell);
  },
  addTag(tool: ContextMenuTool) {
    // @ts-ignore
    tool.graph?.extendAttr?.setRightToolbarActive("tag");
    selectTopic(tool.graph, tool.cell.data);
  },
  addIcon(tool: ContextMenuTool) {
    // @ts-ignore
    tool.graph?.extendAttr?.setRightToolbarActive("icon");
    selectTopic(tool.graph, tool.cell.data);
  },
  addCode(tool: ContextMenuTool) {
    tool.cell.setData({
      extraModules: {
        type: "code",
        data: {
          code: "",
          language: "javascript",
        },
      },
    });
  },
  chooseSameLevel(tool: ContextMenuTool) {
    const parentId = tool.cell.data?.parentId;
    if (!parentId) return;
    const parent = tool.graph.getCellById(parentId);
    selectTopics(tool.graph, parent.data?.children);
  },
  chooseAllSameLevel(tool: ContextMenuTool) {
    // todo
  },
  copy(tool: ContextMenuTool) {
    localStorage.setItem("mindmap-copy-data", JSON.stringify([tool.cell]));
    navigator.clipboard.writeText("  ");
  },
  cut(tool: ContextMenuTool) {
    // tool.graph.cut([tool.cell]);
    localStorage.setItem("mindmap-copy-data", JSON.stringify([tool.cell]));
    deleteTopics([tool.cell.id], tool.graph, tool.cell.data.setMindProjectInfo);
    navigator.clipboard.writeText("  ");
  },
  paste(tool: ContextMenuTool) {
    handleMindmapPaste(tool.graph, tool.cell.data.setMindProjectInfo);
  },
  delete(tool: ContextMenuTool) {
    deleteTopics([tool.cell.id], tool.graph, tool.cell.data.setMindProjectInfo);
  },
  deleteCurrent(tool: ContextMenuTool) {
    tool.cell.isNode() && handleDeleteCurrentTopic(tool.graph, [tool.cell]);
  },
  exportImage(tool: ContextMenuTool) {
    tool.graph.exportPNG("", {
      quality: 1,
      copyStyles: false,
    });
  },
  copyImage(tool: ContextMenuTool) {
    // TODO复制为图片
  },
};
