"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,
} from "@xyflow/react";
import "@xyflow/react/dist/style.css";
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 } 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,
    updateTextbookContent,
  } = useLessonPlanEditor();

  // 锚点添加回调（正文节点使用）
  const handleAddRangeAnchor = useCallback(
    (params: { nodeId: string; start: number; end: number; textPreview: string }) => {
      // 如果 nodeId 是 __selected__，使用当前选中节点
      // 如果是 __new__，提示用户先创建节点
      const actualNodeId =
        params.nodeId === "__selected__"
          ? selectedNodeId ?? ""
          : params.nodeId;
      if (!actualNodeId || actualNodeId === "__new__") {
        // 简化：不自动创建新节点，提示用户先选中或创建
        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 || actualNodeId === "__new__") {
        return;
      }
      addAnchor({
        nodeId: actualNodeId,
        type: "point",
        start: params.start,
      });
    },
    [addAnchor, selectedNodeId],
  );

  const handleZoomChange = useCallback(
    (zoom: number) => {
      updateTextbookContent({ zoom });
    },
    [updateTextbookContent],
  );

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

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

  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")}>
      {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
        deleteKeyCode={["Backspace", "Delete"]}
        multiSelectionKeyCode={["Shift", "Meta", "Control"]}
        defaultEdgeOptions={{
          animated: true,
          style: { stroke: "#1976d2", strokeWidth: 2 },
        }}
        proOptions={{ hideAttribution: true }}
        className="bg-surface-container-low"
      >
        <Background
          variant={BackgroundVariant.Dots}
          gap={20}
          size={1}
          color="#ccc"
        />
        <Controls className="!bg-surface !border-outline-variant" />
        <MiniMap
          className="!bg-surface !border-outline-variant"
          nodeColor={(n) => {
            const nodeData = (n.data as { node?: AnyLessonPlanNode }).node;
            if (!nodeData) return "#9e9e9e";
            return getNodeColor(nodeData.type);
          }}
        />
      </ReactFlow>
    </div>
  );
}
