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

// ─── Mock dispatcher to capture routed commands ─────────────────────────

const _lastRouted: string | null = null;
const _lastQuick: string | null = null;

const _mockCtx = {
	ui: {
		notify: (_msg: string, _level: string) => {},
	},
} as any;

// We test the keyword matching logic directly since the handler imports
// the dispatcher dynamically (which requires the full extension runtime).

// Inline the route-matching logic from commands-do.ts for unit testing.
interface Route {
	keywords: string[];
	command: string;
}

const ROUTES: Route[] = [
	{
		keywords: ["progress", "status", "dashboard", "how far", "where are we"],
		command: "status",
	},
	{
		keywords: ["auto", "autonomous", "run all", "keep going", "start auto"],
		command: "auto",
	},
	{ keywords: ["stop", "halt", "abort"], command: "stop" },
	{ keywords: ["pause", "break", "take a break"], command: "pause" },
	{
		keywords: ["history", "past", "what happened", "previous"],
		command: "history",
	},
	{
		keywords: ["doctor", "health", "diagnose", "check health"],
		command: "doctor",
	},
	{
		keywords: ["clean up", "cleanup", "remove old", "prune", "tidy"],
		command: "cleanup",
	},
	{
		keywords: ["ship", "pull request", "create pr", "open pr", "merge"],
		command: "ship",
	},
	{
		keywords: ["discuss", "talk about", "architecture", "design"],
		command: "discuss",
	},
	{ keywords: ["undo", "revert", "rollback", "take back"], command: "undo" },
	{ keywords: ["skip", "skip task", "skip this"], command: "skip" },
	{
		keywords: ["visualize", "viz", "graph", "chart", "show graph"],
		command: "visualize",
	},
	{
		keywords: ["capture", "note", "idea", "thought", "remember"],
		command: "capture",
	},
	{
		keywords: ["inspect", "database", "sqlite", "db state"],
		command: "inspect",
	},
	{
		keywords: ["session report", "session summary", "cost summary", "how much"],
		command: "session-report",
	},
	{
		keywords: ["backlog", "parking lot", "later", "someday"],
		command: "backlog",
	},
	{
		keywords: ["add tests", "write tests", "generate tests", "test coverage"],
		command: "add-tests",
	},
	{ keywords: ["next", "step", "next step", "what's next"], command: "next" },
];

interface MatchResult {
	command: string;
	remainingArgs: string;
	score: number;
}

function matchRoute(input: string): MatchResult | null {
	const lower = input.toLowerCase();
	let bestMatch: MatchResult | null = null;

	for (const route of ROUTES) {
		for (const keyword of route.keywords) {
			if (lower.includes(keyword)) {
				const score = keyword.length;
				if (!bestMatch || score > bestMatch.score) {
					const idx = lower.indexOf(keyword);
					const remaining = (
						input.slice(0, idx) + input.slice(idx + keyword.length)
					).trim();
					bestMatch = {
						command: route.command,
						remainingArgs: remaining,
						score,
					};
				}
			}
		}
	}

	return bestMatch;
}

// ─── Tests ──────────────────────────────────────────────────────────────

test("/sf do: routes 'show me progress' to status", () => {
	const match = matchRoute("show me progress");
	assert.ok(match);
	assert.equal(match.command, "status");
});

test("/sf do: routes 'run autonomously' to auto", () => {
	const match = matchRoute("run autonomously");
	assert.ok(match);
	assert.equal(match.command, "auto");
});

test("/sf do: routes 'clean up old branches' to cleanup", () => {
	const match = matchRoute("clean up old branches");
	assert.ok(match);
	assert.equal(match.command, "cleanup");
	assert.equal(match.remainingArgs, "old branches");
});

test("/sf do: routes 'create pr for milestone' to ship", () => {
	const match = matchRoute("create pr for milestone");
	assert.ok(match);
	assert.equal(match.command, "ship");
});

test("/sf do: routes 'add tests for S03' to add-tests", () => {
	const match = matchRoute("add tests for S03");
	assert.ok(match);
	assert.equal(match.command, "add-tests");
});

test("/sf do: routes 'what is next' to next", () => {
	const match = matchRoute("what's next");
	assert.ok(match);
	assert.equal(match.command, "next");
});

test("/sf do: returns null for unrecognized input", () => {
	const match = matchRoute("florbinate the gizmo");
	assert.equal(match, null);
});

test("/sf do: prefers longer keyword match", () => {
	// "check health" (12 chars) should beat "health" (6 chars)
	const match = matchRoute("check health of the system");
	assert.ok(match);
	assert.equal(match.command, "doctor");
	assert.ok(match.score >= 12);
});

test("/sf do: routes 'session report' to session-report", () => {
	const match = matchRoute("show me the session report");
	assert.ok(match);
	assert.equal(match.command, "session-report");
});
