// SPEC: PJ2026-010404 project management draft-2026-06-25-p0-mdtodo-web-active-editing-hwpod-source.
// 职责：根据节点自身及全部后代推导只用于展示的 TaskTree 父级时间范围。

export type TaskTreeTimedNode = {
  id: string;
  parentId: string | null;
  startAt: string | null;
  dueAt: string | null;
};

export type TaskTreeTimeRange = Pick<TaskTreeTimedNode, "startAt" | "dueAt">;

export function deriveEffectiveTaskTimeRanges(tasks: TaskTreeTimedNode[]): Map<string, TaskTreeTimeRange> {
  const tasksById = new Map(tasks.map((task) => [task.id, task]));
  const childrenByParent = new Map<string, TaskTreeTimedNode[]>();
  for (const task of tasks) {
    if (!task.parentId || !tasksById.has(task.parentId)) continue;
    childrenByParent.set(task.parentId, [...(childrenByParent.get(task.parentId) ?? []), task]);
  }

  const ranges = new Map<string, TaskTreeTimeRange>();
  const resolving = new Set<string>();
  const resolve = (task: TaskTreeTimedNode): TaskTreeTimeRange => {
    const cached = ranges.get(task.id);
    if (cached) return cached;
    if (resolving.has(task.id)) return { startAt: task.startAt, dueAt: task.dueAt };
    resolving.add(task.id);
    const values = [task.startAt, task.dueAt];
    for (const child of childrenByParent.get(task.id) ?? []) {
      const childRange = resolve(child);
      values.push(childRange.startAt, childRange.dueAt);
    }
    const timestamps = values
      .filter((value): value is string => Boolean(value))
      .map((value) => new Date(value).getTime())
      .filter(Number.isFinite);
    const range = timestamps.length > 0
      ? { startAt: new Date(Math.min(...timestamps)).toISOString(), dueAt: new Date(Math.max(...timestamps)).toISOString() }
      : { startAt: null, dueAt: null };
    resolving.delete(task.id);
    ranges.set(task.id, range);
    return range;
  };

  for (const task of tasks) resolve(task);
  return ranges;
}
