/**
 * MCP Status — `/mcp` command handler.
 *
 * Shows configured MCP servers, their connection status, and available tools.
 *
 * Subcommands:
 *   /mcp             — Overview of all servers (alias: /mcp status)
 *   /mcp status      — Same as bare /mcp
 *   /mcp check <srv> — Detailed status for a specific server
 */
import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";

function readMcpConfigs() {
	const servers = [];
	const seen = new Set();
	const configPaths = [
		join(process.cwd(), ".mcp.json"),
		join(process.cwd(), ".sf", "mcp.json"),
	];
	for (const configPath of configPaths) {
		try {
			if (!existsSync(configPath)) continue;
			const raw = readFileSync(configPath, "utf-8");
			const data = JSON.parse(raw);
			const mcpServers = data.mcpServers ?? data.servers;
			if (!mcpServers || typeof mcpServers !== "object") continue;
			for (const [name, config] of Object.entries(mcpServers)) {
				if (seen.has(name)) continue;
				seen.add(name);
				const hasCommand = typeof config.command === "string";
				const hasUrl = typeof config.url === "string";
				const transport = hasCommand ? "stdio" : hasUrl ? "http" : "unknown";
				servers.push({
					name,
					transport,
					...(hasCommand && {
						command: config.command,
						args: Array.isArray(config.args) ? config.args : undefined,
					}),
					...(hasUrl && { url: config.url }),
				});
			}
		} catch {
			// Non-fatal — config file may not exist or be malformed
		}
	}
	return servers;
}
// ─── Formatters (exported for testing) ──────────────────────────────────────
export function formatMcpStatusReport(servers) {
	if (servers.length === 0) {
		return [
			"No MCP servers configured.",
			"",
			"Add external tool servers to .mcp.json or .sf/mcp.json to enable MCP integrations.",
			"SF does not expose its own workflow as an MCP server.",
			"See: https://modelcontextprotocol.io/quickstart",
		].join("\n");
	}
	const lines = [`MCP Server Status — ${servers.length} server(s)\n`];
	for (const s of servers) {
		const icon = s.error ? "✗" : s.connected ? "✓" : "○";
		const status = s.error
			? `error: ${s.error}`
			: s.connected
				? `connected — ${s.toolCount} tools`
				: "disconnected";
		lines.push(`  ${icon} ${s.name} (${s.transport}) — ${status}`);
	}
	lines.push("");
	lines.push("Use /mcp check <server> for details on a specific server.");
	lines.push("Use mcp_discover to connect and list tools for a server.");
	return lines.join("\n");
}
export function formatMcpServerDetail(server) {
	const lines = [`MCP Server: ${server.name}\n`];
	lines.push(`  Transport: ${server.transport}`);
	if (server.error) {
		lines.push(`  Status:    error`);
		lines.push(`  Error:     ${server.error}`);
	} else if (server.connected) {
		lines.push(`  Status:    connected`);
		lines.push(`  Tools:     ${server.toolCount}`);
		if (server.tools.length > 0) {
			lines.push("");
			lines.push("  Available tools:");
			for (const tool of server.tools) {
				lines.push(`    - ${tool}`);
			}
		}
	} else {
		lines.push(`  Status:    disconnected`);
		lines.push("");
		lines.push(
			`  Run mcp_discover("${server.name}") to connect and list tools.`,
		);
	}
	return lines.join("\n");
}
// ─── Command handler ────────────────────────────────────────────────────────
/**
 * Handle `/mcp [status|check <server>|reload]`.
 */
export async function handleMcpStatus(args, ctx) {
	const trimmed = args.trim();
	const lowered = trimmed.toLowerCase();
	const configs = readMcpConfigs();
	if (!lowered || lowered === "status") {
		// handled below
	} else if (lowered === "init" || lowered.startsWith("init ")) {
		ctx.ui.notify(
			"SF workflow MCP exposure is disabled. Configure only external MCP tool servers in .mcp.json or .sf/mcp.json.",
			"warning",
		);
		return;
	}
	// /mcp reload — disconnect all, re-read config, reconnect lazily on next use
	if (lowered === "reload") {
		try {
			const mcpClient = await import("../mcp-client/index.js");
			if (typeof mcpClient.disconnectAll === "function") {
				await mcpClient.disconnectAll();
				const fresh = readMcpConfigs();
				ctx.ui.notify(
					`MCP servers reloaded — ${fresh.length} server(s) configured. Connections will re-establish on next use.\n\n${fresh.map((s) => `  ○ ${s.name} (${s.transport})`).join("\n") || "  (none)"}`,
					"info",
				);
			} else {
				ctx.ui.notify(
					"MCP client does not support hot-reload. Use /reload to restart the extension layer.",
					"warning",
				);
			}
		} catch {
			ctx.ui.notify(
				"Failed to reload MCP servers. Config may be invalid — check .mcp.json or .sf/mcp.json.",
				"error",
			);
		}
		return;
	}
	// /mcp check <server>
	if (lowered.startsWith("check ")) {
		const serverName = trimmed.slice("check ".length).trim();
		const config = configs.find((c) => c.name === serverName);
		if (!config) {
			const available = configs.map((c) => c.name).join(", ") || "(none)";
			ctx.ui.notify(
				`Unknown MCP server: "${serverName}"\n\nAvailable: ${available}`,
				"warning",
			);
			return;
		}
		// Try to get connection/tool info from the mcp-client module if available
		let connected = false;
		let toolNames = [];
		let error;
		try {
			const mcpClient = await import("../mcp-client/index.js");
			// Access the module's connection state if exported; fall back gracefully
			const mod = mcpClient;
			if (typeof mod.getConnectionStatus === "function") {
				const status = mod.getConnectionStatus(serverName);
				connected = status.connected;
				toolNames = status.tools;
				error = status.error;
			}
		} catch {
			// mcp-client may not expose status helpers — that's fine
		}
		ctx.ui.notify(
			formatMcpServerDetail({
				name: config.name,
				transport: config.transport,
				connected,
				toolCount: toolNames.length,
				tools: toolNames,
				error,
			}),
			"info",
		);
		return;
	}
	// /mcp or /mcp status
	if (!lowered || lowered === "status") {
		// Build status for each server
		const statuses = [];
		for (const config of configs) {
			let connected = false;
			let toolCount = 0;
			let error;
			try {
				const mcpClient = await import("../mcp-client/index.js");
				const mod = mcpClient;
				if (typeof mod.getConnectionStatus === "function") {
					const status = mod.getConnectionStatus(config.name);
					connected = status.connected;
					toolCount = status.tools.length;
					error = status.error;
				}
			} catch {
				// Fall back to unknown state
			}
			statuses.push({
				name: config.name,
				transport: config.transport,
				connected,
				toolCount,
				error,
			});
		}
		ctx.ui.notify(formatMcpStatusReport(statuses), "info");
		return;
	}
	// Unknown subcommand
	ctx.ui.notify(
		"Usage: /mcp [status|check <server>|reload]\n\n" +
			"  status           Show all MCP server statuses (default)\n" +
			"  check <server>   Detailed status for a specific server\n" +
			"  reload           Disconnect all servers and re-read config (no restart needed)",
		"warning",
	);
}
