import type { PersistedProviderDecideCheckpointRequest } from "../checkpoint-codec.js";
import {
  collectReplayArtifactObligationFailures,
  compileReplayArtifactObligations,
} from "./provider-replay-deliverable-repair.js";
import { decideReplayRepairWithObservation } from "./provider-replay-repair-decision-runner.js";
import type { ReplayTerminalRepairState } from "./provider-replay-terminal-repair-state.js";
import { buildTerminalOutputInvalidRepair } from "./provider-terminal-output-handler.js";
import { resolveProviderTurnActionPolicy, resolveProviderVisibleTools } from "./tool-constraint.js";

export async function repairReplayDecideTerminalOutput(input: {
  responseText: string;
  state: ReplayTerminalRepairState;
}): Promise<string> {
  const { payload, replayContextAvailableTools, runtime, turn } = input.state;
  const request = runtime.hydrateProviderDecideCheckpointRequest(
    payload.request as PersistedProviderDecideCheckpointRequest,
  );
  const availableTools = replayContextAvailableTools ?? request.tools;
  const artifactObligations = compileReplayArtifactObligations({
    availableTools,
    cwd: runtime.cwd,
    messages: request.messages,
    objective: payload.replayContext?.objective,
    payloadArtifactObligations: payload.artifactObligations,
  });
  const deliverableFailures =
    artifactObligations.length > 0
      ? await collectReplayArtifactObligationFailures({
          artifactObligations,
          cwd: runtime.cwd,
          runtime,
          turn,
        })
      : [];
  const visibleToolsForPrompt =
    deliverableFailures.length > 0
      ? resolveProviderVisibleTools(availableTools, undefined, request.messages)
      : request.tools;
  const allowPhaseResult =
    deliverableFailures.length > 0
      ? false
      : Boolean(request.allowPhaseResult && request.phaseResultPhaseName);
  const allowPlanUpdate =
    deliverableFailures.length > 0 ? false : (request.allowPlanUpdate ?? false);
  const terminalRepair = buildTerminalOutputInvalidRepair({
    baseActionPolicy: resolveProviderTurnActionPolicy({
      allowPhaseResult,
      allowPlanUpdate,
      requestKind: "decide",
      requiredToolConstraint:
        deliverableFailures.length > 0 ? undefined : payload.replayContext?.requiredToolConstraint,
      visibleTools: visibleToolsForPrompt,
    }),
    deliverableFailures,
    observationToolNames: visibleToolsForPrompt.map((tool) => tool.name),
    text: input.responseText,
    visibleTools: visibleToolsForPrompt,
  });
  return decideReplayRepairWithObservation({
    artifactObligations,
    missingProfileMessage:
      "Provider request checkpoint is missing the profile needed to repair replayed terminal output.",
    repairCode: "TERMINAL_OUTPUT_INVALID",
    repairInput: {
      assertTerminal: true,
      repairActionPolicy: terminalRepair.actionPolicy,
      requiresDeliverableAssertion: terminalRepair.requiresDeliverableAssertion,
      suppressStructuredControls: terminalRepair.suppressStructuredControls,
    },
    repairObservation: terminalRepair.observation,
    repairSystemPrompt: request.systemPrompt,
    request,
    state: input.state,
  });
}
