import assert from "node:assert/strict";
import { mkdtemp, readFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";

import { deployBundleLspConfig, materializeBundleLspConfig } from "../extensions/lsp-config.ts";

const RUNTIME = {
	nodeBinary: "/runtime/node",
	serverCliPath: "/bundle/typescript-language-server/lib/cli.mjs",
};

test("LSP config materializes the bundled TypeScript server command", () => {
	const source = JSON.stringify({
		version: 1,
		servers: [
			{ id: "typescript-language-server", bin: "typescript-language-server", args: ["--stdio"] },
			{ id: "jdtls", bin: "jdtls", args: [] },
		],
	});
	const config = JSON.parse(materializeBundleLspConfig(source, RUNTIME));

	assert.deepEqual(config.servers[0], {
		id: "typescript-language-server",
		bin: RUNTIME.nodeBinary,
		args: [RUNTIME.serverCliPath, "--stdio"],
	});
	assert.deepEqual(config.servers[1], { id: "jdtls", bin: "jdtls", args: [] });
});

test("LSP config deployment writes the materialized bundle config", async () => {
	const agentDir = await mkdtemp(join(tmpdir(), "my-pi-lsp-"));
	try {
		deployBundleLspConfig(agentDir, RUNTIME);
		const config = JSON.parse(await readFile(join(agentDir, "lsp.json"), "utf8"));
		const server = config.servers.find((entry: { id?: string }) => entry.id === "typescript-language-server");

		assert.equal(server.bin, RUNTIME.nodeBinary);
		assert.deepEqual(server.args, [RUNTIME.serverCliPath, "--stdio"]);
		assert.deepEqual(server.include, [
			"**/*.ts",
			"**/*.tsx",
			"**/*.mts",
			"**/*.cts",
			"**/*.js",
			"**/*.jsx",
			"**/*.mjs",
			"**/*.cjs",
		]);
	} finally {
		await rm(agentDir, { recursive: true, force: true });
	}
});
