import assert from "node:assert/strict";
import { describe, it } from "vitest";
import { computeAdaptiveVerificationPolicy } from "../uok/adaptive-verification-policy.js";

function makeEvent(outcome, failureClass = "unknown") {
	return {
		gateId: "outcome-learning",
		outcome,
		failureClass,
		ts: new Date().toISOString(),
	};
}

// ─── Minimum sample threshold ──────────────────────────────────────────────

describe("computeAdaptiveVerificationPolicy", () => {
	it("returns_null_when_fewer_than_5_samples", () => {
		const events = [
			makeEvent("pass"),
			makeEvent("pass"),
			makeEvent("pass"),
			makeEvent("pass"),
		];
		const result = computeAdaptiveVerificationPolicy("/tmp", {}, events);
		assert.equal(result, null);
	});

	// ─── High failure rate (>60%) for verification/artifact/execution ───────

	it("reduces_retries_when_verification_failure_rate_exceeds_60%", () => {
		const events = Array.from({ length: 10 }, () =>
			makeEvent("fail", "verification"),
		);
		const result = computeAdaptiveVerificationPolicy("/tmp", {}, events);
		assert.ok(result, "Expected policy change");
		assert.equal(result.verification_max_retries, 1);
		assert.equal(result.verification_auto_fix, false);
	});

	it("reduces_retries_when_artifact_failure_rate_exceeds_60%", () => {
		const events = Array.from({ length: 10 }, () =>
			makeEvent("fail", "artifact"),
		);
		const result = computeAdaptiveVerificationPolicy("/tmp", {}, events);
		assert.ok(result);
		assert.equal(result.verification_max_retries, 1);
		assert.equal(result.verification_auto_fix, false);
	});

	it("reduces_retries_when_execution_failure_rate_exceeds_60%", () => {
		const events = Array.from({ length: 10 }, () =>
			makeEvent("fail", "execution"),
		);
		const result = computeAdaptiveVerificationPolicy("/tmp", {}, events);
		assert.ok(result);
		assert.equal(result.verification_max_retries, 1);
		assert.equal(result.verification_auto_fix, false);
	});

	it("does_not_reduce_retries_for_closeout_git_failures", () => {
		const events = Array.from({ length: 10 }, () =>
			makeEvent("fail", "closeout"),
		);
		const result = computeAdaptiveVerificationPolicy("/tmp", {}, events);
		assert.equal(result, null);
	});

	it("does_not_reduce_retries_for_git_failures", () => {
		const events = Array.from({ length: 10 }, () => makeEvent("fail", "git"));
		const result = computeAdaptiveVerificationPolicy("/tmp", {}, events);
		assert.equal(result, null);
	});

	// ─── Low failure rate (<30%) with all passing ────────────────────────────

	it("increases_retries_when_all_passing", () => {
		const events = Array.from({ length: 5 }, () => makeEvent("pass"));
		const result = computeAdaptiveVerificationPolicy(
			"/tmp",
			{ verification_max_retries: 2 },
			events,
		);
		assert.ok(result);
		assert.equal(result.verification_max_retries, 3);
		assert.equal(result.verification_auto_fix, true); // unchanged
	});

	it("caps_retries_at_3", () => {
		const events = Array.from({ length: 5 }, () => makeEvent("pass"));
		const result = computeAdaptiveVerificationPolicy(
			"/tmp",
			{ verification_max_retries: 3 },
			events,
		);
		assert.equal(result, null); // already at ceiling
	});

	it("does_not_increase_retries_when_some_failures_exist", () => {
		const events = [
			...Array.from({ length: 4 }, () => makeEvent("pass")),
			makeEvent("fail", "verification"),
		];
		const result = computeAdaptiveVerificationPolicy(
			"/tmp",
			{ verification_max_retries: 2 },
			events,
		);
		assert.equal(result, null);
	});

	// ─── Mixed scenarios ─────────────────────────────────────────────────────

	it("returns_null_when_no_change_needed", () => {
		const events = [
			makeEvent("pass"),
			makeEvent("pass"),
			makeEvent("pass"),
			makeEvent("fail", "unknown"),
			makeEvent("pass"),
		];
		const result = computeAdaptiveVerificationPolicy(
			"/tmp",
			{ verification_max_retries: 2, verification_auto_fix: true },
			events,
		);
		assert.equal(result, null);
	});

	it("uses_defaults_when_prefs_omitted", () => {
		const events = Array.from({ length: 10 }, () =>
			makeEvent("fail", "verification"),
		);
		const result = computeAdaptiveVerificationPolicy("/tmp", {}, events);
		assert.ok(result);
		assert.equal(result.verification_max_retries, 1);
		assert.equal(result.verification_auto_fix, false);
	});

	it("ignores_non_outcome_learning_events", () => {
		const events = [
			...Array.from({ length: 10 }, () => makeEvent("fail", "verification")),
			{ gateId: "cost-guard", outcome: "fail", failureClass: "budget" },
		];
		const result = computeAdaptiveVerificationPolicy("/tmp", {}, events);
		assert.ok(result);
		assert.equal(result.verification_max_retries, 1);
	});
});
