import assert from "node:assert/strict";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, test } from "vitest";
import {
	discoverCommands,
	hasMissingProjectPathReferences,
} from "../verification-gate.js";

const tmpRoots = [];

afterEach(() => {
	for (const dir of tmpRoots.splice(0)) {
		rmSync(dir, { recursive: true, force: true });
	}
});

function makeProject() {
	const root = mkdtempSync(join(tmpdir(), "sf-verify-discovery-"));
	tmpRoots.push(root);
	return root;
}

test("discoverCommands_when_preferences_reference_missing_repo_dirs_falls_back_to_python_project", () => {
	const root = makeProject();
	writeFileSync(join(root, "pyproject.toml"), "[project]\nname = 'demo'\n");
	const staleCommand =
		'bash -c \'set -e; for d in "scanner" "supervisor"; do (cd "$d" && cargo check); done\'';

	const result = discoverCommands({
		cwd: root,
		preferenceCommands: [staleCommand, "uv run pytest -x"],
	});

	assert.deepEqual(result, {
		commands: ["python -m pytest -q"],
		source: "python-project",
	});
});

test("discoverCommands_when_for_loop_dirs_exist_keeps_preference_commands", () => {
	const root = makeProject();
	mkdirSync(join(root, "scanner"));
	mkdirSync(join(root, "supervisor"));
	const command =
		'bash -c \'set -e; for d in "scanner" "supervisor"; do (cd "$d" && cargo check); done\'';

	const result = discoverCommands({
		cwd: root,
		preferenceCommands: [command],
	});

	assert.deepEqual(result, {
		commands: [command],
		source: "preference",
	});
});

test("discoverCommands_when_broad_cargo_preferences_conflict_with_task_plan_uses_task_plan", () => {
	const root = makeProject();
	mkdirSync(join(root, "scanner"));
	mkdirSync(join(root, "supervisor"));
	writeFileSync(join(root, "pyproject.toml"), "[project]\nname = 'demo'\n");
	const command =
		'bash -c \'set -e; for d in "scanner" "supervisor"; do (cd "$d" && cargo check); done\'';

	const result = discoverCommands({
		cwd: root,
		preferenceCommands: [command, "uv run pytest -x"],
		taskPlanVerify: "make pytest",
	});

	assert.deepEqual(result, {
		commands: ["make pytest"],
		source: "task-plan",
	});
});

test("discoverCommands_when_broad_cargo_preferences_conflict_with_makefile_uses_python_project", () => {
	const root = makeProject();
	mkdirSync(join(root, "scanner"));
	mkdirSync(join(root, "supervisor"));
	writeFileSync(join(root, "pyproject.toml"), "[project]\nname = 'demo'\n");
	writeFileSync(
		join(root, "Makefile"),
		"verify-python:\n\tpython -m pytest -q\n",
	);
	const command =
		'bash -c \'set -e; for d in "scanner" "supervisor"; do (cd "$d" && cargo check); done\'';

	const result = discoverCommands({
		cwd: root,
		preferenceCommands: [command, "uv run pytest -x"],
	});

	assert.deepEqual(result, {
		commands: ["python -m pytest -q"],
		source: "python-project",
	});
});

test("hasMissingProjectPathReferences_detects_absent_for_loop_cd_targets", () => {
	const root = makeProject();

	assert.equal(
		hasMissingProjectPathReferences(
			root,
			'bash -c \'for d in "scanner"; do (cd "$d" && cargo test); done\'',
		),
		true,
	);
});
