import type { ChatMessage, RunningTask } from './types';

/**
 * Put recovered background-task rows back where they belong, rather than at the end.
 *
 * A task row is officer's own invention — nothing corresponding to it is written to Claude's transcript —
 * so a refresh rebuilds the conversation without it, and the server hands the still-running ones back on
 * `sync:live`. The question is where they go.
 *
 * The row carries no timestamp, but it does not need one: the harness stamps the task's id into the output
 * of the very tool call that started it ("running in background with ID: …"). Live, `task:started` arrives
 * immediately after that tool result — anchoring there reproduces the position the row would have had if
 * you had never refreshed.
 *
 * The *first* mention wins, and that is the whole correctness argument: the id is minted by the call that
 * spawns the task, so nothing earlier in the conversation can contain it. Later mentions are commonplace —
 * the agent quoting a task id while diagnosing something, or a command that prints one — and matching the
 * most recent instead put rows next to a diagnostic that merely named them.
 *
 * A task whose tool call has scrolled out of the loaded window still appends. That is the old behaviour
 * kept as the fallback: at the end is worse than in place, and better than silently dropped.
 */
export function spliceRunningTasks(messages: ChatMessage[], tasks: RunningTask[]): ChatMessage[] {
  const known = new Set(messages.filter((m) => m.role === 'task').map((m) => m.taskId));
  const fresh = tasks.filter((t) => !known.has(t.taskId));
  if (!fresh.length) return messages;

  const anchored = new Map<number, ChatMessage[]>();
  const unanchored: ChatMessage[] = [];
  for (const task of fresh) {
    const row: ChatMessage = { role: 'task', ...task };
    const at = messages.findIndex((m) => m.role === 'tool' && m.output?.includes(task.taskId));
    if (at === -1) unanchored.push(row);
    else anchored.set(at, [...(anchored.get(at) ?? []), row]);
  }
  if (!anchored.size) return [...messages, ...unanchored];

  const next: ChatMessage[] = [];
  messages.forEach((message, i) => {
    next.push(message);
    const rows = anchored.get(i);
    if (rows) next.push(...rows);
  });
  return [...next, ...unanchored];
}
