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 { pathToFileURL } from "node:url";
import { afterEach, test } from "vitest";

const { resolveSfCliEntry } = await import("../../web/cli-entry.ts");

function makeFixture(paths: string[]): string {
	const root = mkdtempSync(join(tmpdir(), "sf-cli-entry-"));
	for (const relativePath of paths) {
		const fullPath = join(root, relativePath);
		mkdirSync(join(fullPath, ".."), { recursive: true });
		writeFileSync(fullPath, "// fixture\n");
	}
	return root;
}

test("resolveSfCliEntry prefers the built loader for packaged standalone interactive sessions", (_t) => {
	const packageRoot = makeFixture([
		"dist/loader.js",
		"src/loader.ts",
		"src/resources/extensions/sf/tests/resolve-ts.mjs",
	]);

	afterEach(() => {
		rmSync(packageRoot, { recursive: true, force: true });
	});

	const entry = resolveSfCliEntry({
		packageRoot,
		cwd: "/tmp/project-a",
		execPath: "/custom/node",
		hostKind: "packaged-standalone",
		mode: "interactive",
	});

	assert.deepEqual(entry, {
		command: "/custom/node",
		args: [join(packageRoot, "dist", "loader.js")],
		cwd: "/tmp/project-a",
	});
});

test("resolveSfCliEntry prefers the source loader for source-dev interactive sessions", (_t) => {
	const packageRoot = makeFixture([
		"dist/loader.js",
		"src/loader.ts",
		"src/resources/extensions/sf/tests/resolve-ts.mjs",
	]);

	afterEach(() => {
		rmSync(packageRoot, { recursive: true, force: true });
	});

	const entry = resolveSfCliEntry({
		packageRoot,
		cwd: "/tmp/project-b",
		execPath: "/custom/node",
		hostKind: "source-dev",
		mode: "interactive",
	});

	assert.deepEqual(entry, {
		command: "/custom/node",
		args: [
			"--import",
			pathToFileURL(
				join(
					packageRoot,
					"src",
					"resources",
					"extensions",
					"sf",
					"tests",
					"resolve-ts.mjs",
				),
			).href,
			"--experimental-strip-types",
			join(packageRoot, "src", "loader.ts"),
		],
		cwd: "/tmp/project-b",
	});
});

test("resolveSfCliEntry appends rpc arguments for bridge sessions", (_t) => {
	const packageRoot = makeFixture(["dist/loader.js"]);

	afterEach(() => {
		rmSync(packageRoot, { recursive: true, force: true });
	});

	const entry = resolveSfCliEntry({
		packageRoot,
		cwd: "/tmp/project-c",
		execPath: "/custom/node",
		hostKind: "packaged-standalone",
		mode: "rpc",
		sessionDir: "/tmp/.sf/sessions/project-c",
	});

	assert.deepEqual(entry, {
		command: "/custom/node",
		args: [
			join(packageRoot, "dist", "loader.js"),
			"--mode",
			"rpc",
			"--continue",
			"--session-dir",
			"/tmp/.sf/sessions/project-c",
		],
		cwd: "/tmp/project-c",
	});
});
