import assert from "node:assert/strict";
import { describe, test } from "vitest";
import {
	buildExecutionPolicyJournalEntry,
	classifyExecutionPolicyCall,
	extractExecutionPolicyInput,
	resolveExecutionPolicyProfile,
} from "../execution-policy.js";

describe("execution policy profiles", () => {
	test("resolveExecutionPolicyProfile_when_unknown_returns_restricted_profile", () => {
		assert.equal(resolveExecutionPolicyProfile("missing").id, "restricted");
	});

	test("classifyExecutionPolicyCall_restricted_allows_read_only_bash", () => {
		const decision = classifyExecutionPolicyCall(
			"restricted",
			"Bash",
			"git status",
		);

		assert.equal(decision.allowed, true);
		assert.equal(decision.profile, "restricted");
		assert.equal(decision.permissionProfile, "restricted");
	});

	test("classifyExecutionPolicyCall_restricted_blocks_source_write", () => {
		const decision = classifyExecutionPolicyCall(
			"restricted",
			"Write",
			"src/app.ts",
		);

		assert.equal(decision.allowed, false);
		assert.match(decision.reason, /planning tool/i);
	});

	test("classifyExecutionPolicyCall_restricted_allows_sf_artifact_write", () => {
		const decision = classifyExecutionPolicyCall(
			"restricted",
			"Write",
			".sf/milestones/M001/CONTEXT.md",
		);

		assert.equal(decision.allowed, true);
	});

	test("classifyExecutionPolicyCall_normal_marks_destructive_bash_but_allows_for_later_gate", () => {
		const decision = classifyExecutionPolicyCall(
			"normal",
			"Bash",
			"git reset --hard",
		);

		assert.equal(decision.allowed, true);
		assert.equal(decision.permissionProfile, "normal");
		assert.equal(decision.risk, "destructive");
		assert.deepEqual(decision.destructiveLabels, ["hard reset"]);
	});

	test("resolveExecutionPolicyProfile_when_trusted_returns_trusted_permission_profile", () => {
		const profile = resolveExecutionPolicyProfile("trusted");
		const decision = classifyExecutionPolicyCall(
			"trusted",
			"Bash",
			"git status",
		);

		assert.equal(profile.id, "trusted");
		assert.equal(profile.permissionProfile, "trusted");
		assert.equal(decision.profile, "trusted");
		assert.equal(decision.permissionProfile, "trusted");
		assert.equal(decision.allowed, true);
	});

	test("extractExecutionPolicyInput_uses_command_or_path_without_full_payload", () => {
		assert.equal(
			extractExecutionPolicyInput("Bash", {
				command: "git status",
				extra: "x",
			}),
			"git status",
		);
		assert.equal(
			extractExecutionPolicyInput("Write", {
				path: "src/app.ts",
				content: "x",
			}),
			"src/app.ts",
		);
	});

	test("buildExecutionPolicyJournalEntry_records_tool_decision", () => {
		const entry = buildExecutionPolicyJournalEntry({
			now: () => "2026-05-07T16:30:00.000Z",
			profileId: "restricted",
			unit: { type: "execute-task", id: "M001/S01/T01" },
			event: {
				toolCallId: "call-1",
				toolName: "Write",
				input: { path: "src/app.ts", content: "secret body" },
			},
		});

		assert.equal(entry.eventType, "execution-policy-decision");
		assert.equal(entry.unitType, "execute-task");
		assert.equal(entry.data.toolName, "Write");
		assert.equal(entry.data.input, "src/app.ts");
		assert.equal(entry.data.decision.allowed, false);
		assert.equal(entry.data.decision.profile, "restricted");
		assert.equal(entry.data.decision.permissionProfile, "restricted");
	});
});
