/**
 * Sort a list by its `position` field ascending (nulls treated as 0).
 * Returns a new array; the input is not mutated.
 */
export const sortByPosition = <T extends { position: number | null }>(
  items: T[],
): T[] => [...items].sort((a, b) => (a.position ?? 0) - (b.position ?? 0));

/**
 * Depth-first flatten of a tree's descendants (root excluded), preserving each
 * level's order. Works on any node exposing a nullable `children` array.
 */
export const flattenTree = <T extends { children: T[] | null }>(
  root?: T | null,
): T[] => {
  if (!root?.children?.length) return [];

  const result: T[] = [];
  const stack = [...root.children].reverse();

  while (stack.length) {
    const node = stack.pop();
    if (!node) break;

    result.push(node);

    if (node.children) stack.push(...[...node.children].reverse());
  }

  return result;
};

/**
 * Map every node id in a tree to its 1-based depth (root = 1). Works on any
 * node exposing an `id` and a nullable `children` array.
 */
export const buildDepthMap = <T extends { id: number; children: T[] | null }>(
  tree: T | null | undefined,
  depth = 1,
  map = new Map<number, number>(),
): Map<number, number> => {
  if (!tree) return map;

  map.set(tree.id, depth);
  tree.children?.forEach(child => {
    buildDepthMap(child, depth + 1, map);
  });

  return map;
};
