import type { StateCreator } from "zustand";
import { createId } from "@paralleldrive/cuid2";
import type {
  AnchorType,
  Block,
  BlockType,
  LessonPlanDocument,
  LessonPlanNode,
  NodeAnchor,
  TextbookContentNode,
  TextbookContentNodeData,
} from "../types";
import { defaultDataForType } from "../lib/document-migration";
import type { EditorState } from "./use-lesson-plan-editor";

export interface EditorSlice {
  planId: string;
  title: string;
  doc: LessonPlanDocument;
  setTitle: (title: string) => void;
  setPlanId: (planId: string) => void;
  addNode: (type: BlockType, position?: { x: number; y: number }, title?: string) => string;
  updateNode: (id: string, patch: Omit<Partial<Block>, "type">) => void;
  removeNode: (id: string) => void;
  updateTextbookContent: (data: Partial<TextbookContentNodeData>) => void;
  getTextbookContentNode: () => TextbookContentNode | undefined;
  /**
   * V4：添加锚点（不再传 start/end，锚点位置由 Tiptap Mark 内嵌）。
   *
   * 兼容说明：旧调用方可能传入 { nodeId, type, start, end, textPreview }，
   * 这些 v3 字段会被忽略，等阶段 H 改造调用方时再清理。
   */
  addAnchor: (params: {
    nodeId: string;
    type: AnchorType;
    /** @deprecated v3 字段，v4 已由 Tiptap Mark 承载，忽略 */
    start?: number;
    /** @deprecated v3 字段，v4 忽略 */
    end?: number;
    /** @deprecated v3 字段，v4 忽略 */
    textPreview?: string;
  }) => string;
  removeAnchor: (anchorId: string) => void;
  updateAnchor: (anchorId: string, patch: Partial<NodeAnchor>) => void;
}

function reindex(nodes: LessonPlanNode[]): LessonPlanNode[] {
  return nodes.map((n, i) => ({ ...n, order: i }));
}

export const createEditorSlice: StateCreator<
  EditorState,
  [],
  [],
  EditorSlice
> = (set, get) => ({
  planId: "",
  title: "",
  doc: {
    version: 4,
    textbookContentNodeId: "",
    nodes: [],
    edges: [],
    anchors: [],
    expandedNodeIds: [],
  },

  setTitle: (title) => {
    get().pushHistory();
    set({ title, isDirty: true });
  },
  setPlanId: (planId) => set({ planId }),

  addNode: (type, _position, title) => {
    const id = createId();
    const state = get();
    state.pushHistory(); // V5-2：撤销/重做
    const teachingNodes = state.doc.nodes.filter(
      (n): n is LessonPlanNode => n.type !== "textbook_content",
    );
    const nodeCount = teachingNodes.length;
    const node: LessonPlanNode = {
      id,
      type,
      title: title ?? type,
      data: defaultDataForType(type),
      order: nodeCount,
      position: { x: 0, y: 0 }, // V4：不再使用，保留字段兼容
    };
    set((s) => ({
      doc: { ...s.doc, nodes: [...s.doc.nodes, node] },
      isDirty: true,
      selectedNodeId: id,
    }));
    return id;
  },

  updateNode: (id, patch) => {
    get().pushHistory(); // V5-2：撤销/重做
    set((s) => ({
      doc: {
        ...s.doc,
        nodes: s.doc.nodes.map((n) =>
          n.id === id
            ? n.type === "textbook_content"
              ? ({ ...n, ...patch } as TextbookContentNode)
              : ({ ...n, ...patch } as LessonPlanNode)
            : n,
        ),
      },
      isDirty: true,
    }));
  },

  removeNode: (id) => {
    get().pushHistory(); // V5-2：撤销/重做
    set((s) => {
      const remainingTeachingNodes = reindex(
        s.doc.nodes.filter(
          (n): n is LessonPlanNode => n.id !== id && n.type !== "textbook_content",
        ),
      );
      const textbookNode = s.doc.nodes.find(
        (n): n is TextbookContentNode => n.type === "textbook_content",
      );
      const nodes = textbookNode
        ? [textbookNode, ...remainingTeachingNodes]
        : remainingTeachingNodes;
      return {
        doc: {
          ...s.doc,
          nodes,
          edges: s.doc.edges.filter(
            (e) => e.source !== id && e.target !== id,
          ),
          anchors: s.doc.anchors.filter((a) => a.nodeId !== id),
        },
        isDirty: true,
        selectedNodeId: s.selectedNodeId === id ? null : s.selectedNodeId,
      };
    });
  },

  updateTextbookContent: (data) => {
    get().pushHistory(); // V5-2：撤销/重做
    set((s) => ({
      doc: {
        ...s.doc,
        nodes: s.doc.nodes.map((n) =>
          n.type === "textbook_content" && n.id === s.doc.textbookContentNodeId
            ? { ...n, data: { ...n.data, ...data } }
            : n,
        ),
      },
      isDirty: true,
    }));
  },

  getTextbookContentNode: () => {
    const state = get();
    return state.doc.nodes.find(
      (n): n is TextbookContentNode => n.type === "textbook_content",
    );
  },

  addAnchor: ({ nodeId, type }) => {
    const anchorId = createId();
    get().pushHistory(); // V5-2：撤销/重做
    set((s) => ({
      doc: {
        ...s.doc,
        anchors: [
          ...s.doc.anchors,
          { id: anchorId, nodeId, type },
        ],
      },
      isDirty: true,
    }));
    return anchorId;
  },

  removeAnchor: (anchorId) => {
    get().pushHistory(); // V5-2：撤销/重做
    set((s) => ({
      doc: {
        ...s.doc,
        anchors: s.doc.anchors.filter((a) => a.id !== anchorId),
        edges: s.doc.edges.filter(
          (e) => !(e.type === "anchor" && e.anchorId === anchorId),
        ),
      },
      isDirty: true,
    }));
  },

  updateAnchor: (anchorId, patch) => {
    get().pushHistory(); // V5-2：撤销/重做
    set((s) => ({
      doc: {
        ...s.doc,
        anchors: s.doc.anchors.map((a) =>
          a.id === anchorId ? { ...a, ...patch } : a,
        ),
      },
      isDirty: true,
    }));
  },
});
