"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { FolderOpenOutlined, NodeIndexOutlined, PictureOutlined, PlusOutlined } from "@ant-design/icons";
import { useWorkflowStore } from "@/store/workflowStore";
import { NodeType } from "@/types";
import { useReactFlow } from "@xyflow/react";
import { useI18n } from "@/i18n";
import { buildDefaultGenerationNodeData } from "@/utils/defaultGenerationNodeModel";
import { GenerateNodeMenu } from "./GenerateNodeMenu";
import { AssetLibraryDrawer } from "./AssetLibraryDrawer";
import { CanvasOutlineDrawer } from "./CanvasOutlineDrawer";
import { MyCreationPickerModal } from "./MyCreationPickerModal";
import { useFTUXStore, TutorialStep } from "@/store/ftuxStore";

// Get the center of the React Flow pane in screen coordinates
function getPaneCenter() {
  const pane = document.querySelector(".react-flow");
  if (pane) {
    const rect = pane.getBoundingClientRect();
    return {
      x: rect.left + rect.width / 2,
      y: rect.top + rect.height / 2,
    };
  }
  return { x: window.innerWidth / 2, y: window.innerHeight / 2 };
}

function GenerateComboButton() {
  const { t } = useI18n();
  const [isOpen, setIsOpen] = useState(false);
  const menuRef = useRef<HTMLDivElement>(null);
  const addNode = useWorkflowStore((state) => state.addNode);
  const selectSingleNode = useWorkflowStore((state) => state.selectSingleNode);
  const { screenToFlowPosition } = useReactFlow();

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
        setIsOpen(false);
      }
    };

    if (isOpen) {
      document.addEventListener("mousedown", handleClickOutside);
    }

    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [isOpen]);

  const handleAddNode = async (type: NodeType) => {
    const center = getPaneCenter();
    const position = screenToFlowPosition({
      x: center.x + Math.random() * 100 - 50,
      y: center.y + Math.random() * 100 - 50,
    });

    const nodeId = addNode(type, position, await buildDefaultGenerationNodeData(type));
    selectSingleNode(nodeId);
    setIsOpen(false);
  };

  const handleDragStart = (event: React.DragEvent, type: NodeType) => {
    event.dataTransfer.setData("application/node-type", type);
    event.dataTransfer.effectAllowed = "copy";
    setIsOpen(false);
  };

  return (
    <div className="relative" ref={menuRef}>
      <button
        onClick={() => setIsOpen(!isOpen)}
        title={t("toolbar.addNode")}
        aria-label={t("toolbar.addNode")}
        aria-expanded={isOpen}
        className="flex h-8 w-8 items-center justify-center rounded-lg bg-[var(--text-secondary)] text-[var(--text-inverse)] shadow-sm transition-colors hover:bg-[var(--text-primary)]"
      >
        <span className={`text-[18px] leading-none transition-transform duration-200 ${isOpen ? "rotate-45" : "rotate-0"}`}>
          <PlusOutlined />
        </span>
        <span className="sr-only">{t("toolbar.addNode")}</span>
      </button>

      {isOpen && (
        <GenerateNodeMenu
          draggable
          onSelect={handleAddNode}
          onDragStart={handleDragStart}
          className="absolute left-full top-0 ml-2 min-w-[140px] overflow-visible outline-none"
        />
      )}
    </div>
  );
}

function MyCreationButton() {
  const { t } = useI18n();
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button
        onClick={() => setIsOpen(true)}
        title={t("myCreation.title")}
        aria-label={t("myCreation.title")}
        className="flex h-8 w-8 items-center justify-center rounded-lg bg-[var(--surface-2)] text-[var(--text-secondary)] transition-colors hover:bg-[var(--surface-hover)] hover:text-[var(--text-primary)]"
      >
        <PictureOutlined className="text-[18px]" />
        <span className="sr-only">{t("myCreation.title")}</span>
      </button>

      {isOpen && <MyCreationPickerModal onClose={() => setIsOpen(false)} />}
    </>
  );
}

function AssetLibraryButton() {
  const { t } = useI18n();
  const [isAssetLibraryOpen, setIsAssetLibraryOpen] = useState(false);

  return (
    <>
      <button
        onClick={() => setIsAssetLibraryOpen(true)}
        title={t("assetLibrary.title")}
        aria-label={t("assetLibrary.title")}
        className="flex h-8 w-8 items-center justify-center rounded-lg bg-[var(--surface-2)] text-[var(--text-secondary)] transition-colors hover:bg-[var(--surface-hover)] hover:text-[var(--text-primary)]"
      >
        <FolderOpenOutlined className="text-[18px]" />
        <span className="sr-only">{t("assetLibrary.title")}</span>
      </button>

      <AssetLibraryDrawer
        open={isAssetLibraryOpen}
        onClose={() => setIsAssetLibraryOpen(false)}
      />
    </>
  );
}

function CanvasOutlineButton() {
  const { t } = useI18n();
  const [isOutlineOpen, setIsOutlineOpen] = useState(false);

  return (
    <>
      <button
        onClick={() => setIsOutlineOpen(true)}
        title={t("canvasOutline.title")}
        aria-label={t("canvasOutline.title")}
        className="flex h-8 w-8 items-center justify-center rounded-lg bg-[var(--surface-2)] text-[var(--text-secondary)] transition-colors hover:bg-[var(--surface-hover)] hover:text-[var(--text-primary)]"
      >
        <NodeIndexOutlined className="text-[18px]" />
        <span className="sr-only">{t("canvasOutline.title")}</span>
      </button>

      {isOutlineOpen && (
        <CanvasOutlineDrawer
          open={isOutlineOpen}
          onClose={() => setIsOutlineOpen(false)}
        />
      )}
    </>
  );
}

export function FloatingActionBar() {
  const { t } = useI18n();
  const nodes = useWorkflowStore((state) => state.nodes) ?? [];
  const isRunning = useWorkflowStore((state) => state.isRunning) ?? false;
  const currentNodeIds = useWorkflowStore((state) => state.currentNodeIds) ?? [];
  const executeWorkflow = useWorkflowStore((state) => state.executeWorkflow) ?? (async () => {});
  const regenerateNode = useWorkflowStore((state) => state.regenerateNode) ?? (async () => {});
  const executeSelectedNodes = useWorkflowStore((state) => state.executeSelectedNodes) ?? (async () => {});
  const stopWorkflow = useWorkflowStore((state) => state.stopWorkflow) ?? (() => {});
  const mockTutorialExecution = useWorkflowStore((state) => state.mockTutorialExecution) ?? (async () => {});
  const validateWorkflow = useWorkflowStore((state) => state.validateWorkflow);
  const edgeStyle = useWorkflowStore((state) => state.edgeStyle);
  const setEdgeStyle = useWorkflowStore((state) => state.setEdgeStyle);
  const [tutorialActive, setTutorialActive] = useState(false);
  const [currentTutorialStep, setCurrentTutorialStep] = useState(0);
  const [tutorialSteps, setTutorialSteps] = useState<TutorialStep[]>([]);
  const [runMenuOpen, setRunMenuOpen] = useState(false);
  const runMenuRef = useRef<HTMLDivElement>(null);
  const { valid, errors } = validateWorkflow?.() ?? { valid: true, errors: [] };

  useEffect(() => {
    const unsubscribe = useFTUXStore.subscribe((state) => {
      setTutorialActive(state.tutorialActive);
      setCurrentTutorialStep(state.currentTutorialStep);
      setTutorialSteps(state.tutorialSteps);
    });

    const currentState = useFTUXStore.getState();
    setTutorialActive(currentState.tutorialActive);
    setCurrentTutorialStep(currentState.currentTutorialStep);
    setTutorialSteps(currentState.tutorialSteps);

    return unsubscribe;
  }, []);

  const selectedNodes = useMemo(() => nodes.filter((node) => node.selected), [nodes]);
  const selectedNode = useMemo(() => selectedNodes.length === 1 ? selectedNodes[0] : null, [selectedNodes]);

  const isRunOptionsTutorialStep = useMemo(() => {
    if (!tutorialActive || tutorialSteps.length === 0) return false;
    const currentStep = tutorialSteps[currentTutorialStep];
    return currentStep?.id === "explain-run-options";
  }, [currentTutorialStep, tutorialActive, tutorialSteps]);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (runMenuRef.current && !runMenuRef.current.contains(event.target as Node) && !isRunOptionsTutorialStep) {
        setRunMenuOpen(false);
      }
    };

    if (runMenuOpen) {
      document.addEventListener("mousedown", handleClickOutside);
    }

    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [isRunOptionsTutorialStep, runMenuOpen]);

  useEffect(() => {
    if (isRunOptionsTutorialStep) {
      setRunMenuOpen(true);
    }
  }, [isRunOptionsTutorialStep]);

  useEffect(() => {
    if (!tutorialActive || tutorialSteps.length === 0) return;
    const currentStep = tutorialSteps[currentTutorialStep];
    if (
      currentStep?.id === "run-workflow" ||
      currentStep?.id === "demonstrate-downstream" ||
      currentStep?.id === "demonstrate-complete"
    ) {
      setRunMenuOpen(false);
    }
  }, [currentTutorialStep, tutorialActive, tutorialSteps]);

  const runningNodeCount = currentNodeIds.length;
  const getRunningLabel = useCallback(() => {
    if (runningNodeCount === 0) return t("toolbar.running");
    if (runningNodeCount === 1) {
      const node = nodes.find((item) => item.id === currentNodeIds[0]);
      const customTitle = node?.data?.customTitle;
      const nodeName = typeof customTitle === "string" || typeof customTitle === "number" ? customTitle : node?.type || "node";
      return t("toolbar.runningNode", { node: nodeName });
    }
    return t("toolbar.runningNodes", { count: runningNodeCount });
  }, [currentNodeIds, nodes, runningNodeCount, t]);

  const toggleEdgeStyle = () => {
    setEdgeStyle(edgeStyle === "angular" ? "curved" : "angular");
  };

  const handleRunClick = useCallback(() => {
    const ftuxState = useFTUXStore.getState();
    const currentStep = ftuxState.tutorialSteps[ftuxState.currentTutorialStep];

    if (isRunning) {
      stopWorkflow();
    } else if (ftuxState.tutorialActive && currentStep?.id === "run-workflow") {
      void mockTutorialExecution();
    } else {
      void executeWorkflow();
    }
  }, [executeWorkflow, isRunning, mockTutorialExecution, stopWorkflow]);

  const handleRunFromSelected = useCallback(() => {
    if (!selectedNode) return;
    void executeWorkflow(selectedNode.id);
    setRunMenuOpen(false);
  }, [executeWorkflow, selectedNode]);

  const handleRunSelectedOnly = useCallback(() => {
    if (!selectedNode) return;
    void regenerateNode(selectedNode.id);
    setRunMenuOpen(false);
  }, [regenerateNode, selectedNode]);

  const handleRunSelectedNodes = useCallback(() => {
    if (selectedNodes.length === 0) return;
    void executeSelectedNodes(selectedNodes.map((node) => node.id));
    setRunMenuOpen(false);
  }, [executeSelectedNodes, selectedNodes]);

  return (
    <div className="fixed left-5 top-1/2 z-50 -translate-y-1/2">
      <div className="flex flex-col items-center gap-2 rounded-2xl border border-[var(--border-subtle)] bg-[var(--surface-2)] px-1.5 py-1.5 shadow-[var(--shadow-panel)]">
        <GenerateComboButton />
        <CanvasOutlineButton />
        <AssetLibraryButton />
        <MyCreationButton />

        <button
          onClick={toggleEdgeStyle}
          title={t("toolbar.switchConnectors", { style: edgeStyle === "angular" ? t("toolbar.curved") : t("toolbar.angular") })}
          className="flex h-8 w-8 items-center justify-center rounded-lg bg-[var(--surface-2)] text-[var(--text-secondary)] transition-colors hover:bg-[var(--surface-hover)] hover:text-[var(--text-primary)]"
        >
          {edgeStyle === "angular" ? (
            <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M4 12h4l4-8 4 8h4" />
            </svg>
          ) : (
            <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M4 12c0 0 4-8 8-8s8 8 8 8" />
            </svg>
          )}
        </button>
      </div>
    </div>
  );
}
