import { devlog } from "@frontend/kitui";
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
import { Box, Button } from "@mui/material";
import { clearRuleForAll } from "@root/questions/actions";
import { useQuestionsStore } from "@root/questions/store";
import { updateRootContentId } from "@root/quizes/actions";
import { useCurrentQuiz } from "@root/quizes/hooks";
import {
  cleardragQuestionContentId,
  setModalQuestionParentContentId,
  setModalQuestionTargetContentId,
  updateOpenedModalSettingsId,
} from "@root/uiTools/actions";
import { useUiTools } from "@root/uiTools/store";
import type { Core } from "cytoscape";
import { enqueueSnackbar } from "notistack";
import { useEffect, useLayoutEffect, useMemo, useRef } from "react";
import CytoscapeComponent from "react-cytoscapejs";
import { withErrorBoundary } from "react-error-boundary";
import { DeleteNodeModal } from "../DeleteNodeModal";
import CsNodeButtons from "./CsNodeButtons";
import { addNode, layoutOptions, storeToNodes } from "./helper";
import { useRemoveNode } from "./hooks/useRemoveNode";
import "./style/styles.css";
import { stylesheet } from "./style/stylesheet";

function CsComponent() {
  const desireToOpenABranchingModal = useUiTools((state) => state.desireToOpenABranchingModal);
  const modalQuestionParentContentId = useUiTools((state) => state.modalQuestionParentContentId);
  const modalQuestionTargetContentId = useUiTools((state) => state.modalQuestionTargetContentId);
  const trashQuestions = useQuestionsStore((state) => state.questions);
  const cyRef = useRef<Core | null>(null);
  const { removeNode } = useRemoveNode({ cyRef });

  const csElements = useMemo(() => {
    const questions = trashQuestions.filter(
      (question): question is AnyTypedQuizQuestion => question.type !== null && question.type !== "result"
    );

    return storeToNodes(questions);
  }, [trashQuestions]);

  useLayoutEffect(() => {
    const cy = cyRef?.current;
    if (desireToOpenABranchingModal) {
      setTimeout(() => {
        cy?.getElementById(desireToOpenABranchingModal)?.data("eroticeyeblink", true);
      }, 250);
    } else {
      cy?.elements().data("eroticeyeblink", false);
    }
  }, [desireToOpenABranchingModal]);

  useEffect(() => {
    if (modalQuestionTargetContentId.length !== 0 && modalQuestionParentContentId.length !== 0) {
      if (!cyRef.current) return;

      addNode({
        parentNodeContentId: modalQuestionParentContentId,
        targetNodeContentId: modalQuestionTargetContentId,
      });
    }
    setModalQuestionParentContentId("");
    setModalQuestionTargetContentId("");
  }, [modalQuestionTargetContentId]);

  useEffect(function onMount() {
    updateOpenedModalSettingsId();
    document.addEventListener("pointerup", cleardragQuestionContentId);

    return () => {
      document.removeEventListener("pointerup", cleardragQuestionContentId);
    };
  }, []);

  useEffect(
    function rerunLayout() {
      cyRef.current?.layout(layoutOptions).run();
      cyRef.current?.fit(undefined, 70);
    },
    [csElements]
  );

  return (
    <>
      <Box mb="20px">
        <Button
          sx={{
            height: "27px",
            color: "#7E2AEA",
            textDecoration: "underline",
            fontSize: "16px",
          }}
          variant="text"
          onClick={() => {
            cyRef.current?.fit(undefined, 70);
          }}
        >
          Выровнять
        </Button>
      </Box>
      <Box
        sx={{
          position: "relative",
          height: "480px",
          background: "#F2F3F7",
        }}
      >
        <CytoscapeComponent
          wheelSensitivity={0.1}
          elements={csElements}
          style={{
            height: "100%",
            width: "100%",
            overflow: "hidden",
          }}
          stylesheet={stylesheet}
          layout={layoutOptions}
          cy={(cy) => {
            cyRef.current = cy;
          }}
          autoungrabify={true}
          autounselectify={true}
          boxSelectionEnabled={false}
        />
        <CsNodeButtons csElements={csElements} cyRef={cyRef} />
      </Box>
      <DeleteNodeModal removeNode={removeNode} />
    </>
  );
}

function Clear() {
  const quiz = useCurrentQuiz();
  if (quiz) {
    updateRootContentId(quiz?.id, "");
  }
  clearRuleForAll();
  return <></>;
}

export default withErrorBoundary(CsComponent, {
  fallback: <Clear />,
  onError: (error, info) => {
    enqueueSnackbar("Дерево порвалось");
    devlog(info);
    devlog(error);
  },
});
