import type { CanonicalModelError } from "../../model/index.js";
import type { ContextRecoveryDecision } from "../protocol/types.js";

export type ContextOverflowRecoveryOptions = {
  truncateFirstKeepRatio?: number;
  truncateSecondKeepRatio?: number;
};

const DEFAULT_FIRST_KEEP = 0.5;
const DEFAULT_SECOND_KEEP = 0.25;

/**
 * Single-shot recovery decision (decision §3.1 #8). The first PTL within a
 * turn keeps the trailing 50%; the second keeps 25%; anything else
 * (including a third PTL) yields `give_up` and the loop must turn_failed.
 */
export class ContextOverflowRecovery {
  private readonly first: number;
  private readonly second: number;

  constructor(options: ContextOverflowRecoveryOptions = {}) {
    this.first = options.truncateFirstKeepRatio ?? DEFAULT_FIRST_KEEP;
    this.second = options.truncateSecondKeepRatio ?? DEFAULT_SECOND_KEEP;
  }

  decide(input: { error: CanonicalModelError; hasAttemptedCompact: boolean }): ContextRecoveryDecision {
    if (input.error.recoverableViaImageStrip) {
      return { type: "strip_images_and_retry", reason: "multimodal-processor-error" };
    }
    if (input.error.code !== "prompt_too_long") {
      return { type: "give_up", reason: `non_recoverable_model_error:${input.error.code}` };
    }
    if (input.hasAttemptedCompact) {
      return { type: "give_up", reason: "ptl-exhausted-after-two-attempts" };
    }
    return { type: "truncate_head_and_retry", keepRatio: this.first, reason: "ptl-first-attempt" };
  }
}