import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
import { devlog } from "@frontend/kitui";
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
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 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";
import { Box, useMediaQuery, useTheme } from "@mui/material";
import { InfoBanner } from "./InfoBanner/InfoBanner";
import { PositionControl } from "./PositionControl/PositionControl";
import { ZoomControl } from "./ZoomControl/ZoomControl";

function CsComponent() {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down(650));
  const [isBannerVisible, setBannerVisible] = useState(true);
  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
      sx={{
        width: "100%",
      }}
    >
      <CsNodeButtons csElements={csElements} cyRef={cyRef} />
      <Box sx={{ position: "relative" }}>
        {isBannerVisible && <InfoBanner setBannerVisible={setBannerVisible} />}
        <PositionControl cyRef={cyRef} />
        <ZoomControl cyRef={cyRef} />
        <CytoscapeComponent
          wheelSensitivity={0.1}
          elements={csElements}
          style={{
            height: isMobile ? "327px" : "481px",
            background: "#F2F3F7",
            overflow: "hidden",
            borderRadius: "12px",
            width: "100%",
          }}
          stylesheet={stylesheet}
          layout={layoutOptions}
          cy={(cy) => {
            cyRef.current = cy;
          }}
          autoungrabify={true}
          autounselectify={true}
          boxSelectionEnabled={false}
        />
      </Box>
      <DeleteNodeModal removeNode={removeNode} />
    </Box>
  );
}

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);
  },
});
