import assert from "node:assert/strict";
import { afterEach, describe, it } from 'vitest';
import type { ToolResultEvent } from "@singularity-forge/pi-coding-agent";
import {
	observeMemorySleeperToolResult,
	resetMemorySleeper,
} from "../memory-sleeper.ts";

function bashResult(args: {
	command: string;
	text?: string;
	isError?: boolean;
}): ToolResultEvent {
	return {
		type: "tool_result",
		toolName: "bash",
		toolCallId: "tool-1",
		input: { command: args.command },
		content: [{ type: "text", text: args.text ?? "" }],
		details: undefined,
		isError: args.isError ?? false,
	} as ToolResultEvent;
}

function customResult(text: string): ToolResultEvent {
	return {
		type: "tool_result",
		toolName: "sf_auto",
		toolCallId: "tool-2",
		input: {},
		content: [{ type: "text", text }],
		details: undefined,
		isError: true,
	} as ToolResultEvent;
}

describe("memory sleeper steering", () => {
	afterEach(() => {
		resetMemorySleeper();
	});

	it("steers bun commands toward Node/npm and dedupes the correction", () => {
		const first = observeMemorySleeperToolResult(
			bashResult({ command: "bun run test", isError: false }),
		);
		const second = observeMemorySleeperToolResult(
			bashResult({ command: "bun run lint", isError: false }),
		);

		assert.equal(first?.key, "bun-command");
		assert.match(first?.content ?? "", /Node\/npm/);
		assert.equal(second, undefined);
	});

	it("does not require an error to catch forbidden command choices", () => {
		const steer = observeMemorySleeperToolResult(
			bashResult({ command: "bunx biome check src", isError: false }),
		);

		assert.equal(steer?.severity, "warning");
		assert.match(steer?.content ?? "", /Replace Bun commands/);
	});

	it("steers on repeated identical bash failures", () => {
		const first = observeMemorySleeperToolResult(
			bashResult({
				command: "npm run test:sf-light",
				text: "suite failed",
				isError: true,
			}),
		);
		const second = observeMemorySleeperToolResult(
			bashResult({
				command: "npm run test:sf-light",
				text: "suite failed again",
				isError: true,
			}),
		);
		const third = observeMemorySleeperToolResult(
			bashResult({
				command: "npm run test:sf-light",
				text: "suite failed a third time",
				isError: true,
			}),
		);

		assert.equal(first, undefined);
		assert.match(second?.content ?? "", /same bash command has failed 2 times/);
		assert.equal(third, undefined);
	});

	it("recognizes the dispatcher import failure from command extension startup", () => {
		const steer = observeMemorySleeperToolResult(
			customResult(
				"Extension command:sf error: Cannot find module '/home/mhugo/.sf/agent/extensions/sf/commands/dispatcher.js' imported from index.js",
			),
		);

		assert.equal(steer?.key, "sf-dispatcher-import");
		assert.match(steer?.content ?? "", /extension sync\/build path/);
	});

	it("recognizes the exec-policy rules permission trap", () => {
		const steer = observeMemorySleeperToolResult(
			customResult(
				"Failed to apply execpolicy amendment: failed to update rules file /home/mhugo/.codex/rules/default.rules: Permission denied",
			),
		);

		assert.equal(steer?.key, "exec-policy-permission");
		assert.match(steer?.content ?? "", /read-only symlink/);
	});
});
