/**
 * Tests for subagent inheritance audit and enforcement.
 */
import assert from "node:assert";
import { test } from "vitest";
import {
	applyInheritanceToEnv,
	buildSubagentInheritanceEnvelope,
	readParentInheritanceFromEnv,
	validateSubagentDispatch,
} from "../subagent-inheritance.js";

// --- Tests ---

const testBuildEnvelopeDefaults = () => {
	// Without a session, should still return defaults
	const envelope = buildSubagentInheritanceEnvelope({});
	assert.ok(envelope.workMode);
	assert.ok(envelope.modelMode);
	assert.ok(envelope.permissionProfile);
	assert.ok(envelope.runControl);
	assert.ok(envelope.surface);
};

const testBuildEnvelopeWithMode = () => {
	const envelope = buildSubagentInheritanceEnvelope({
		mode: {
			workMode: "build",
			modelMode: "fast",
			permissionProfile: "restricted",
			runControl: "assisted",
			surface: "headless",
		},
	});
	assert.strictEqual(envelope.workMode, "build");
	assert.strictEqual(envelope.modelMode, "fast");
	assert.strictEqual(envelope.permissionProfile, "restricted");
	assert.strictEqual(envelope.runControl, "assisted");
	assert.strictEqual(envelope.surface, "headless");
};

const testValidateAllowedProvider = () => {
	const envelope = {
		workMode: "build",
		modelMode: "smart",
		permissionProfile: "normal",
		runControl: "assisted",
		surface: "tui",
		allowedProviders: ["anthropic"],
		blockedProviders: null,
	};
	const result = validateSubagentDispatch(envelope, {
		model: "anthropic/claude-sonnet",
		provider: "anthropic",
		tools: ["read"],
	});
	assert.strictEqual(result.ok, true);
};

const testValidateBlockedProvider = () => {
	const envelope = {
		workMode: "build",
		modelMode: "smart",
		permissionProfile: "normal",
		runControl: "assisted",
		surface: "tui",
		allowedProviders: null,
		blockedProviders: ["openai"],
	};
	const result = validateSubagentDispatch(envelope, {
		model: "openai/gpt-4",
		provider: "openai",
		tools: ["read"],
	});
	assert.strictEqual(result.ok, false);
	assert.ok(result.reason.includes("blocked"));
};

const testValidateFastBlocksHeavy = () => {
	const envelope = {
		workMode: "build",
		modelMode: "fast",
		permissionProfile: "trusted",
		runControl: "assisted",
		surface: "tui",
		allowedProviders: null,
		blockedProviders: null,
	};
	const result = validateSubagentDispatch(envelope, {
		model: "claude-3-opus",
		provider: "anthropic",
		tools: ["read"],
	});
	assert.strictEqual(result.ok, false);
	assert.ok(result.reason.includes("fast"));
};

const testValidateRestrictedBlocksDestructive = () => {
	const envelope = {
		workMode: "build",
		modelMode: "smart",
		permissionProfile: "restricted",
		runControl: "assisted",
		surface: "tui",
		allowedProviders: null,
		blockedProviders: null,
	};
	const result = validateSubagentDispatch(envelope, {
		model: "claude-sonnet",
		provider: "anthropic",
		tools: ["write", "read"],
	});
	assert.strictEqual(result.ok, false);
	assert.ok(result.reason.includes("write"));
};

const testApplyInheritanceToEnv = () => {
	const envelope = {
		workMode: "review",
		modelMode: "deep",
		permissionProfile: "trusted",
		runControl: "autonomous",
		surface: "headless",
	};
	const env = applyInheritanceToEnv(envelope, {});
	assert.strictEqual(env.SF_PARENT_WORK_MODE, "review");
	assert.strictEqual(env.SF_PARENT_MODEL_MODE, "deep");
	assert.strictEqual(env.SF_PARENT_PERMISSION_PROFILE, "trusted");
	assert.strictEqual(env.SF_PARENT_RUN_CONTROL, "autonomous");
	assert.strictEqual(env.SF_PARENT_SURFACE, "headless");
};

const testReadParentFromEnv = () => {
	const env = {
		SF_PARENT_WORK_MODE: "repair",
		SF_PARENT_MODEL_MODE: "smart",
		SF_PARENT_PERMISSION_PROFILE: "normal",
		SF_PARENT_RUN_CONTROL: "assisted",
		SF_PARENT_SURFACE: "tui",
	};
	const result = readParentInheritanceFromEnv(env);
	assert.strictEqual(result.workMode, "repair");
	assert.strictEqual(result.modelMode, "smart");
	assert.strictEqual(result.permissionProfile, "normal");
	assert.strictEqual(result.runControl, "assisted");
	assert.strictEqual(result.surface, "tui");
};

const testReadParentFromEnvMissing = () => {
	const result = readParentInheritanceFromEnv({});
	assert.strictEqual(result, null);
};

test(
	"buildSubagentInheritanceEnvelope_defaults_are_resolved",
	testBuildEnvelopeDefaults,
);
test(
	"buildSubagentInheritanceEnvelope_uses_explicit_mode_axes",
	testBuildEnvelopeWithMode,
);
test(
	"validateSubagentDispatch_allows_allowed_provider",
	testValidateAllowedProvider,
);
test(
	"validateSubagentDispatch_blocks_blocked_provider",
	testValidateBlockedProvider,
);
test(
	"validateSubagentDispatch_fast_blocks_heavy_model",
	testValidateFastBlocksHeavy,
);
test(
	"validateSubagentDispatch_restricted_blocks_destructive_tools",
	testValidateRestrictedBlocksDestructive,
);
test("applyInheritanceToEnv_writes_parent_axes", testApplyInheritanceToEnv);
test("readParentInheritanceFromEnv_reads_parent_axes", testReadParentFromEnv);
test(
	"readParentInheritanceFromEnv_returns_null_without_parent",
	testReadParentFromEnvMissing,
);
