import { useState, useRef, useEffect, useCallback } from "react";
import { Cell, Graph, Node } from "@antv/x6";
import { Dnd } from "@antv/x6-plugin-dnd";
import { Transform } from "@antv/x6-plugin-transform";
import { Snapline } from "@antv/x6-plugin-snapline";
import { Clipboard } from "@antv/x6-plugin-clipboard";
import { Selection } from "@repo/x6-plugin-selection/src/index";
import { History } from "@antv/x6-plugin-history";
import { Keyboard } from "@antv/x6-plugin-keyboard";
import { Export } from "@antv/x6-plugin-export";
import { useModel } from "umi";
import "@/components/PageContainer";
import { handleGraphEvent, handleGraphApiEvent } from "@/events/flowEvent";
import { pageMenu, nodeMenu } from "@/utils/contentMenu";
import { bindKeys } from "./fastKey";
import { handleSetEdgeStyle } from "@/utils";
import { getDefaultDataByTheme } from "@/config/data";
import { getFlowNodeMetaByBasic, getFlowNodeMetaByAi } from "@/utils/flow";
export default function flowchartModel() {
  const [graph, setGraph] = useState<Graph>();
  const [dnd, setDnd] = useState<Dnd>();

  const pageNodeRef = useRef<Node>();
  const dndRef = useRef(dnd);
  const [updateKey, setUpdateKey] = useState(0);
  // 画布
  const graphRef = useRef<Graph>();
  const { pageState } = useModel("appModel");
  // 当前选中的节点
  const [selectedCell, setSelectedCell] = useState<Cell[]>([]);
  const [canRedo, setCanRedo] = useState(false);
  const [canUndo, setCanUndo] = useState(false);

  useEffect(() => {
    // 用于恢复历史后画布更新
    if (updateKey) {
      graphRef.current?.off("cell:added");
      graphRef.current?.off("cell:change:*");
      graphRef.current?.off("cell:removed");
      pageNodeRef?.current &&
        graphRef.current?.resetCells([pageNodeRef?.current]);
    }
  }, [updateKey]);
  const addPageNode = () => {
    const graph = graphRef.current;
    pageNodeRef.current = graph?.addNode({
      shape: "page-container-node",
      width: pageState.width,
      height: pageState.height,
      zIndex: -1,
      data: {
        isPage: true,
        ignoreDrag: true,
        ...pageState,
      },
      tools: [
        {
          name: "contextmenu",
          args: {
            menu: pageMenu,
          },
        },
      ],
    });
    return pageNodeRef.current;
  };

  // 初始化元素数据
  const initCells = (cells: Cell.Properties[], theme = "1") => {
    if (graphRef.current) {
      const defaultDataByTheme = getDefaultDataByTheme(theme);
      // 添加节点，可能节点数据不完整，需要合并默认数据
      const list = (cells || []).map((item) =>
        getFlowNodeMetaByBasic(item, defaultDataByTheme)
      );
      console.log('=====init cells:=======\n');
      graphRef.current.fromJSON({ cells: list as any });
      addPageNode();
      handleGraphApiEvent(graphRef.current);
      // graphRef.current?.centerContent();
    }
  };

  /**初始化页面节点 */
  useEffect(() => {
    if (pageState.width && graphRef.current && !pageNodeRef.current) {
      addPageNode();
    }
  }, [pageState.width, graphRef.current]);

  useEffect(() => {
    pageNodeRef.current?.setData({
      background: pageState.backgroundColor,
      ...pageState,
    });
    pageNodeRef.current?.setSize({
      width: pageState.width,
      height: pageState.height,
    });
  }, [pageState]);

  // 修改跨线展示
  useEffect(() => {
    const edges = graphRef.current?.getEdges();
    (edges || []).forEach((edge) => {
      handleSetEdgeStyle(edge, edge.data?.connectorType, pageState.jumpOver);
    });
  }, [pageState.jumpOver]);

  const enabledTransform = (node: Node) => {
    const data = node.getData<{ isPage: boolean; lock: boolean }>();
    return !data?.isPage && !data?.lock;
  };
  /**初始化画布 */
  const initGraph = (instance: Graph) => {
    // 添加插件
    instance
      .use(
        new Transform({
          resizing: {
            enabled: enabledTransform,
            minWidth: 20,
            minHeight: 20,
          },
          rotating: {
            enabled: enabledTransform,
            grid: 1,
          },
        })
      )
      .use(
        new Selection({
          enabled: true,
          multiple: true,
          rubberband: true,
          movable: true,
          showNodeSelectionBox: true,
          // showEdgeSelectionBox: true,
          pointerEvents: "none",
          strict: true,
          filter: (cell: Cell) => {
            const data = cell?.getData<{ isPage: boolean; lock: boolean }>();
            return !data?.isPage && !data?.lock;
          },
        })
      )
      .use(
        new Snapline({
          sharp: true,
          resizing: true,
        })
      )
      .use(
        new Keyboard({
          enabled: true,
          global: true,
        })
      )
      .use(new Clipboard())
      .use(
        new History({
          enabled: true,
          beforeAddCommand: (event, args) => {
            // @ts-ignore 排除不用创建的节点
            if (args?.cell?.data?.noCreate) return false;
            // @ts-ignore 排除页面节点
            return !(event === "cell:added" && args?.cell?.getData()?.isPage);
          },
        })
      )
      .use(new Export());

    setGraph(instance);
    graphRef.current = instance;

    // 选中的节点/边发生改变(增删)时触发
    instance.on(
      "selection:changed",
      ({ selected }: { added: Cell[]; removed: Cell[]; selected: Cell[] }) => {
        setSelectedCell(selected);
      }
    );

    instance.on("history:change", () => {
      setCanRedo(instance.canRedo());
      setCanUndo(instance.canUndo());
    });

    // 通用事件处理
    handleGraphEvent(instance);

    // 绑定快捷键
    bindKeys(instance);
  };

  /**初始化拖拽 */
  const initDnd = (instance: Dnd) => {
    setDnd(instance);
    dndRef.current = instance;
  };

  /**组件库拖拽生成 */
  const startDrag: (
    e: React.MouseEvent<HTMLDivElement, MouseEvent>,
    node: Node.Metadata
  ) => void = useCallback(
    (e, node) => {
      if (!dndRef.current || !graphRef.current) return;
      // 查找对应主题的默认数据
      const defaultDataByTheme = getDefaultDataByTheme(pageState.theme || "1");

      // 往画布添加节点
      const n = graphRef.current.createNode({
        ...node,
        data: {
          ...defaultDataByTheme.nodeDefaultData,
          ...node.data,
        },
        ports: node?.ports || defaultDataByTheme.ports,
      });

      // 右键菜单
      n.addTools({
        name: "contextmenu",
        args: {
          menu: nodeMenu,
        },
      });
      dndRef.current.start(n, e.nativeEvent as any);
    },
    [pageState.theme]
  );

  // 撤销
  const onUndo = () => {
    graphRef.current?.undo();
  };

  // 重做
  const onRedo = () => {
    graphRef.current?.redo();
  };

  // 添加AI的生成节点
  const handleAddNodeByAi: (data: any) => void = useCallback(
    (data) => {
      if(!graphRef.current || !data) return;

      graphRef.current?.cleanSelection();

      // 查找对应主题的默认数据
      const defaultDataByTheme = getDefaultDataByTheme(pageState.theme || "1");
      // 数组
      if(Array.isArray(data)) {
        const list = (data || []).map((item) =>
          getFlowNodeMetaByAi(item, defaultDataByTheme)
        );
        console.log('=====ai creator cells:=======\n', list);
        list.forEach((cell) => {
          if(cell.shape !== 'edge') {
            graphRef.current?.addNode(cell);
          }
          if(cell.shape === 'edge') {
            graphRef.current?.addEdge(cell);
          }
          graphRef.current?.select(graphRef.current?.getCellById(cell.id));
        });
      }
      // 对象
      if(data instanceof Object) {
        const cell = getFlowNodeMetaByAi(data, defaultDataByTheme);
        if(cell.shape !== 'edge') {
          graphRef.current?.addNode(cell);
        }
        if(cell.shape === 'edge') {
          graphRef.current?.addEdge(cell);
        }
        graphRef.current?.select(graphRef.current?.getCellById(cell.id));
      }
    },
    [pageState.theme, graphRef.current]
  );

  return {
    graph,
    dnd,
    initGraph,
    initDnd,
    startDrag,
    selectedCell,
    canRedo,
    canUndo,
    onUndo,
    onRedo,
    initCells,
    updateKey,
    setUpdateKey,
    handleAddNodeByAi,
  };
}
