"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 { toRfNodes, toRfEdges } from "../lib/rf-mappers";
import { getNodeColor } from "../lib/node-summary";
import type { LessonPlanNode } from "../types";

const nodeTypes = { lesson: LessonNode };

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

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

  // 使用纯函数映射 nodes/edges
  const rfNodes: Node[] = useMemo(
    () => toRfNodes(doc.nodes, selectedNodeId),
    [doc.nodes, selectedNodeId],
  );

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

  const onNodesChange = useCallback(
    (changes: NodeChange[]) => {
      changes.forEach((change) => {
        if (change.type === "position" && change.position) {
          // 拖拽结束时（dragging: false）才写入最终位置，避免中间状态污染（修复 P1-1）
          if (change.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) => ({
        id: e.id,
        source: e.source,
        target: e.target,
        sourceHandle: e.sourceHandle ?? null,
        targetHandle: e.targetHandle ?? null,
      }));
      setEdges(ourEdges);
    },
    [rfEdges, setEdges],
  );

  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?: LessonPlanNode }).node;
            if (!nodeData) return "#9e9e9e";
            return getNodeColor(nodeData.type);
          }}
        />
      </ReactFlow>
    </div>
  );
}
