#!/usr/bin/env bash
# Linkbreakers MCP setup helper. Feel free to copy/share (e.g., as a GitHub Gist).
set -euo pipefail

if ! command -v python3 >/dev/null 2>&1; then
  echo "Error: python3 is required to update the JSON config."
  exit 1
fi

if [ -t 1 ]; then
  UI_ENABLED=1
  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[0;33m'
  BLUE='\033[0;34m'
  CYAN='\033[0;36m'
  DIM='\033[2m'
  BOLD='\033[1m'
  INVERT='\033[7m'
  RESET='\033[0m'
else
  UI_ENABLED=0
  RED=''
  GREEN=''
  YELLOW=''
  BLUE=''
  CYAN=''
  DIM=''
  BOLD=''
  INVERT=''
  RESET=''
fi

print_banner() {
  printf "${CYAN}============================================================${RESET}\n"
  printf "${BOLD}${CYAN} Linkbreakers MCP Setup${RESET}\n"
  printf "${BLUE} Configure an MCP client (Claude Desktop, Continue, or any MCP-compatible client)${RESET}\n"
  printf "${CYAN}============================================================${RESET}\n\n"
}

cleanup_ui() {
  if [ "${UI_ENABLED}" -eq 1 ]; then
    printf '\033[?25h' >&2
  fi
}

trap cleanup_ui EXIT
print_banner

INPUT="/dev/stdin"
if [ ! -t 0 ]; then
  if [ -r /dev/tty ]; then
    INPUT="/dev/tty"
  else
    echo "Error: no interactive TTY available for prompts."
    echo "Hint: run this script directly or with bash -c, not via a pipe without a TTY."
    exit 1
  fi
fi

auth_options=(
  "Automatic login (OAuth) - recommended"
  "Manual token (paste workspace/member token)"
)

auth_choice="$(choose_option "Authentication method:" "${auth_options[@]}" < "$INPUT")"
printf "${GREEN}Selected:${RESET} %s\n\n" "$auth_choice"

AUTH_MODE="oauth"
TOKEN=""

case "$auth_choice" in
  "Manual token (paste workspace/member token)")
    AUTH_MODE="token"
    printf "${BOLD}${BLUE}Workspace token:${RESET} " >&2
    read -r -s TOKEN < "$INPUT"
    printf "\n"

    # Strip ANSI escape sequences (bracketed paste mode, etc.)
    TOKEN=$(printf '%s' "$TOKEN" | sed $'s/\x1b\\[[0-9;]*[a-zA-Z]//g' | sed $'s/\x1b[^[]//g' | tr -d '\000-\037' | tr -d '\177')

    if [ -z "${TOKEN}" ]; then
      echo "Error: token cannot be empty."
      exit 1
    fi
    ;;
esac

options=(
  "Claude Desktop (macOS)"
  "Claude Desktop (Windows)"
  "Claude Code (project)"
  "Claude Code (global)"
  "Continue (VSCode)"
  "Other MCP client (Codex, Gemini, Cursor, etc.)"
  "Print JSON only (no file changes)"
)

CONFIG=""
FORMAT=""
choose_option() {
  local prompt="$1"
  shift
  local choices=("$@")
  local current=0
  local count="${#choices[@]}"
  local i
  local key
  local esc
  local redraw_count=0

  if [ "$count" -eq 0 ]; then
    echo "Error: no options provided." >&2
    return 1
  fi

  printf "${BOLD}${BLUE}%s${RESET}\n" "$prompt" >&2
  printf "${DIM}Use Up/Down arrows and Enter to select (or type 1-%s).${RESET}\n" "$count" >&2
  if [ "${UI_ENABLED}" -eq 1 ]; then
    printf '\033[?25l' >&2
  fi

  while true; do
    if [ "$redraw_count" -gt 0 ]; then
      printf '\033[%sA' "$redraw_count" >&2
    fi

    for ((i = 0; i < count; i++)); do
      if [ "$i" -eq "$current" ]; then
        printf " ${INVERT}${BOLD}[%d] %s${RESET}\n" "$((i + 1))" "${choices[$i]}" >&2
      else
        printf "  [%d] %s\n" "$((i + 1))" "${choices[$i]}" >&2
      fi
    done
    redraw_count="$count"

    IFS= read -r -s -n 1 key < "$INPUT" || true

    case "$key" in
      "")
        printf '\n' >&2
        if [ "${UI_ENABLED}" -eq 1 ]; then
          printf '\033[?25h' >&2
        fi
        printf '%s\n' "${choices[$current]}"
        return 0
        ;;
      [1-9])
        i=$((key - 1))
        if [ "$i" -ge 0 ] && [ "$i" -lt "$count" ]; then
          current="$i"
        fi
        ;;
      $'\x1b')
        IFS= read -r -s -n 2 esc < "$INPUT" || true
        case "$esc" in
          "[A")
            current=$(( (current - 1 + count) % count ))
            ;;
          "[B")
            current=$(( (current + 1) % count ))
            ;;
        esac
        ;;
    esac
  done
}

client_choice="$(choose_option "Select your MCP client:" "${options[@]}" < "$INPUT")"
printf "${GREEN}Selected:${RESET} %s\n\n" "$client_choice"
case "$client_choice" in
  "Claude Desktop (macOS)")
    CONFIG="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
    FORMAT="object"
    ;;
  "Claude Desktop (Windows)")
    BASE_DIR="${APPDATA:-$HOME/AppData/Roaming}"
    CONFIG="$BASE_DIR/Claude/claude_desktop_config.json"
    FORMAT="object"
    ;;
  "Claude Code (project)")
    CONFIG="$HOME/.claude.json"
    FORMAT="claude_code_project"
    printf "${BOLD}${BLUE}Project path${RESET} [${PWD}]: " >&2
    read -r PROJECT_PATH < "$INPUT"
    if [ -z "$PROJECT_PATH" ]; then
      PROJECT_PATH="$PWD"
    fi
    ;;
  "Claude Code (global)")
    CONFIG="$HOME/.claude.json"
    FORMAT="claude_code_global"
    ;;
  "Continue (VSCode)")
    CONFIG="$HOME/.continue/config.json"
    FORMAT="array"
    ;;
  "Other MCP client (Codex, Gemini, Cursor, etc.)")
    printf "${BOLD}${BLUE}Config path:${RESET} " >&2
    read -r CONFIG < "$INPUT"
    if [ -z "$CONFIG" ]; then
      echo "Error: config path is required."
      exit 1
    fi
    printf "${BOLD}${BLUE}Config format${RESET} (object/array/print) [object]: " >&2
    read -r FORMAT < "$INPUT"
    FORMAT="${FORMAT,,}"
    if [ -z "$FORMAT" ]; then
      FORMAT="object"
    fi
    if [ "$FORMAT" != "object" ] && [ "$FORMAT" != "array" ] && [ "$FORMAT" != "print" ]; then
      echo "Error: format must be object, array, or print."
      exit 1
    fi
    ;;
  "Print JSON only (no file changes)")
    FORMAT="print"
    ;;
  *)
    echo "Error: unsupported option selected."
    exit 1
    ;;
esac

if [ "$FORMAT" != "print" ]; then
  if [ -z "$CONFIG" ]; then
    echo "Error: config path is required."
    exit 1
  fi
  mkdir -p "$(dirname "$CONFIG")"
fi

TOKEN="$TOKEN" AUTH_MODE="$AUTH_MODE" CONFIG="$CONFIG" FORMAT="$FORMAT" PROJECT_PATH="${PROJECT_PATH:-}" python3 - <<'PY'
import json
import os
import sys
from pathlib import Path

token = os.environ.get("TOKEN", "").strip()
auth_mode = os.environ.get("AUTH_MODE", "oauth")
config_path = os.environ.get("CONFIG", "")
fmt = os.environ.get("FORMAT", "object")
project_path = os.environ.get("PROJECT_PATH", "").strip()

if auth_mode == "token":
    payload = {
        "type": "http",
        "url": "https://mcp.linkbreakers.com",
        "headers": {"Authorization": f"Bearer {token}"},
    }
else:
    # OAuth mode: no headers needed, MCP client handles auth automatically
    payload = {
        "type": "http",
        "url": "https://mcp.linkbreakers.com",
    }

if fmt == "print":
    print("\nClaude/obj config:")
    print(json.dumps({"mcpServers": {"linkbreakers": payload}}, indent=2))
    print("\nArray config (Continue-style):")
    print(json.dumps({"mcpServers": [{"name": "linkbreakers", **payload}]}, indent=2))
    sys.exit(0)

if not config_path:
    raise SystemExit("Missing config path.")

path = Path(config_path)

data = {}
if path.exists():
    try:
        data = json.loads(path.read_text())
    except json.JSONDecodeError:
        data = {}

if fmt == "object":
    if not isinstance(data.get("mcpServers"), dict):
        data["mcpServers"] = {}
    # Always overwrite any existing Linkbreakers entry
    if "linkbreakers" in data["mcpServers"]:
        del data["mcpServers"]["linkbreakers"]
    data["mcpServers"]["linkbreakers"] = payload
elif fmt == "claude_code_project":
    if not project_path:
        raise SystemExit("Project path is required for Claude Code project config.")
    projects = data.get("projects")
    if not isinstance(projects, dict):
        projects = {}
    proj = projects.get(project_path)
    if not isinstance(proj, dict):
        proj = {}
    mcp = proj.get("mcpServers")
    if not isinstance(mcp, dict):
        mcp = {}
    mcp["linkbreakers"] = payload
    proj["mcpServers"] = mcp
    projects[project_path] = proj
    data["projects"] = projects
elif fmt == "claude_code_global":
    if not isinstance(data.get("mcpServers"), dict):
        data["mcpServers"] = {}
    data["mcpServers"]["linkbreakers"] = payload
elif fmt == "array":
    servers = data.get("mcpServers")
    if not isinstance(servers, list):
        servers = []
    servers = [s for s in servers if not (isinstance(s, dict) and s.get("name") == "linkbreakers")]
    servers.append({"name": "linkbreakers", **payload})
    data["mcpServers"] = servers
else:
    raise SystemExit(f"Unsupported format: {fmt}")

path.write_text(json.dumps(data, indent=2) + "\n")
print(f"\nDone: Linkbreakers MCP configured in {path}")
PY

printf "\n${GREEN}All set.${RESET}\n"
