"use client";

import { useCallback, useMemo } from "react";
import { useTranslations } from "next-intl";
import {
  ReactFlow,
  Background,
  Controls,
  MiniMap,
  type Node,
  type Edge,
  type NodeChange,
  type EdgeChange,
  type Connection,
  applyEdgeChanges,
  BackgroundVariant,
  Panel,
} from "@xyflow/react";
import "@xyflow/react/dist/style.css";
import { LayoutGrid } from "lucide-react";
import { Button } from "@/shared/components/ui/button";
import { useLessonPlanEditor } from "../hooks/use-lesson-plan-editor";
import { LessonNode } from "./nodes/lesson-node";
import { TextbookContentNode as TextbookContentNodeComponent } from "./nodes/textbook-content-node";
import { toRfNodes, toRfEdges } from "../lib/rf-mappers";
import { getNodeColor } from "../lib/node-summary";
import type { AnyLessonPlanNode, BlockType } from "../types";

const nodeTypes = {
  lesson: LessonNode,
  textbook_content: TextbookContentNodeComponent,
};

// NodeEditor 只负责画布交互，内容编辑由 NodeEditPanel 处理
type Props = Record<string, never>;

export function NodeEditor({}: Props) {
  const t = useTranslations("lessonPreparation");
  const {
    doc,
    selectedNodeId,
    updateNodePosition,
    removeNode,
    connect,
    selectNode,
    setEdges,
    addAnchor,
    addNode,
    autoLayout,
  } = useLessonPlanEditor();

  // V5-8：自动布局按钮
  const handleAutoLayout = useCallback(() => {
    autoLayout("TB");
  }, [autoLayout]);

  // P1-1：构建可锚定的教学节点列表（排除正文节点）
  const anchorableNodes = useMemo(
    () =>
      doc.nodes
        .filter((n): n is Extract<AnyLessonPlanNode, { type: BlockType }> => n.type !== "textbook_content")
        .map((n) => ({ id: n.id, title: n.title, type: n.type })),
    [doc.nodes],
  );

  // 锚点添加回调（正文节点使用）
  const handleAddRangeAnchor = useCallback(
    (params: { nodeId: string; start: number; end: number; textPreview: string }) => {
      // __selected__ 表示使用当前选中节点
      const actualNodeId =
        params.nodeId === "__selected__"
          ? selectedNodeId ?? ""
          : params.nodeId;
      if (!actualNodeId) return;
      addAnchor({
        nodeId: actualNodeId,
        type: "range",
        start: params.start,
        end: params.end,
        textPreview: params.textPreview,
      });
    },
    [addAnchor, selectedNodeId],
  );

  const handleAddPointAnchor = useCallback(
    (params: { nodeId: string; start: number }) => {
      const actualNodeId =
        params.nodeId === "__selected__"
          ? selectedNodeId ?? ""
          : params.nodeId;
      if (!actualNodeId) return;
      addAnchor({
        nodeId: actualNodeId,
        type: "point",
        start: params.start,
      });
    },
    [addAnchor, selectedNodeId],
  );

  // P1-1：创建新节点并锚定
  const handleCreateNewNode = useCallback(
    (params: {
      anchorType: "range" | "point";
      start: number;
      end?: number;
      textPreview?: string;
    }) => {
      // 默认创建 rich_text 节点（最通用的类型），用户可后续切换
      const newNodeId = addNode("rich_text", undefined, t("blockType.rich_text"));
      addAnchor({
        nodeId: newNodeId,
        type: params.anchorType,
        start: params.start,
        ...(params.end !== undefined ? { end: params.end } : {}),
        ...(params.textPreview ? { textPreview: params.textPreview } : {}),
      });
    },
    [addNode, addAnchor, t],
  );

  // 使用纯函数映射 nodes/edges
  const rfNodes: Node[] = useMemo(
    () =>
      toRfNodes(doc.nodes, selectedNodeId, {
        anchors: doc.anchors,
        selectedNodeId,
        anchorableNodes,
        onAddRangeAnchor: handleAddRangeAnchor,
        onAddPointAnchor: handleAddPointAnchor,
        onCreateNewNode: handleCreateNewNode,
        onSelectNode: selectNode,
      }),
    [doc.nodes, doc.anchors, selectedNodeId, anchorableNodes, handleAddRangeAnchor, handleAddPointAnchor, handleCreateNewNode, selectNode],
  );

  const rfEdges: Edge[] = useMemo(
    () => toRfEdges(doc.edges, selectedNodeId, doc.anchors, doc.nodes),
    [doc.edges, selectedNodeId, doc.anchors, doc.nodes],
  );

  const onNodesChange = useCallback(
    (changes: NodeChange[]) => {
      changes.forEach((change) => {
        if (change.type === "position" && change.position) {
          // 实时拖动：每次 position 变化都更新（不再等待 dragging=false）
          // 但仅在节点正在被拖动或拖动结束时更新
          updateNodePosition(change.id, change.position);
        } else if (change.type === "remove") {
          removeNode(change.id);
        } else if (change.type === "select") {
          selectNode(change.selected ? change.id : null);
        }
      });
    },
    [updateNodePosition, removeNode, selectNode],
  );

  const onConnect = useCallback(
    (conn: Connection) => {
      if (conn.source && conn.target) {
        connect(conn.source, conn.target);
      }
    },
    [connect],
  );

  // 同步 edges 变化（如拖拽重连）
  const onEdgesChangeSync = useCallback(
    (changes: EdgeChange[]) => {
      // 简单处理：删除时调用 disconnect
      const nextEdges = applyEdgeChanges(changes, rfEdges);
      const ourEdges = nextEdges.map((e) => {
        // 保留原有的 type 信息
        const original = doc.edges.find((oe) => oe.id === e.id);
        if (original?.type === "anchor") {
          return {
            id: e.id,
            source: e.source,
            target: e.target,
            sourceHandle: e.sourceHandle ?? null,
            targetHandle: e.targetHandle ?? null,
            type: "anchor" as const,
            anchorId: original.anchorId,
          };
        }
        return {
          id: e.id,
          source: e.source,
          target: e.target,
          sourceHandle: e.sourceHandle ?? null,
          targetHandle: e.targetHandle ?? null,
          type: "flow" as const,
        };
      });
      setEdges(ourEdges);
    },
    [rfEdges, setEdges, doc.edges],
  );

  return (
    <div
      className="w-full h-full relative"
      role="application"
      aria-label={t("editor.canvasLabel")}
      // 禁用整个画布的浏览器默认右键菜单
      onContextMenu={(e) => e.preventDefault()}
    >
      {doc.nodes.length === 0 && (
        <div className="absolute inset-0 flex items-center justify-center pointer-events-none z-10">
          <div className="text-center text-on-surface-variant">
            <p className="text-lg font-medium">{t("editor.canvasEmpty")}</p>
            <p className="text-sm mt-1">{t("editor.canvasEmptyHint")}</p>
          </div>
        </div>
      )}
      <ReactFlow
        nodes={rfNodes}
        edges={rfEdges}
        nodeTypes={nodeTypes}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChangeSync}
        onConnect={onConnect}
        onNodeClick={(_, node) => selectNode(node.id)}
        onPaneClick={() => selectNode(null)}
        fitView
        fitViewOptions={{ padding: 0.2, maxZoom: 1.2 }}
        nodesFocusable
        nodesDraggable
        edgesFocusable
        elementsSelectable
        panOnDrag
        zoomOnPinch
        zoomOnDoubleClick={false}
        selectionOnDrag={false}
        deleteKeyCode={["Backspace", "Delete"]}
        multiSelectionKeyCode={["Shift", "Meta", "Control"]}
        defaultEdgeOptions={{
          animated: true,
          style: { stroke: "#1976d2", strokeWidth: 2 },
        }}
        proOptions={{ hideAttribution: true }}
        className="bg-surface-container-low"
        onlyRenderVisibleElements
        minZoom={0.2}
        maxZoom={2.5}
        elevateNodesOnSelect={false}
      >
        <Background
          variant={BackgroundVariant.Dots}
          gap={20}
          size={1}
          color="#ccc"
        />
        <Controls className="!bg-surface !border-outline-variant" />
        {/* V5-8：自动布局按钮 */}
        <Panel position="top-right" className="!m-2">
          <Button
            variant="outline"
            size="sm"
            onClick={handleAutoLayout}
            disabled={doc.nodes.length === 0}
            title={t("editor.autoLayoutHint")}
            aria-label={t("editor.autoLayout")}
          >
            <LayoutGrid className="w-4 h-4 mr-1" />
            {t("editor.autoLayout")}
          </Button>
        </Panel>
        <MiniMap
          className="!bg-surface !border-outline-variant"
          nodeColor={(n) => {
            // V3 修复：从 React Flow 的 Node.data（Record<string, unknown>）安全提取 node 字段
            // 使用类型守卫替代 as 断言
            const data = n.data;
            if (!data || typeof data !== "object") return "#9e9e9e";
            const nodeData = data.node;
            if (
              nodeData &&
              typeof nodeData === "object" &&
              nodeData !== null &&
              "type" in nodeData &&
              typeof nodeData.type === "string"
            ) {
              return getNodeColor(nodeData.type);
            }
            return "#9e9e9e";
          }}
        />
      </ReactFlow>
    </div>
  );
}
