import assert from "node:assert/strict";
import {
	mkdirSync,
	mkdtempSync,
	readFileSync,
	rmSync,
	writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, it } from "vitest";
import {
	readSwarmRegistry,
	stableSwarmId,
	syncSwarmRegistryFromProjects,
} from "./swarm-registry.js";
import type { ProjectInfo } from "./types.js";

const roots: string[] = [];

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

function tmpRoot(): string {
	const root = mkdtempSync(join(tmpdir(), "sf-daemon-swarms-"));
	roots.push(root);
	return root;
}

describe("swarm registry", () => {
	it("stableSwarmId_returns_path_stable_hex_id", () => {
		assert.match(stableSwarmId("/tmp/repo"), /^[a-f0-9]{16}$/);
		assert.equal(stableSwarmId("/tmp/repo"), stableSwarmId("/tmp/repo"));
	});

	it("syncSwarmRegistryFromProjects_writes_sorted_schema_v1_registry", () => {
		const root = tmpRoot();
		const registryPath = join(root, "swarms.json");
		const projects: ProjectInfo[] = [
			{
				name: "z-repo",
				path: join(root, "z-repo"),
				markers: ["git"],
				lastModified: 20,
			},
			{
				name: "a-repo",
				path: join(root, "a-repo"),
				markers: ["sf", "node"],
				lastModified: 30,
			},
		];

		const result = syncSwarmRegistryFromProjects(
			projects,
			registryPath,
			() => new Date("2026-05-17T00:00:00.000Z"),
		);
		const registry = JSON.parse(readFileSync(registryPath, "utf8"));

		assert.equal(result.written, 2);
		assert.equal(registry.schemaVersion, 1);
		assert.equal(registry.updatedAt, "2026-05-17T00:00:00.000Z");
		assert.deepEqual(
			registry.swarms.map((entry: { name: string }) => entry.name),
			["a-repo", "z-repo"],
		);
		assert.equal(registry.swarms[0].supervisor.kind, "daemon-scan");
	});

	it("syncSwarmRegistryFromProjects_preserves_existing_id_and_display_name", () => {
		const root = tmpRoot();
		const registryPath = join(root, "swarms.json");
		const repoPath = join(root, "repo");
		mkdirSync(repoPath);
		writeFileSync(
			registryPath,
			JSON.stringify({
				swarms: [{ id: "manual-id", name: "Display", path: repoPath }],
			}),
		);

		syncSwarmRegistryFromProjects(
			[{ name: "repo", path: repoPath, markers: ["sf"], lastModified: 1 }],
			registryPath,
		);
		const registry = readSwarmRegistry(registryPath);

		assert.equal(registry.swarms[0]?.id, "manual-id");
		assert.equal(registry.swarms[0]?.name, "Display");
	});
});
