import { cellStyle } from "@/types";
import { Cell, Edge, EventArgs, Graph, Node } from "@antv/x6";
import { message } from "antd";
import { useEffect, useMemo, useRef, useState } from "react";
import { Selection } from "@repo/x6-plugin-selection";
import { Keyboard } from "@antv/x6-plugin-keyboard";
import { Transform } from "@antv/x6-plugin-transform";
import { Scroller } from "@antv/x6-plugin-scroller";
import { Clipboard } from "@antv/x6-plugin-clipboard";
import { Export } from "@antv/x6-plugin-export";
import { MindMapProjectInfo } from "../interface";
import { bindMindMapEvents } from "../mindMapEvent";
import { renderMindMap } from "../render";
import { TopicType } from "@/enum";
import { isEqual, cloneDeep } from "lodash-es";
import { bindMindmapKeys } from "../fastKey";
import { handleCreateCorrelationEdge } from "../mindmapHander";
import { Dnd } from "@antv/x6-plugin-dnd";
import { EditGraph, BatchEditMindMapElement } from "@/api/systemDesigner";
import { create } from "zustand";
import { useHistoryTravel } from "ahooks";

class MindmapState {
  updateState: (para: Partial<MindmapState>) => void;
  reset: () => void;
  mindProjectInfo: MindMapProjectInfo;
  constructor() {
    this.updateState = () => {};
    this.reset = () => {};
    this.mindProjectInfo = new MindMapProjectInfo();
  }
}

const getInitState = () => {
  const { updateState, reset, ...rest } = new MindmapState();
  return {
    ...rest,
  };
};

export const useMindMapStore = create<MindmapState>((set) => {
  return {
    ...getInitState(),
    updateState: (para: Partial<MindMapProjectInfo>) =>
      set((state) => ({ ...state, ...para })),
    reset: () => set(getInitState()),
  };
});

export default function mindMapModel() {
  const [rightToobarActive, setRightToolbarActive] = useState<string>();
  // 格式刷启用
  const [enableFormatBrush, setEnableFormatBrush] = useState(false);
  // 格式刷样式
  const formatBrushStyle = useRef<cellStyle>();
  const graphRef = useRef<Graph>();
  const dndRef = useRef<Dnd>();
  const [graph, setGraph] = useState<Graph>();
  const [selectedCell, setSelectedCell] = useState<Cell[]>([]);
  const correlationEdgeRef = useRef<Edge>();
  const mindProjectInfo = useMindMapStore((state) => state.mindProjectInfo);

  const projectInfoRef = useRef<MindMapProjectInfo>();
  const timer = useRef<any>();
  const settingTimer = useRef<any>();
  const canLoadHistory = useRef(false); // 能否加载历史记录
  // 历史记录
  const {
    value: historyValue,
    setValue: setHistoryValue,
    backLength,
    forwardLength,
    back,
    forward,
    reset,
  } = useHistoryTravel<MindMapProjectInfo>(undefined, 20);

  /**
   * 更新项目信息
   * @param info 项目信息
   * @param init 是否初始化
   * @param ignoreRender 忽略渲染
   * @param ignoreHistory 忽略历史记录
   * @returns
   */
  const setMindProjectInfo = ({
    info,
    init,
    ignoreRender,
    ignoreHistory,
  }: {
    info: MindMapProjectInfo;
    init?: boolean;
    ignoreRender?: boolean;
    ignoreHistory?: boolean;
  }) => {
    console.log("设置数据：", JSON.parse(JSON.stringify(info)));
    console.log("init:", init);
    console.log("ignoreRender:", ignoreRender);
    console.log("ignoreHistory:", ignoreHistory);
    canLoadHistory.current = false;
    if (isEqual(info, projectInfoRef.current)) {
      return;
    }
    useMindMapStore.getState().updateState({
      mindProjectInfo: info,
    });

    // 初始化加载数据 清空画布
    if (init) {
      graph?.clearCells();
      reset(info);
      graph?.centerContent();
      setTimeout(() => {
        graph?.centerContent();
      }, 200);
    }

    if (!init && !isEqual(info?.topics, projectInfoRef.current?.topics)) {
      const graphId = sessionStorage.getItem("projectId");
      if (graphId && info?.topics) {
        // 清除定时器
        clearTimeout(timer.current);
        timer.current = setTimeout(() => {
          BatchEditMindMapElement(
            info.topics.map((topic) => {
              return {
                ...topic,
                parentId: null,
                graphId,
              };
            })
          );
        }, 500);
      }
    }

    const changeSetting = !isEqual(
      {
        ...info,
        topics: null,
      },
      {
        ...projectInfoRef.current,
        topics: null,
      }
    );

    // 配置更新
    if (changeSetting) {
      const pageSetting = info?.pageSetting;
      if (sessionStorage.getItem("projectId") && pageSetting) {
        settingTimer.current && clearTimeout(settingTimer.current);
        settingTimer.current = setTimeout(() => {
          EditGraph({
            id: sessionStorage.getItem("projectId"),
            ...pageSetting,
            structure: info?.structure,
            theme: info?.theme,
            langNameList: [
              {
                name: "zh-CN",
                value: info.name,
              },
            ],
          });
        }, 500);
      }
    }

    if (!ignoreRender && graphRef.current) {
      renderMindMap({
        graph: graphRef.current,
        setMindProjectInfo,
        pageSetting: info?.pageSetting,
        structure: info?.structure,
        theme: info?.theme,
        topics: info.topics,
      });
    }

    // 添加记录
    if (!ignoreHistory && !ignoreRender && !init) {
      setHistoryValue(info);
    }

    projectInfoRef.current = JSON.parse(JSON.stringify(info));
  };


  useEffect(() => {
    // 加载历史记录数据 根据撤销重做加载
    if (historyValue && canLoadHistory.current) {
      setMindProjectInfo({
        info: historyValue,
        ignoreHistory: true
      });
    }
  }, [historyValue]);

  const pageSettingRef = useRef<MindMapProjectInfo["pageSetting"]>();
  // 画布配置更新
  useEffect(() => {
    if (mindProjectInfo?.pageSetting && graph) {
      if (isEqual(pageSettingRef.current, mindProjectInfo?.pageSetting)) {
        return;
      }
      pageSettingRef.current = cloneDeep(
        mindProjectInfo?.pageSetting
      ) as MindMapProjectInfo["pageSetting"];
      const pageSetting = pageSettingRef.current;
      if (pageSetting?.backgroundType === "color") {
        graph.drawBackground({
          color: pageSetting?.backgroundColor,
        });
      } else {
        graph.drawBackground({
          image: pageSetting?.backgroundImage,
          repeat: "repeat",
        });
      }

      // 设置水印
      if (pageSetting.showWatermark && pageSetting.watermarkText) {
        const canvas = document.createElement("canvas");
        canvas.width = pageSetting.watermarkText.length * 16;
        canvas.height = 100;
        const ctx = canvas.getContext("2d");
        if (ctx) {
          ctx.fillStyle = "#aaa";
          ctx.font = "16px Arial";
          ctx.fillText(pageSetting.watermarkText, 1, 15);
        }
        const img = canvas.toDataURL();

        graph.drawBackground({
          image: img,
          repeat: "watermark",
        });
      }
    }
  }, [graph, mindProjectInfo?.pageSetting]);

  // 初始化脑图
  const initMindMap = (container: HTMLElement) => {
    const instance = new Graph({
      container,
      width: document.documentElement.clientWidth,
      height: document.documentElement.clientHeight,
      autoResize: true,
      async: false,
      mousewheel: {
        enabled: true,
        modifiers: "ctrl",
        minScale: 0.2,
        maxScale: 2,
      },
      connecting: {
        connectionPoint: "anchor",
      },
      interacting: {
        nodeMovable: (view) => {
          const data = view.cell.getData<{
            ignoreDrag: boolean;
            lock: boolean;
            type: TopicType;
            parentId: string;
            shadow: boolean;
            isSummary: boolean;
          }>();
          // 禁止拖拽或锁节点
          if (data?.ignoreDrag || data?.lock) return false;
          // 影子节点
          if (data?.shadow) return true;
          // 概要
          if (data?.isSummary) return false;
          // 自由节点
          return data?.type === TopicType.branch && !data?.parentId;
        },
      },
    });

    instance.use(new Selection());
    instance.use(new Keyboard());
    instance.use(new Clipboard());
    instance.use(new Export());
    instance.use(
      new Scroller({
        enabled: true,
        pannable: true,
      })
    );
    instance.use(
      new Transform({
        resizing: {
          enabled: true,
          orthogonal: true,
        },
      })
    );

    graphRef.current = instance;

    dndRef.current = new Dnd({
      target: instance,
      validateNode: () => {
        return false;
      },
    });

    // 绑定事件
    bindMindMapEvents(instance, setMindProjectInfo, setSelectedCell, dndRef);
    // 绑定键盘
    bindMindmapKeys(instance, setMindProjectInfo);
    // 绑定实例方法
    // @ts-ignore
    instance.extendAttr = {
      setRightToolbarActive,
      correlationEdgeRef,
      setMindProjectInfo,
    };

    setGraph(instance);
  };

  const handleBrushClick = (args: EventArgs & { cell: Cell }) => {
    // 取消格式刷
    if (!args?.cell || args?.cell?.data?.isPage) {
      formatBrushStyle.current = undefined;
      setEnableFormatBrush(false);
      graphRef.current?.off("cell:click", handleBrushClick);
      graphRef.current?.off("blank:click", handleBrushClick);
    } else {
      if (args.cell.data?.lock) return;
      // 应用格式刷
      const data = args.cell.data;
      args.cell.setData({
        text: formatBrushStyle.current?.text || data?.text,
        fill: formatBrushStyle.current?.fill || data?.fill,
        stroke: formatBrushStyle.current?.stroke || data?.stroke,
        opacity: formatBrushStyle.current?.opacity || data?.opacity,
      });
    }
  };

  // 开启格式刷
  const toggleFormatBrush = (graph: Graph) => {
    graphRef.current = graph;
    const cell = graph?.getSelectedCells()?.find((item) => item.isNode());
    setEnableFormatBrush((state) => {
      if (!state) {
        const data = cell?.getData();
        formatBrushStyle.current = data;
        message.info("格式刷已开启");
        graph.on("cell:click", handleBrushClick);
        graph.on("blank:click", handleBrushClick);
      } else {
        formatBrushStyle.current = undefined;
        graph.off("cell:click", handleBrushClick);
        graph.off("blank:click", handleBrushClick);
      }
      return !state;
    });
  };

  // 设置右侧工具激活项
  const rightToolbarActive = (type: string) => {
    setRightToolbarActive(rightToobarActive === type ? undefined : type);
  };

  // 撤销
  const onUndo = () => {
    canLoadHistory.current = true;
    back();
  };

  // 重做
  const onRedo = () => {
    canLoadHistory.current = true;
    forward();
  };

  const setCorrelationEdgeInfo = (sourceNode?: Node) => {
    graph && handleCreateCorrelationEdge(graph, correlationEdgeRef, sourceNode);
  };

  // 添加连接线
  const handleAddCorrelation = (source: Cell, target: Cell) => {
    const link = graph
      ?.createEdge({
        source: {
          cell: source.id,
          connectionPoint: "rect",
          anchor: "center",
        },
        target: {
          cell: target.id,
          connectionPoint: "rect",
          anchor: "center",
        },
        zIndex: 0,
        connector: "smooth",
        attrs: {
          line: {
            stroke: "#71cb2d",
            strokeWidth: 2,
          },
        },
        data: {
          isLink: true,
        },
        tools: ["vertices", "edge-editor", "button-remove"],
      })
      .toJSON();
    if (link) {
      source.setData({
        links: [...(source.data?.links || []), link],
      });
    }
  };

  useEffect(() => {
    if (graph) {
      graph.on("node:click", (args) => {
        if (correlationEdgeRef.current) {
          handleAddCorrelation(
            correlationEdgeRef.current.getSourceCell()!,
            args.node
          );
        }
      });
      graph.on("blank:click", () => {
        setTimeout(() => {
          setCorrelationEdgeInfo(undefined);
        }, 50);
      });
      graph.on("cell:click", () => {
        setTimeout(() => {
          setCorrelationEdgeInfo(undefined);
        }, 50);
      });
    }
  }, [graph]);

  return {
    graph,
    selectedCell,
    initMindMap,
    rightToobarActive,
    rightToolbarActive,
    setMindProjectInfo,
    canUndo: !!backLength,
    canRedo: !!forwardLength,
    onUndo,
    onRedo,
    enableFormatBrush,
    toggleFormatBrush,
    setCorrelationEdgeInfo,
  };
}
