import type { Node, Edge } from "@xyflow/react";
import type {
  AnyLessonPlanEdge,
  AnyLessonPlanNode,
  NodeAnchor,
} from "../types";
import { getNodeColor } from "./node-summary";

/**
 * 纯函数：根据 nodeId 从节点列表中查找节点类型。
 * P0-8 修复：toRfEdges 需要节点类型来获取颜色，而非传入 nodeId。
 */
function getNodeTypeById(
  nodes: AnyLessonPlanNode[],
  nodeId: string,
): string {
  const node = nodes.find((n) => n.id === nodeId);
  return node?.type ?? "rich_text";
}

/**
 * 纯函数：将课案 nodes/edges 映射为 React Flow 格式。
 * 从 node-editor.tsx 抽取，便于单元测试。
 *
 * v3 升级：
 * - 区分教学节点（type="lesson"）和正文节点（type="textbook_content"）
 * - 正文节点传入 anchors/selectedNodeId/onAddAnchor 等回调
 * - 边区分 anchor/flow 类型，应用不同透明度
 */

export interface ToRfNodesContext {
  anchors: NodeAnchor[];
  selectedNodeId: string | null;
  /** 可锚定的教学节点列表（P1-1：用于节点选择器）*/
  anchorableNodes?: { id: string; title: string; type: string }[];
  onAddRangeAnchor?: (params: {
    nodeId: string;
    start: number;
    end: number;
    textPreview: string;
  }) => void;
  onAddPointAnchor?: (params: {
    nodeId: string;
    start: number;
  }) => void;
  /** 创建新节点并锚定（P1-1）*/
  onCreateNewNode?: (params: {
    anchorType: "range" | "point";
    start: number;
    end?: number;
    textPreview?: string;
  }) => void;
  onSelectNode?: (id: string | null) => void;
}

export function toRfNodes(
  nodes: AnyLessonPlanNode[],
  selectedNodeId: string | null,
  ctx?: ToRfNodesContext,
): Node[] {
  // 当有选中节点时，收集所有与选中节点相关的节点 ID（通过锚点关联）
  const relatedNodeIds = new Set<string>();
  if (selectedNodeId && ctx?.anchors) {
    for (const a of ctx.anchors) {
      if (a.nodeId === selectedNodeId) {
        relatedNodeIds.add(a.nodeId);
      }
    }
    // 正文节点始终相关（因为锚点在正文上）
    const textbookNode = nodes.find((n) => n.type === "textbook_content");
    if (textbookNode) relatedNodeIds.add(textbookNode.id);
    relatedNodeIds.add(selectedNodeId);
  }

  return nodes.map((n) => {
    // 正文节点：n.type === "textbook_content" 已收窄为 TextbookContentNode
    if (n.type === "textbook_content") {
      const tbNode = n;
      const isDimmed = selectedNodeId !== null && !relatedNodeIds.has(tbNode.id);
      return {
        id: tbNode.id,
        type: "textbook_content",
        position: tbNode.position,
        data: {
          node: tbNode,
          anchors: ctx?.anchors ?? [],
          selectedNodeId,
          anchorableNodes: ctx?.anchorableNodes ?? [],
          onAddRangeAnchor: ctx?.onAddRangeAnchor,
          onAddPointAnchor: ctx?.onAddPointAnchor,
          onCreateNewNode: ctx?.onCreateNewNode,
          onSelectNode: ctx?.onSelectNode,
        } as Record<string, unknown>,
        selected: tbNode.id === selectedNodeId,
        draggable: false,
        style: isDimmed ? { opacity: 0.3 } : undefined,
      };
    }

    // 教学节点：textbook_content 分支已上方 return，此处 n 已收窄为 LessonPlanNode
    const lessonNode = n;
    const isDimmed = selectedNodeId !== null && !relatedNodeIds.has(lessonNode.id);
    return {
      id: lessonNode.id,
      type: "lesson",
      position: lessonNode.position,
      data: { node: lessonNode } as Record<string, unknown>,
      selected: lessonNode.id === selectedNodeId,
      style: isDimmed ? { opacity: 0.3 } : undefined,
    };
  });
}

export function toRfEdges(
  edges: AnyLessonPlanEdge[],
  selectedNodeId: string | null,
  anchors: NodeAnchor[],
  nodes: AnyLessonPlanNode[] = [],
): Edge[] {
  return edges.map((e) => {
    if (e.type === "anchor") {
      // 锚点边：默认 40% 透明度，选中关联节点时 100%
      const anchor = anchors.find((a) => a.id === e.anchorId);
      const isActive = anchor && anchor.nodeId === selectedNodeId;
      // P0-8 修复：传入节点 type 而非 nodeId，使颜色映射正确生效
      const nodeType = anchor ? getNodeTypeById(nodes, anchor.nodeId) : "rich_text";
      const strokeColor = getNodeColor(nodeType);
      return {
        ...e,
        animated: isActive,
        className: isActive ? "anchor-edge active" : "anchor-edge",
        // P1-3 修复：将 anchorId 存入 data，fromRfEdges 从 data 读取
        data: { anchorId: e.anchorId },
        style: {
          stroke: strokeColor,
          strokeWidth: isActive ? 3 : 2,
          opacity: isActive ? 1 : 0.4,
        },
      };
    }

    // 流程边
    const isDimmed = selectedNodeId !== null && e.source !== selectedNodeId && e.target !== selectedNodeId;
    return {
      ...e,
      animated: !isDimmed,
      style: {
        stroke: "#1976d2",
        strokeWidth: 2,
        opacity: isDimmed ? 0.2 : 1,
      },
    };
  });
}

/**
 * 将 React Flow edges 转回课案 edges 格式。
 */
export function fromRfEdges(
  rfEdges: Edge[],
): AnyLessonPlanEdge[] {
  return rfEdges.map((e) => {
    const base = {
      id: e.id,
      source: e.source,
      target: e.target,
      sourceHandle: e.sourceHandle ?? null,
      targetHandle: e.targetHandle ?? null,
    };

    // P1-3 修复：优先从 data.anchorId 读取，回退到 className 判断
    const dataAnchorId = (e.data as { anchorId?: string } | undefined)?.anchorId;
    if (dataAnchorId || e.className?.includes("anchor-edge")) {
      return {
        ...base,
        type: "anchor" as const,
        anchorId: dataAnchorId ?? e.id,
      };
    }

    return {
      ...base,
      type: "flow" as const,
    };
  });
}
