#!/usr/bin/env bash
set -e

MCP_URL="https://api.lens.thoughtindustries.com/mcp"
KEY="$LENS_API_KEY"
SERVER_NAME="$LENS_SERVER_NAME"

if [ -z "$KEY" ]; then
  echo "Set LENS_API_KEY to an MCP API key, then run this command again." >&2
  exit 1
fi

warn() { echo "Warning: $1" >&2; }

confirm_override() {
  client="$1"
  if [ ! -r /dev/tty ]; then
    warn "$client already has a server named '$SERVER_NAME'; skipping it."
    return 1
  fi
  reply=""
  read -r -p "$client already has '$SERVER_NAME'. Override it? [y/N] " reply </dev/tty || return 1
  case "$reply" in [yY]|[yY][eE][sS]) return 0 ;; esac
  return 1
}

json_server_exists() {
  target="$1"
  server_key="$2"
  [ -f "$target" ] || return 1
  command -v node >/dev/null 2>&1 || return 1
  MCP_CONFIG="$target" MCP_SERVER_KEY="$server_key" MCP_SERVER_NAME="$SERVER_NAME" node <<'NODE'
const fs = require("fs");
try {
  const config = JSON.parse(fs.readFileSync(process.env.MCP_CONFIG, "utf8"));
  const servers = config?.[process.env.MCP_SERVER_KEY];
  process.exit(
    servers && typeof servers === "object" && !Array.isArray(servers) &&
      Object.hasOwn(servers, process.env.MCP_SERVER_NAME)
      ? 0
      : 1,
  );
} catch {
  process.exit(1);
}
NODE
}

if [ -z "$SERVER_NAME" ] && [ -r /dev/tty ]; then
  read -r -p "MCP server name [lens-ai]: " SERVER_NAME </dev/tty || true
fi
if [ -z "$SERVER_NAME" ]; then
  SERVER_NAME="lens-ai"
fi
case "$SERVER_NAME" in
  *[!a-zA-Z0-9_-]*)
    echo "MCP server name may only contain letters, numbers, hyphens, and underscores." >&2
    exit 1
    ;;
esac

merge_json() {
  target="$1"
  server_key="$2"
  client="$3"
  if ! command -v node >/dev/null 2>&1; then
    warn "Node.js is required to configure $target."
    return 1
  fi
  mkdir -p "$(dirname "$target")"
  MCP_CONFIG="$target" MCP_SERVER_KEY="$server_key" MCP_CLIENT="$client" MCP_URL="$MCP_URL" MCP_KEY="$KEY" MCP_SERVER_NAME="$SERVER_NAME" node <<'NODE'
const fs = require("fs");
const path = process.env.MCP_CONFIG;
const serverKey = process.env.MCP_SERVER_KEY;
let config = {};
if (fs.existsSync(path)) {
  try {
    config = JSON.parse(fs.readFileSync(path, "utf8"));
  } catch {
    console.error("Existing configuration is invalid JSON; it was not changed.");
    process.exit(1);
  }
}
if (!config || typeof config !== "object" || Array.isArray(config)) {
  console.error("Existing configuration must be a JSON object; it was not changed.");
  process.exit(1);
}
if (!config[serverKey]) config[serverKey] = {};
if (typeof config[serverKey] !== "object" || Array.isArray(config[serverKey])) {
  console.error("Existing server configuration must be a JSON object; it was not changed.");
  process.exit(1);
}
config[serverKey][process.env.MCP_SERVER_NAME] =
  process.env.MCP_CLIENT === "claude-desktop"
    ? {
        command: "npx",
        args: [
          "-y",
          "mcp-remote",
          process.env.MCP_URL,
          "--header",
          "Authorization:${AUTH_HEADER}",
        ],
        env: { AUTH_HEADER: "Bearer " + process.env.MCP_KEY },
      }
    : {
        type: "http",
        url: process.env.MCP_URL,
        headers: { Authorization: "Bearer " + process.env.MCP_KEY },
      };
fs.writeFileSync(path + ".tmp", JSON.stringify(config, null, 2) + "\n");
fs.renameSync(path + ".tmp", path);
NODE
}

vscode_config_path() {
  case "$(uname)" in
    Darwin) echo "$HOME/Library/Application Support/Code/User/mcp.json" ;;
    Linux) echo "$HOME/.config/Code/User/mcp.json" ;;
    *) echo "$APPDATA/Code/User/mcp.json" ;;
  esac
}

echo "Choose assistants to configure:"
echo "  1) Claude Desktop"
echo "  2) Claude Code"
echo "  3) Cursor"
echo "  4) VS Code"
echo "  5) Codex"
clients="$LENS_CLIENTS"
if [ -z "$clients" ]; then
  if [ ! -r /dev/tty ]; then
    echo "Set LENS_CLIENTS (for example, 1 3) when running without a terminal." >&2
    exit 1
  fi
  if ! read -r -p "Numbers, separated by spaces: " clients </dev/tty; then
    echo "No assistants selected." >&2
    exit 1
  fi
fi

failed=0
for client in $clients; do
  case "$client" in
    1)
      if [ "$(uname)" = "Darwin" ]; then
        path="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
      else
        path="$HOME/.config/Claude/claude_desktop_config.json"
      fi
      if json_server_exists "$path" "mcpServers" && ! confirm_override "Claude Desktop"; then
        echo "Claude Desktop left unchanged."
      elif merge_json "$path" "mcpServers" "claude-desktop"; then
        echo "Claude Desktop configured. Restart it to load Lens."
      else
        failed=1
      fi
      ;;
    2)
      if ! command -v claude >/dev/null 2>&1; then
        warn "Claude Code CLI is not installed; skipping."
        failed=1
      else
        if claude mcp get "$SERVER_NAME" >/dev/null 2>&1 && ! confirm_override "Claude Code"; then
          echo "Claude Code left unchanged."
          continue
        fi
        claude mcp remove --scope user "$SERVER_NAME" >/dev/null 2>&1 || true
        if ! claude mcp add --scope user --transport http "$SERVER_NAME" "$MCP_URL" --header "Authorization: Bearer $KEY"; then
          warn "Claude Code configuration failed; skipping."
          failed=1
        fi
      fi
      ;;
    3)
      path="$HOME/.cursor/mcp.json"
      if json_server_exists "$path" "mcpServers" && ! confirm_override "Cursor"; then
        echo "Cursor left unchanged."
      elif merge_json "$path" "mcpServers" "http"; then
        echo "Cursor configured. Restart it to load Lens."
      else
        failed=1
      fi
      ;;
    4)
      path="$(vscode_config_path)"
      if json_server_exists "$path" "servers" && ! confirm_override "VS Code"; then
        echo "VS Code left unchanged."
      elif merge_json "$path" "servers" "http"; then
        echo "VS Code configured. Restart it to load Lens."
      else
        failed=1
      fi
      ;;
    5)
      if ! command -v codex >/dev/null 2>&1; then
        warn "Codex CLI is not installed; skipping."
        failed=1
      elif codex mcp get "$SERVER_NAME" >/dev/null 2>&1 && ! confirm_override "Codex"; then
        echo "Codex left unchanged."
      else
        codex mcp remove "$SERVER_NAME" >/dev/null 2>&1 || true
        if ! codex mcp add "$SERVER_NAME" --url "$MCP_URL" --header "Authorization: Bearer $KEY"; then
        warn "Codex configuration failed; skipping."
        failed=1
        fi
      fi
      ;;
    *) echo "Skipping unknown option: $client" ;;
  esac
done

exit "$failed"
