import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
  classifyGoogleContractToolOutcome,
  createGoogleContractState,
  isSubmitTaskAlreadySubmitted,
  recordGoogleContractFrMismatch,
  recordGoogleContractHitMaxRounds,
  recordGoogleContractInvalidOutput,
  recordGoogleContractModelNotFound,
  recordGoogleContractToolResult,
  recordGoogleContractZeroToolcall,
  shouldStopGoogleContractLoop,
} from "../FcopGoogleRuntimeContract.ts";

describe("FcopGoogleRuntimeContract", () => {
  it("createGoogleContractState starts unblocked", () => {
    const state = createGoogleContractState();
    assert.equal(state.blocked, false);
    assert.equal(state.stopReason, null);
    assert.equal(state.hadWriteReportSuccess, false);
  });

  it("recordGoogleContractToolResult tracks write_report success", () => {
    const state = createGoogleContractState();
    recordGoogleContractToolResult(state, {
      toolName: "write_report",
      output: JSON.stringify({ ok: true, status: "done" }),
      ok: true,
    });
    assert.equal(state.hadWriteReportSuccess, true);
  });

  it("recordGoogleContractZeroToolcall blocks after 3 strikes", () => {
    const state = createGoogleContractState();
    recordGoogleContractZeroToolcall(state);
    recordGoogleContractZeroToolcall(state);
    assert.equal(state.blocked, false);
    recordGoogleContractZeroToolcall(state);
    assert.equal(state.blocked, true);
    assert.equal(state.stopReason, "zero_toolcall");
  });

  it("recordGoogleContractInvalidOutput blocks after 2 strikes", () => {
    const state = createGoogleContractState();
    recordGoogleContractInvalidOutput(state);
    assert.equal(state.blocked, false);
    recordGoogleContractInvalidOutput(state);
    assert.equal(state.blocked, true);
    assert.equal(state.stopReason, "invalid_agent_output");
  });

  it("recordGoogleContractFrMismatch blocks after 2 strikes", () => {
    const state = createGoogleContractState();
    recordGoogleContractFrMismatch(state);
    recordGoogleContractFrMismatch(state);
    assert.equal(state.blocked, true);
    assert.equal(state.stopReason, "function_response_misaligned");
  });

  it("recordGoogleContractModelNotFound blocks immediately", () => {
    const state = createGoogleContractState();
    recordGoogleContractModelNotFound(state);
    assert.equal(state.blocked, true);
    assert.equal(state.stopReason, "model_not_found");
  });

  it("recordGoogleContractHitMaxRounds sets hit_max_rounds", () => {
    const state = createGoogleContractState();
    recordGoogleContractHitMaxRounds(state);
    assert.equal(state.hitMaxRounds, true);
    assert.equal(state.stopReason, "hit_max_rounds");
  });

  it("classifies duplicate submit_task (already in review) as success", () => {
    const err =
      '{"error":"submit_review denied: expected state active, got review"}';
    assert.equal(isSubmitTaskAlreadySubmitted(err), true);
    assert.equal(
      classifyGoogleContractToolOutcome("submit_task", err).outcome,
      "success",
    );
    const state = createGoogleContractState();
    recordGoogleContractToolResult(state, {
      toolName: "submit_task",
      output: err,
    });
    assert.equal(state.hadSubmitTaskSuccess, true);
  });

  it("shouldStopGoogleContractLoop early-stops on report+submit success", () => {
    const state = createGoogleContractState();
    recordGoogleContractToolResult(state, {
      toolName: "write_report",
      output: '{"ok":true}',
      ok: true,
    });
    recordGoogleContractToolResult(state, {
      toolName: "submit_task",
      output: '{"ok":true}',
      ok: true,
    });
    assert.equal(shouldStopGoogleContractLoop({ state }), true);
    assert.equal(state.stopReason, "write_report_submit_done");
  });
});
