import type { Json } from "@/types/supabase";

type BlockLike = {
  id: string;
  type?: string;
  props?: Record<string, unknown>;
  content?: unknown;
  children?: BlockLike[];
};

const asBlockArray = (value: unknown): BlockLike[] => {
  if (!Array.isArray(value)) return [];
  return value.filter((b) => b && typeof b === "object" && typeof (b as { id?: unknown }).id === "string") as BlockLike[];
};

export const findBlockInTree = (
  blocks: BlockLike[],
  blockId: string,
): { block: BlockLike; parent: BlockLike | null; index: number } | null => {
  const stack: Array<{ list: BlockLike[]; parent: BlockLike | null }> = [{ list: blocks, parent: null }];
  while (stack.length) {
    const item = stack.pop()!;
    const list = item.list;
    for (let i = 0; i < list.length; i += 1) {
      const b = list[i]!;
      if (b.id === blockId) {
        return { block: b, parent: item.parent, index: i };
      }
      if (Array.isArray(b.children) && b.children.length > 0) {
        stack.push({ list: b.children, parent: b });
      }
    }
  }
  return null;
};

const cloneBlock = (block: BlockLike): BlockLike => {
  return {
    ...block,
    props: block.props ? { ...block.props } : undefined,
    content: Array.isArray(block.content) ? [...block.content] : block.content,
    children: Array.isArray(block.children) ? block.children.map(cloneBlock) : block.children,
  };
};

export const removeBlockSubtree = (
  blocks: BlockLike[],
  blockId: string,
): { removed: BlockLike | null; nextBlocks: BlockLike[] } => {
  // 说明：这里不直接修改入参 blocks，返回新的 nextBlocks。
  const nextTop = blocks.map(cloneBlock);
  const hit = findBlockInTree(nextTop, blockId);
  if (!hit) return { removed: null, nextBlocks: nextTop };

  if (hit.parent) {
    const parent = hit.parent;
    const nextChildren = asBlockArray(parent.children).map(cloneBlock);
    const removed = nextChildren.splice(hit.index, 1)[0] ?? null;
    parent.children = nextChildren;
    return { removed, nextBlocks: nextTop };
  }

  const removed = nextTop.splice(hit.index, 1)[0] ?? null;
  return { removed, nextBlocks: nextTop };
};

export const replaceBlockInTree = (
  blocks: BlockLike[],
  blockId: string,
  nextBlock: BlockLike,
): { ok: boolean; nextBlocks: BlockLike[] } => {
  const nextTop = blocks.map(cloneBlock);
  const hit = findBlockInTree(nextTop, blockId);
  if (!hit) return { ok: false, nextBlocks: nextTop };

  const normalized = cloneBlock({ ...nextBlock, id: blockId });
  if (hit.parent) {
    const parent = hit.parent;
    const nextChildren = asBlockArray(parent.children).map(cloneBlock);
    nextChildren[hit.index] = normalized;
    parent.children = nextChildren;
    return { ok: true, nextBlocks: nextTop };
  }

  nextTop[hit.index] = normalized;
  return { ok: true, nextBlocks: nextTop };
};

export const extractBlockText = (block: BlockLike): string => {
  const inline = Array.isArray(block.content) ? (block.content as Array<{ text?: unknown }>) : [];
  const text = inline.map((n) => (typeof n?.text === "string" ? n.text : "")).join("");
  return text.trim();
};

export const getBlocksFromDocumentContent = (content: unknown): BlockLike[] => {
  if (Array.isArray(content)) return asBlockArray(content);
  if (content && typeof content === "object") {
    const blocks = (content as { blocks?: unknown }).blocks;
    return asBlockArray(blocks);
  }
  return [];
};

export const withBlocksWrittenBack = (content: unknown, blocks: BlockLike[]): Json => {
  // 复用现有结构：数组或 {blocks: []}
  if (Array.isArray(content)) {
    return blocks as unknown as Json;
  }
  if (content && typeof content === "object") {
    return { ...(content as Record<string, unknown>), blocks } as Json;
  }
  return { blocks } as Json;
};

