import * as fs from "fs";
import * as path from "path";
import * as os from "os";
import * as vscode from "vscode";

/**
 * The MCP server entry that gets added to Cursor's mcp.json.
 * Uses stdio transport -- Cursor spawns the process and speaks MCP over stdin/stdout.
 * The same process also starts the management API on port 19420 for the sidebar.
 *
 * Command resolution order:
 *   1. If `mcp-grid` binary is on PATH (pip/pipx/uvx install), use that.
 *   2. Otherwise fall back to `python3 -m mcp_bridge.server`.
 */
function getMcpGridEntry(pythonPath: string): Record<string, unknown> {
  // Read user preferences for metrics
  const cfg = vscode.workspace.getConfiguration("mcpGrid");
  const metricsEnabled = cfg.get<boolean>("metricsEnabled", true);
  const retentionDays = cfg.get<number>("metricsRetentionDays", 30);

  const env: Record<string, string> = {};
  if (!metricsEnabled) {
    env["MCP_BRIDGE_METRICS_ENABLED"] = "false";
  }
  if (retentionDays !== 30) {
    env["MCP_BRIDGE_METRICS_RETENTION_DAYS"] = String(retentionDays);
  }

  // Try to use the installed `mcp-grid` CLI entry point first.
  // This works for pip install, pipx install, and uvx run.
  const { execSync } = require("child_process");
  try {
    const bin = execSync("which mcp-grid", { encoding: "utf-8" }).trim();
    if (bin) {
      const entry: Record<string, unknown> = { type: "stdio", command: bin, args: [] };
      if (Object.keys(env).length > 0) { entry.env = env; }
      return entry;
    }
  } catch {
    // `which` failed -- fall through to python3 fallback
  }

  const entry: Record<string, unknown> = {
    type: "stdio",
    command: pythonPath,
    args: ["-m", "mcp_bridge.server"],
  };
  if (Object.keys(env).length > 0) { entry.env = env; }
  return entry;
}

/**
 * Get the path to Cursor's global mcp.json config file.
 */
function getCursorMcpConfigPath(): string {
  return path.join(os.homedir(), ".cursor", "mcp.json");
}

/**
 * Read the current Cursor MCP config, or return an empty structure.
 */
function readMcpConfig(configPath: string): Record<string, unknown> {
  try {
    if (fs.existsSync(configPath)) {
      const raw = fs.readFileSync(configPath, "utf-8");
      return JSON.parse(raw);
    }
  } catch (err) {
    console.warn("[MCP Grid] Failed to read mcp.json:", err);
  }
  return { mcpServers: {} };
}

/**
 * Write the MCP config back to disk.
 */
function writeMcpConfig(
  configPath: string,
  config: Record<string, unknown>
): boolean {
  try {
    // Ensure .cursor directory exists
    const dir = path.dirname(configPath);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
    return true;
  } catch (err) {
    console.error("[MCP Grid] Failed to write mcp.json:", err);
    return false;
  }
}

/**
 * Check if MCP Grid is already registered in Cursor's MCP config.
 */
export function isMcpGridRegistered(): boolean {
  const configPath = getCursorMcpConfigPath();
  const config = readMcpConfig(configPath);
  const servers = (config.mcpServers || {}) as Record<string, unknown>;
  return "mcp-grid" in servers;
}

/**
 * Register MCP Grid in Cursor's global mcp.json.
 *
 * Adds the entry if not already present. Does NOT overwrite an existing entry
 * (in case the user customized it).
 *
 * Returns true if the entry was added, false if it was already there.
 */
export async function registerMcpServer(): Promise<boolean> {
  const configPath = getCursorMcpConfigPath();
  const config = readMcpConfig(configPath);

  const servers = (config.mcpServers || {}) as Record<string, unknown>;

  if ("mcp-grid" in servers) {
    console.log("[MCP Grid] Already registered in mcp.json");
    return false;
  }

  const pythonPath = vscode.workspace
    .getConfiguration("mcpGrid")
    .get<string>("pythonPath", "python3");

  servers["mcp-grid"] = getMcpGridEntry(pythonPath);
  config.mcpServers = servers;

  const success = writeMcpConfig(configPath, config);

  if (success) {
    console.log("[MCP Grid] Registered in Cursor MCP config at", configPath);
    vscode.window
      .showInformationMessage(
        "MCP Grid registered as an MCP server. Reload the window for the agent to see the 21 tools.",
        "Reload Window"
      )
      .then((choice) => {
        if (choice === "Reload Window") {
          vscode.commands.executeCommand("workbench.action.reloadWindow");
        }
      });
    return true;
  }

  vscode.window.showErrorMessage(
    "Failed to register MCP Grid in Cursor config. You can manually add it to ~/.cursor/mcp.json."
  );
  return false;
}

/**
 * Unregister MCP Grid from Cursor's mcp.json.
 */
export function unregisterMcpServer(): boolean {
  const configPath = getCursorMcpConfigPath();
  const config = readMcpConfig(configPath);
  const servers = (config.mcpServers || {}) as Record<string, unknown>;

  if (!("mcp-grid" in servers)) {
    return false;
  }

  delete servers["mcp-grid"];
  config.mcpServers = servers;
  return writeMcpConfig(configPath, config);
}
