import { createId } from "@paralleldrive/cuid2";
import type {
  AnchorEdge,
  AnyLessonPlanEdge,
  AnyLessonPlanNode,
  BlockData,
  BlockType,
  FlowEdge,
  LessonPlanDocument,
  LessonPlanDocumentV1,
  LessonPlanDocumentV2,
  LessonPlanEdge,
  LessonPlanNode,
  NodeAnchor,
  TemplateBlockSkeleton,
  TextbookContentNode,
} from "../types";

/**
 * 纯函数模块：课案文档迁移、规范化、初始内容构建。
 * 从 data-access.ts 抽取，便于单元测试。
 */

// ---- 默认数据生成器：为每种 BlockType 提供初始 data ----
export function defaultDataForType(type: BlockType): BlockData {
  switch (type) {
    case "objective":
      return { objectives: [] };
    case "key_point":
      return { keyPoints: [] };
    case "import":
      return { method: "question", prompt: "", durationMin: 5 };
    case "new_teaching":
      return { teachingPoints: [] };
    case "summary":
      return { summaryPoints: [], homeworkPreview: "" };
    case "homework":
      return { assignments: [] };
    case "blackboard":
      return { layout: "text", content: "", knowledgePointIds: [] };
    case "reflection":
      return { reflection: [] };
    case "exercise":
      return { items: [], purpose: "class_practice", knowledgePointIds: [] };
    case "text_study":
      return { sourceText: "", annotations: [], knowledgePointIds: [] };
    case "rich_text":
    case "consolidation":
    default:
      // consolidation 暂复用富文本结构（向后兼容旧模板）
      return { html: "", knowledgePointIds: [] };
  }
}

// ---- v1 → v2 迁移：将旧 blocks 数组转换为 nodes + 线性 edges ----
export function migrateV1ToV2(doc: LessonPlanDocumentV1): LessonPlanDocumentV2 {
  const nodes: LessonPlanNode[] = doc.blocks.map((b, i) => ({
    ...b,
    position: { x: 80 + (i % 4) * 280, y: 80 + Math.floor(i / 4) * 200 },
  }));
  const edges: LessonPlanEdge[] = [];
  for (let i = 0; i < nodes.length - 1; i++) {
    edges.push({
      id: `e_${nodes[i].id}_${nodes[i + 1].id}`,
      source: nodes[i].id,
      target: nodes[i + 1].id,
    });
  }
  return { version: 2, nodes, edges };
}

// ---- v2 → v3 迁移：注入正文节点 + 锚点数组 + 边类型 ----
export function migrateV2ToV3(
  doc: LessonPlanDocumentV2,
  chapterId?: string | null,
  chapterContent?: string | null,
): LessonPlanDocument {
  const textbookContentNodeId = createId();
  const textbookNode: TextbookContentNode = {
    id: textbookContentNodeId,
    type: "textbook_content",
    title: "textbook_content",
    data: {
      chapterId: chapterId ?? "",
      content: chapterContent ?? "",
      zoom: 1,
    },
    order: -1,
    position: { x: 400, y: 200 },
    draggable: false,
  };

  // 旧 edges 转为 flow 类型
  const flowEdges: FlowEdge[] = doc.edges.map((e) => ({
    ...e,
    type: "flow" as const,
  }));

  return {
    version: 3,
    textbookContentNodeId,
    nodes: [textbookNode, ...doc.nodes],
    edges: flowEdges,
    anchors: [],
  };
}

// ---- 类型守卫：判断是否为 v3 文档 ----
function isV3Document(content: unknown): content is LessonPlanDocument {
  if (!content || typeof content !== "object") return false;
  const c = content as {
    version?: unknown;
    textbookContentNodeId?: unknown;
    nodes?: unknown;
    edges?: unknown;
    anchors?: unknown;
  };
  return (
    c.version === 3 &&
    typeof c.textbookContentNodeId === "string" &&
    Array.isArray(c.nodes) &&
    Array.isArray(c.edges) &&
    Array.isArray(c.anchors)
  );
}

// ---- 类型守卫：判断是否为 v2 文档 ----
function isV2Document(content: unknown): content is LessonPlanDocumentV2 {
  if (!content || typeof content !== "object") return false;
  const c = content as { version?: unknown; nodes?: unknown; edges?: unknown };
  return (
    c.version === 2 &&
    Array.isArray(c.nodes) &&
    Array.isArray(c.edges)
  );
}

// ---- 类型守卫：判断是否为 v1 文档 ----
function isV1Document(content: unknown): content is LessonPlanDocumentV1 {
  if (!content || typeof content !== "object") return false;
  const c = content as { version?: unknown; blocks?: unknown };
  return c.version === 1 && Array.isArray(c.blocks);
}

// ---- 规范化：确保 content 是 v3 格式（兼容 v1/v2 旧数据）----
export function normalizeDocument(
  content: unknown,
  chapterId?: string | null,
  chapterContent?: string | null,
): LessonPlanDocument {
  if (isV3Document(content)) return content;
  if (isV2Document(content)) {
    return migrateV2ToV3(content, chapterId, chapterContent);
  }
  if (isV1Document(content)) {
    return migrateV2ToV3(migrateV1ToV2(content), chapterId, chapterContent);
  }
  // 空文档：创建一个无正文的 v3
  const textbookContentNodeId = createId();
  const textbookNode: TextbookContentNode = {
    id: textbookContentNodeId,
    type: "textbook_content",
    title: "textbook_content",
    data: { chapterId: chapterId ?? "", content: chapterContent ?? "", zoom: 1 },
    order: -1,
    position: { x: 400, y: 200 },
    draggable: false,
  };
  return {
    version: 3,
    textbookContentNodeId,
    nodes: [textbookNode],
    edges: [],
    anchors: [],
  };
}

// ---- 模板初始化：根据骨架生成初始 content（v3，无正文节点）----
// 注意：此函数不创建正文节点，调用方应使用 buildDefaultSkeleton 创建完整 v3 文档
export function buildInitialContent(
  blocks: TemplateBlockSkeleton[],
): LessonPlanDocument {
  const textbookContentNodeId = createId();
  const textbookNode: TextbookContentNode = {
    id: textbookContentNodeId,
    type: "textbook_content",
    title: "textbook_content",
    data: { chapterId: "", content: "", zoom: 1 },
    order: -1,
    position: { x: 400, y: 200 },
    draggable: false,
  };

  const nodes: LessonPlanNode[] = blocks.map((b, i) => ({
    id: createId(),
    type: b.type,
    title: b.title,
    data: defaultDataForType(b.type),
    order: i,
    position: { x: 80 + (i % 4) * 280, y: 80 + Math.floor(i / 4) * 200 },
  }));

  const edges: FlowEdge[] = [];
  for (let i = 0; i < nodes.length - 1; i++) {
    edges.push({
      id: `e_${nodes[i].id}_${nodes[i + 1].id}`,
      source: nodes[i].id,
      target: nodes[i + 1].id,
      type: "flow",
    });
  }

  return {
    version: 3,
    textbookContentNodeId,
    nodes: [textbookNode, ...nodes],
    edges,
    anchors: [],
  };
}

// ---- 默认骨架：10 节点 + 1 正文节点（创建课案时使用）----
export function buildDefaultSkeleton(
  chapterId: string,
  chapterContent: string,
  translateTitle?: (key: string) => string,
): LessonPlanDocument {
  const textbookContentNodeId = createId();
  // P2-5：正文节点居中，左右列增大间距避免重叠
  const textbookNode: TextbookContentNode = {
    id: textbookContentNodeId,
    type: "textbook_content",
    title: "textbook_content",
    data: { chapterId, content: chapterContent, zoom: 1 },
    order: -1,
    position: { x: 500, y: 250 },
    draggable: false,
  };

  // P2-5：左列 x=80，右列 x=900，避免与正文节点（宽 480）重叠
  const skeleton: { type: BlockType; position: { x: number; y: number } }[] = [
    { type: "objective", position: { x: 80, y: 80 } },
    { type: "key_point", position: { x: 80, y: 200 } },
    { type: "import", position: { x: 80, y: 320 } },
    { type: "text_study", position: { x: 80, y: 440 } },
    { type: "new_teaching", position: { x: 900, y: 80 } },
    { type: "exercise", position: { x: 900, y: 200 } },
    { type: "summary", position: { x: 900, y: 320 } },
    { type: "homework", position: { x: 80, y: 560 } },
    { type: "blackboard", position: { x: 900, y: 440 } },
    { type: "reflection", position: { x: 900, y: 560 } },
  ];

  const nodes: LessonPlanNode[] = skeleton.map((s, i) => ({
    id: createId(),
    type: s.type,
    title: translateTitle
      ? translateTitle(`blockType.${s.type}`)
      : `blockType.${s.type}`,
    data: defaultDataForType(s.type),
    order: i,
    position: s.position,
  }));

  // 默认流程连线：导入→文本研习→新授→练习→小结
  const flowPairs: [number, number][] = [
    [2, 3], // import → text_study
    [3, 4], // text_study → new_teaching
    [4, 5], // new_teaching → exercise
    [5, 6], // exercise → summary
  ];
  const edges: FlowEdge[] = flowPairs.map(([from, to]) => ({
    id: `e_${nodes[from].id}_${nodes[to].id}`,
    source: nodes[from].id,
    target: nodes[to].id,
    type: "flow",
  }));

  return {
    version: 3,
    textbookContentNodeId,
    nodes: [textbookNode, ...nodes],
    edges,
    anchors: [],
  };
}

// ---- 工具函数：判断节点是否为正文节点 ----
export function isTextbookContentNode(
  node: AnyLessonPlanNode,
): node is TextbookContentNode {
  return node.type === "textbook_content";
}

// ---- 工具函数：判断边是否为锚点边 ----
export function isAnchorEdge(
  edge: AnyLessonPlanEdge,
): edge is AnchorEdge {
  return edge.type === "anchor";
}

// ---- 工具函数：获取节点的关联锚点 ----
export function getAnchorsForNode(
  anchors: NodeAnchor[],
  nodeId: string,
): NodeAnchor[] {
  return anchors.filter((a) => a.nodeId === nodeId);
}

// ---- 工具函数：根据选中节点获取激活的锚点 ID 集合 ----
export function getActiveAnchorIds(
  anchors: NodeAnchor[],
  selectedNodeId: string | null,
): Set<string> {
  if (!selectedNodeId) return new Set();
  return new Set(
    anchors.filter((a) => a.nodeId === selectedNodeId).map((a) => a.id),
  );
}

// ---- 工具函数：根据锚点 ID 获取对应的边 ----
export function getAnchorEdges(
  edges: AnyLessonPlanEdge[],
  anchorIds: Set<string>,
): AnchorEdge[] {
  return edges.filter(
    (e): e is AnchorEdge =>
      e.type === "anchor" && anchorIds.has(e.anchorId),
  );
}
