export type ParentLinkedRow = {
  id: string;
  parent_id?: string | null;
};

/**
 * 收集以 rootId 为根的整棵子树（包含根节点本身）。
 *
 * 说明：
 * - 仅依赖 (id, parent_id) 字段，便于在 Convex 与前端共用同一套遍历逻辑。
 * - 会做去重与环检测，避免异常数据导致死循环。
 */
export function collectSubtree<T extends ParentLinkedRow>(rows: readonly T[], rootId: string): T[] {
  const byParentId = new Map<string | null, T[]>();
  for (const row of rows) {
    const parentId = (row.parent_id ?? null) as string | null;
    const bucket = byParentId.get(parentId);
    if (bucket) bucket.push(row);
    else byParentId.set(parentId, [row]);
  }

  const root = rows.find((r) => r.id === rootId);
  if (!root) return [];

  const visited = new Set<string>();
  const stack: T[] = [root];
  const result: T[] = [];

  while (stack.length > 0) {
    const current = stack.pop()!;
    if (visited.has(current.id)) continue;
    visited.add(current.id);
    result.push(current);

    const children = byParentId.get(current.id) ?? [];
    // 倒序入栈，保持更接近“原列表顺序”的遍历结果（不影响正确性）
    for (let i = children.length - 1; i >= 0; i -= 1) {
      stack.push(children[i]!);
    }
  }

  return result;
}

