import assert from "node:assert/strict";
import { test } from 'vitest';

import { registerSFCommand } from "../commands.ts";
import { handleUpdate } from "../commands-handlers.ts";

function createMockPi() {
	const commands = new Map<string, any>();
	return {
		registerCommand(name: string, options: any) {
			commands.set(name, options);
		},
		registerTool() {},
		registerShortcut() {},
		on() {},
		sendMessage() {},
		commands,
	};
}

function _createMockCtx() {
	const notifications: { message: string; level: string }[] = [];
	let reloadCount = 0;
	return {
		notifications,
		get reloadCount() {
			return reloadCount;
		},
		ui: {
			notify(message: string, level: string) {
				notifications.push({ message, level });
			},
			custom: async () => {},
		},
		reload: async () => {
			reloadCount++;
		},
		shutdown: async () => {},
	};
}

test("/sf update reloads current session after successful install", async () => {
	const ctx = _createMockCtx();
	let installedCommand = "";

	await handleUpdate(ctx as any, {
		currentVersion: "1.0.0",
		fetchLatestVersion: async () => "1.0.1",
		install: (command) => {
			installedCommand = command;
		},
	});

	assert.match(installedCommand, /sf-run@latest/);
	assert.equal(ctx.reloadCount, 1);
	assert.ok(
		ctx.notifications.some((entry) =>
			entry.message.includes("Reloaded current session"),
		),
		"successful update should reload the current session automatically",
	);
});

test("/sf update appears in subcommand completions", () => {
	const pi = createMockPi();
	registerSFCommand(pi as any);

	const sf = pi.commands.get("sf");
	assert.ok(sf, "registerSFCommand should register /sf");

	const completions = sf.getArgumentCompletions("update");
	const updateEntry = completions.find((c: any) => c.value === "update");
	assert.ok(updateEntry, "update should appear in completions");
	assert.equal(updateEntry.label, "update");
});

test("/sf update appears in help description", () => {
	const pi = createMockPi();
	registerSFCommand(pi as any);

	const sf = pi.commands.get("sf");
	assert.ok(
		sf?.description?.includes("update"),
		"description should mention update",
	);
});

test("/sf update is listed in completions with correct description", () => {
	const pi = createMockPi();
	registerSFCommand(pi as any);

	const sf = pi.commands.get("sf");
	const completions = sf.getArgumentCompletions("");
	const updateEntry = completions.find((c: any) => c.value === "update");
	assert.ok(updateEntry, "update should appear in full completion list");
	assert.ok(
		updateEntry.description.toLowerCase().includes("update"),
		"completion description should mention updating",
	);
});

test("/sf codebase appears in top-level completions", () => {
	const pi = createMockPi();
	registerSFCommand(pi as any);

	const sf = pi.commands.get("sf");
	const completions = sf.getArgumentCompletions("code");
	const codebaseEntry = completions.find((c: any) => c.value === "codebase");
	assert.ok(codebaseEntry, "codebase should appear in completions");
	assert.match(codebaseEntry.description, /codebase map cache/i);
});

test("/sf codebase appears in help description", () => {
	const pi = createMockPi();
	registerSFCommand(pi as any);

	const sf = pi.commands.get("sf");
	assert.ok(
		sf?.description?.includes("codebase"),
		"description should mention codebase",
	);
});
