import React, { useEffect, useMemo, useRef } from "react";
import { useTranslation } from "react-i18next";
import CodeRoundedIcon from "@mui/icons-material/CodeRounded";
import { createToolFlow } from "@app/components/tools/shared/createToolFlow";
import { useBaseTool } from "@app/hooks/tools/shared/useBaseTool";
import type { BaseToolProps, ToolComponent } from "@app/types/tool";
import {
  useShowJSParameters,
  defaultParameters,
} from "@app/hooks/tools/showJS/useShowJSParameters";
import {
  useShowJSOperation,
  type ShowJSOperationHook,
} from "@app/hooks/tools/showJS/useShowJSOperation";
import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext";
import {
  useNavigationActions,
  useNavigationState,
} from "@app/contexts/NavigationContext";
import ShowJSView from "@app/components/tools/showJS/ShowJSView";
import { useFileSelection } from "@app/contexts/file/fileHooks";

const ShowJS = (props: BaseToolProps) => {
  const { t } = useTranslation();
  const { actions: navigationActions } = useNavigationActions();
  const navigationState = useNavigationState();

  const {
    registerCustomWorkbenchView,
    unregisterCustomWorkbenchView,
    setCustomWorkbenchViewData,
    clearCustomWorkbenchViewData,
  } = useToolWorkflow();

  const VIEW_ID = "showJSView";
  const WORKBENCH_ID = "custom:showJS" as const;
  const viewIcon = useMemo(() => <CodeRoundedIcon fontSize="small" />, []);

  const base = useBaseTool(
    "showJS",
    useShowJSParameters,
    useShowJSOperation,
    props,
    { minFiles: 1 },
  );
  const operation = base.operation as ShowJSOperationHook;
  const hasResults = Boolean(operation.scriptText);
  const { clearSelections } = useFileSelection();

  useEffect(() => {
    registerCustomWorkbenchView({
      id: VIEW_ID,
      workbenchId: WORKBENCH_ID,
      label: t("showJS.view.title", "JavaScript"),
      icon: viewIcon,
      component: ({ data }) => <ShowJSView data={data} />,
    });

    return () => {
      clearCustomWorkbenchViewData(VIEW_ID);
      unregisterCustomWorkbenchView(VIEW_ID);
    };
  }, [
    clearCustomWorkbenchViewData,
    registerCustomWorkbenchView,
    t,
    unregisterCustomWorkbenchView,
    viewIcon,
  ]);

  const lastShownRef = useRef<number | null>(null);

  useEffect(() => {
    if (operation.scriptText) {
      setCustomWorkbenchViewData(VIEW_ID, {
        scriptText: operation.scriptText,
        downloadUrl: operation.downloadUrl,
        downloadFilename: operation.downloadFilename,
      });
      const marker = operation.scriptText.length;
      const isNew =
        lastShownRef.current == null || marker !== lastShownRef.current;
      if (isNew) {
        lastShownRef.current = marker;
        if (
          navigationState.selectedTool === "showJS" &&
          navigationState.workbench !== WORKBENCH_ID
        ) {
          navigationActions.setWorkbench(WORKBENCH_ID);
        }
      }
    } else {
      clearCustomWorkbenchViewData(VIEW_ID);
      lastShownRef.current = null;
    }
  }, [
    clearCustomWorkbenchViewData,
    navigationActions,
    navigationState.selectedTool,
    navigationState.workbench,
    operation.scriptText,
    setCustomWorkbenchViewData,
  ]);

  useEffect(() => {
    if ((base.selectedFiles?.length ?? 0) === 0) {
      try {
        base.operation.resetResults();
      } catch {
        /* noop */
      }
      try {
        clearCustomWorkbenchViewData(VIEW_ID);
      } catch {
        /* noop */
      }
      if (navigationState.workbench === WORKBENCH_ID) {
        try {
          navigationActions.setWorkbench("fileEditor");
        } catch {
          /* noop */
        }
      }
      lastShownRef.current = null;
    }
  }, [
    base.selectedFiles?.length,
    base.operation,
    clearCustomWorkbenchViewData,
    navigationActions,
    navigationState.workbench,
  ]);

  return createToolFlow({
    files: {
      selectedFiles: base.selectedFiles,
      isCollapsed: false,
    },
    steps: [],
    executeButton: {
      text: hasResults
        ? t("back", "Back")
        : t("showJS.submit", "Extract JavaScript"),
      loadingText: t("loading", "Loading..."),
      onClick: hasResults
        ? async () => {
            // Clear results and deselect files so user can pick another file
            try {
              await base.operation.resetResults();
            } catch {
              /* noop */
            }
            try {
              clearSelections();
            } catch {
              /* noop */
            }
            // Close the custom JS view and send user back to file manager to pick another file
            try {
              clearCustomWorkbenchViewData(VIEW_ID);
            } catch {
              /* noop */
            }
            try {
              navigationActions.setWorkbench("fileEditor");
            } catch {
              /* noop */
            }
          }
        : base.handleExecute,
      disabled: hasResults
        ? false
        : !base.hasFiles ||
          (base.selectedFiles?.length ?? 0) !== 1 ||
          base.operation.isLoading ||
          base.endpointLoading ||
          base.endpointEnabled === false,
      isVisible: true,
    },
    review: {
      isVisible: hasResults,
      operation: base.operation,
      title: t("showJS.results", "Result"),
      onUndo: undefined,
    },
  });
};

const ShowJSTool = ShowJS as ToolComponent;
ShowJSTool.tool = () => useShowJSOperation;
ShowJSTool.getDefaultParameters = () => ({ ...defaultParameters });

export default ShowJSTool;
