// P5 (SPLIT SKETCH 5): pure step-decision helpers for the runAssistantTurn
// loop. These COMPOSE the existing decision predicates (detectDoomLoop,
// detectMistakePattern) — they do not reimplement them — so the loop body in
// turn.ts becomes a thin driver and the branch logic is unit-testable without
// a DB, broker, or stream.

import type { ToolCall } from '../../types/api.js';
import { detectDoomLoop } from './sentinels.js';
import { detectMistakePattern, type MistakeState } from './mistake-tracker.js';
import type { ToolPhaseResult } from './tool-phase.js';

// Top-of-loop gate, evaluated before the stream phase. Order matters and
// matches the original inline checks exactly: doom-loop first (identical-repeat
// guard), then the cumulative tool-call budget, otherwise proceed to stream.
export type PreStepDecision =
  | { kind: 'doom'; loop: { name: string; args: Record<string, unknown> } }
  | { kind: 'budget' }
  | { kind: 'stream' };

export function decideStep(input: {
  recentToolCalls: ToolCall[];
  toolsUsed: number;
  budget: number;
}): PreStepDecision {
  const loop = detectDoomLoop(input.recentToolCalls);
  if (loop) return { kind: 'doom', loop };
  if (input.toolsUsed >= input.budget) return { kind: 'budget' };
  return { kind: 'stream' };
}

// Post-tool-phase decision, evaluated after the tool phase returns. 'stop'
// covers the tool-phase's own non-'continue' actions ('paused' for user input,
// 'synthesis_done'); on 'continue' the mistake-tracker pattern gates the
// nudge/escalate/continue choice (detectMistakePattern is only consulted on the
// 'continue' path, exactly as the original loop did).
export type PostToolDecision = 'continue' | 'nudge' | 'escalate' | 'stop';

export function decidePostToolAction(
  action: ToolPhaseResult['action'],
  mistakeTracker: MistakeState,
): PostToolDecision {
  if (action !== 'continue') return 'stop';
  const mistake = detectMistakePattern(mistakeTracker);
  if (mistake === 'nudge') return 'nudge';
  if (mistake === 'escalate') return 'escalate';
  return 'continue';
}
