import { describe, expect, it } from "vitest";
import {
  calculateConversationMemoryBudgetTokens,
  getCompactionAdvisoryFromSnapshot,
} from "./provider-request-budget.js";

describe("agent runtime request budget helpers", () => {
  it("reserves fixed request overhead before planning memory compaction", () => {
    expect(
      calculateConversationMemoryBudgetTokens({
        estimatedConversationTokens: 2_240,
        estimatedRequestTokens: 2_378,
        inputBudgetTokens: 2_320,
      }),
    ).toBe(2_182);
  });

  it("clamps the memory budget at zero when fixed overhead exhausts the input budget", () => {
    expect(
      calculateConversationMemoryBudgetTokens({
        estimatedConversationTokens: 120,
        estimatedRequestTokens: 640,
        inputBudgetTokens: 320,
      }),
    ).toBe(0);
  });

  it("does not advise compaction without a request-budget snapshot", () => {
    expect(getCompactionAdvisoryFromSnapshot(undefined, 512)).toEqual({
      budgetKnown: false,
      plannedCostEstimate: 512,
      reason: "No request-budget snapshot is available yet.",
      shouldCompact: false,
      timing: "none",
    });
  });

  it("advises compaction when planned work crosses the predictive threshold", () => {
    const advisory = getCompactionAdvisoryFromSnapshot(
      {
        autoBudgetOutcome: "not-needed",
        estimatedInputTokens: 650,
        inputBudgetTokens: 1_000,
        updatedAt: "2026-05-09T00:00:00.000Z",
      },
      75,
    );

    expect(advisory.shouldCompact).toBe(true);
    expect(advisory.timing).toBe("before-expensive-operation");
    expect(advisory.projectedTokenUsage).toBe(72.5);
    expect(advisory.remainingInputTokens).toBe(275);
  });

  it("exposes failed-to-fit snapshots through the advisory API", () => {
    const advisory = getCompactionAdvisoryFromSnapshot({
      autoBudgetOutcome: "failed-to-fit",
      estimatedInputTokens: 1_200,
      inputBudgetTokens: 1_000,
      updatedAt: "2026-05-09T00:00:00.000Z",
    });

    expect(advisory).toMatchObject({
      autoBudgetOutcome: "failed-to-fit",
      budgetKnown: true,
      reason: "The latest request did not fit the input budget.",
      remainingInputTokens: -200,
      shouldCompact: true,
      timing: "before-expensive-operation",
    });
  });

  it("preserves the caution-window threshold without planned work", () => {
    const advisory = getCompactionAdvisoryFromSnapshot({
      autoBudgetOutcome: "not-needed",
      estimatedInputTokens: 650,
      inputBudgetTokens: 1_000,
      updatedAt: "2026-05-09T00:00:00.000Z",
    });

    expect(advisory.shouldCompact).toBe(false);
    expect(advisory.timing).toBe("none");
  });

  it("advises compaction inside the caution window without planned work", () => {
    const advisory = getCompactionAdvisoryFromSnapshot({
      autoBudgetOutcome: "not-needed",
      estimatedInputTokens: 900,
      inputBudgetTokens: 1_000,
      updatedAt: "2026-05-09T00:00:00.000Z",
    });

    expect(advisory.shouldCompact).toBe(true);
    expect(advisory.timing).toBe("before-expensive-operation");
    expect(advisory.reason).toBe("The latest request is inside the compaction caution window.");
  });
});
