#!/usr/bin/env bash
# Tumpai Handbook · Claude Code provider switcher for macOS / Linux.
#
# Switch to Sundy:
#   bash <(curl -fsSL https://tumpai-handbook.pages.dev/switch-claude.sh) sundy
#
# Switch back to Tumpai:
#   bash <(curl -fsSL https://tumpai-handbook.pages.dev/switch-claude.sh) tumpai

set -e

if [ -t 1 ]; then
  C_RED=$'\033[31m'; C_GRN=$'\033[32m'; C_YLW=$'\033[33m'
  C_BLU=$'\033[34m'; C_BLD=$'\033[1m';  C_RST=$'\033[0m'
else
  C_RED=""; C_GRN=""; C_YLW=""; C_BLU=""; C_BLD=""; C_RST=""
fi

FABLE_MODEL_ID="${CLAUDE_TUMPAI_FABLE_MODEL:-${ANTHROPIC_DEFAULT_FABLE_MODEL:-claude-fable-5}}"
FABLE_MODEL_NAME="${CLAUDE_TUMPAI_FABLE_MODEL_NAME:-Fable 5}"
FABLE_MODEL_DESCRIPTION="${CLAUDE_TUMPAI_FABLE_MODEL_DESCRIPTION:-Most capable for your hardest and longest-running tasks}"

ok()    { echo "${C_GRN}OK${C_RST} $*"; }
info()  { echo "${C_BLU}INFO${C_RST} $*"; }
warn()  { echo "${C_YLW}WARN${C_RST} $*"; }
fail()  { echo "${C_RED}ERROR${C_RST} $*" >&2; exit 1; }
title() { echo; echo "${C_BLD}${C_BLU}==> $*${C_RST}"; }

usage() {
  cat <<'HELP'
用法:
  bash <(curl -fsSL https://tumpai-handbook.pages.dev/switch-claude.sh) sundy
  bash <(curl -fsSL https://tumpai-handbook.pages.dev/switch-claude.sh) tumpai

选项:
  -p, --provider tumpai|sundy   指定服务
  -y, --yes                     跳过确认
  -h, --help                    查看帮助

环境变量:
  CLAUDE_SWITCH_PROVIDER        tumpai 或 sundy
  TUMPAI_API_KEY                预填 Tumpai 客户端密钥
  SUNDY_API_KEY                 预填 Sundy 客户端密钥
  CLAUDE_TUMPAI_FABLE_MODEL     覆盖 fable alias 目标模型，默认 claude-fable-5
  CLAUDE_SWITCH_YES=1           等同 --yes

说明:
  Claude Code 的 ANTHROPIC_BASE_URL 必须是根地址，不能带 /v1。
HELP
}

normalize_provider() {
  case "$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')" in
    tumpai) printf 'tumpai' ;;
    sundy)  printf 'sundy' ;;
    *)      return 1 ;;
  esac
}

normalize_base_url() {
  local url="${1:-}"
  url="${url%/}"
  if [ "${url%/v1}" != "$url" ]; then
    url="${url%/v1}"
  fi
  printf '%s' "$url"
}

PROVIDER="${CLAUDE_SWITCH_PROVIDER:-}"
ASSUME_YES="${CLAUDE_SWITCH_YES:-0}"

while [ $# -gt 0 ]; do
  case "$1" in
    tumpai|Tumpai|TUMPAI|sundy|Sundy|SUNDY)
      PROVIDER="$1"
      shift
      ;;
    -p|--provider)
      shift
      [ $# -gt 0 ] || fail "--provider 后面需要跟 tumpai 或 sundy"
      PROVIDER="$1"
      shift
      ;;
    -y|--yes)
      ASSUME_YES=1
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      usage
      fail "未知参数：$1"
      ;;
  esac
done

NON_INTERACTIVE=0
if [ ! -t 0 ]; then
  if [ -r /dev/tty ] && { exec </dev/tty; } 2>/dev/null; then
    :
  else
    NON_INTERACTIVE=1
    ASSUME_YES=1
  fi
fi

if [ -z "$PROVIDER" ]; then
  if [ "$NON_INTERACTIVE" = "1" ]; then
    fail "非交互模式需要指定 CLAUDE_SWITCH_PROVIDER=tumpai|sundy"
  fi
  echo "请选择 Claude Code 要使用的服务："
  echo "  1) Tumpai  https://api.tumpai.site:2053"
  echo "  2) Sundy   https://sundy-api.tumpai.site:2053"
  read -rp "${C_BLD}输入 1/2 或 tumpai/sundy: ${C_RST}" PROVIDER
  case "$PROVIDER" in
    1) PROVIDER="tumpai" ;;
    2) PROVIDER="sundy" ;;
  esac
fi

PROVIDER="$(normalize_provider "$PROVIDER")" || fail "服务只能是 tumpai 或 sundy"

case "$PROVIDER" in
  tumpai)
    DISPLAY_NAME="Tumpai"
    BASE_URL="https://api.tumpai.site:2053"
    ENV_KEY_NAME="TUMPAI_API_KEY"
    ;;
  sundy)
    DISPLAY_NAME="Sundy"
    BASE_URL="https://sundy-api.tumpai.site:2053"
    ENV_KEY_NAME="SUNDY_API_KEY"
    ;;
esac

CURRENT_BASE_URL="$(normalize_base_url "${ANTHROPIC_BASE_URL:-}")"
TUMPAI_KEY_VALUE="${TUMPAI_API_KEY:-}"
SUNDY_KEY_VALUE="${SUNDY_API_KEY:-}"
TARGET_KEY="${!ENV_KEY_NAME:-}"
KEY_SOURCE="$ENV_KEY_NAME"

if [ -z "$TARGET_KEY" ] && [ "$CURRENT_BASE_URL" = "$BASE_URL" ] && [ -n "${ANTHROPIC_AUTH_TOKEN:-}" ]; then
  TARGET_KEY="$ANTHROPIC_AUTH_TOKEN"
  KEY_SOURCE="ANTHROPIC_AUTH_TOKEN"
fi

echo
cat <<BANNER
${C_BLD}${C_BLU}╔══════════════════════════════════════════════╗
║   Claude Code 服务切换                       ║
╚══════════════════════════════════════════════╝${C_RST}

目标服务: $DISPLAY_NAME
Base URL: $BASE_URL

本脚本只更新 Claude Code 的连接环境变量，不会重装 Claude Code。
BANNER

if [ "$ASSUME_YES" != "1" ]; then
  GO=""
  read -r -p "${C_BLD}是否继续？[Y/n] ${C_RST}" GO || true
  GO="${GO:-Y}"
  case "$GO" in
    [Yy]*) ;;
    *) info "已取消。"; exit 0 ;;
  esac
fi

title "1/4 准备 API Key"
if [ "$NON_INTERACTIVE" = "1" ]; then
  if [ -n "$TARGET_KEY" ]; then
    ok "已从 ${KEY_SOURCE} 读取 ${DISPLAY_NAME} 密钥（${#TARGET_KEY} 字符）"
  else
    fail "非交互模式未找到 ${ENV_KEY_NAME}，请提前设置后重试"
  fi
else
  if [ -n "$TARGET_KEY" ]; then
    info "检测到已有 ${DISPLAY_NAME} 密钥（来源：${KEY_SOURCE}，${#TARGET_KEY} 字符）"
    echo "直接回车复用；粘贴新的 ${DISPLAY_NAME} API Key 会覆盖旧值。"
  else
    echo "请粘贴服务方发放的 ${DISPLAY_NAME} API Key："
  fi
  echo "  · 这把密钥会保存到本机 shell 配置"
  echo "  · 对 Claude Code 会映射为 ANTHROPIC_AUTH_TOKEN"
  echo "  · 不会上传到网站"
  echo
  OLD_TARGET_KEY="$TARGET_KEY"
  while :; do
    if [ -n "$OLD_TARGET_KEY" ]; then
      read -rp "${C_BLD}${ENV_KEY_NAME} [回车复用]: ${C_RST}" INPUT_KEY
      if [ -z "$INPUT_KEY" ]; then
        TARGET_KEY="$OLD_TARGET_KEY"
        ok "已复用 ${DISPLAY_NAME} 密钥（${#TARGET_KEY} 字符）"
        break
      fi
      TARGET_KEY="$INPUT_KEY"
    else
      read -rp "${C_BLD}${ENV_KEY_NAME}: ${C_RST}" TARGET_KEY
      if [ -z "$TARGET_KEY" ]; then
        warn "密钥为空，请重新输入"
        continue
      fi
    fi
    if [ -z "$TARGET_KEY" ]; then
      warn "密钥为空，请重新输入"
      continue
    fi
    if [ "${#TARGET_KEY}" -lt 10 ]; then
      warn "密钥太短（${#TARGET_KEY} 字符），看起来不太像"
      read -rp "继续使用此密钥？[y/N] " YN
      case "$YN" in [Yy]*) ;; *) TARGET_KEY="$OLD_TARGET_KEY"; continue ;; esac
    fi
    if [ "$TARGET_KEY" = "$OLD_TARGET_KEY" ]; then
      ok "已复用 ${DISPLAY_NAME} 密钥（${#TARGET_KEY} 字符）"
    else
      ok "已更新 ${DISPLAY_NAME} 密钥（${#TARGET_KEY} 字符）"
    fi
    break
  done
fi

case "$ENV_KEY_NAME" in
  TUMPAI_API_KEY) TUMPAI_KEY_VALUE="$TARGET_KEY" ;;
  SUNDY_API_KEY)  SUNDY_KEY_VALUE="$TARGET_KEY" ;;
esac

title "2/4 写入 shell 环境变量"
OS="$(uname -s)"
case "$OS" in
  Darwin) PLATFORM="mac" ;;
  Linux)  PLATFORM="linux" ;;
  *) fail "暂不支持的系统：${OS}（Windows 请使用 switch-claude.ps1）" ;;
esac

SHELL_NAME="${SHELL:-}"
SHELL_RC=""
case "$SHELL_NAME" in
  *zsh)  SHELL_RC="$HOME/.zshrc" ;;
  *bash)
    if [ "$PLATFORM" = "mac" ]; then SHELL_RC="$HOME/.bash_profile"; else SHELL_RC="$HOME/.bashrc"; fi
    ;;
  *fish) SHELL_RC="$HOME/.config/fish/config.fish" ;;
  *)     SHELL_RC="$HOME/.profile" ;;
esac

RC_FILES=("$SHELL_RC")
case "$SHELL_NAME" in
  *zsh)  RC_FILES+=("$HOME/.zshenv") ;;
  *bash)
    if [ "$PLATFORM" = "mac" ]; then RC_FILES+=("$HOME/.bashrc"); else RC_FILES+=("$HOME/.bash_profile"); fi
    ;;
esac

remove_marked_block() {
  local rc="$1"
  local marker="$2"
  [ -f "$rc" ] || return 0
  if [ "$PLATFORM" = "mac" ]; then
    sed -i '' "/# >>> $marker >>>/,/# <<< $marker <<</d" "$rc" 2>/dev/null || true
  else
    sed -i "/# >>> $marker >>>/,/# <<< $marker <<</d" "$rc" 2>/dev/null || true
  fi
}

for rc in "${RC_FILES[@]}"; do
  remove_marked_block "$rc" "claude-tumpai"
  remove_marked_block "$rc" "claude-sundy"
  remove_marked_block "$rc" "claude-provider-switch"
done

TUMPAI_LINE=""
SUNDY_LINE=""
FISH_TUMPAI_LINE=""
FISH_SUNDY_LINE=""
[ -n "$TUMPAI_KEY_VALUE" ] && TUMPAI_LINE="export TUMPAI_API_KEY=\"$TUMPAI_KEY_VALUE\""
[ -n "$SUNDY_KEY_VALUE" ] && SUNDY_LINE="export SUNDY_API_KEY=\"$SUNDY_KEY_VALUE\""
[ -n "$TUMPAI_KEY_VALUE" ] && FISH_TUMPAI_LINE="set -gx TUMPAI_API_KEY \"$TUMPAI_KEY_VALUE\""
[ -n "$SUNDY_KEY_VALUE" ] && FISH_SUNDY_LINE="set -gx SUNDY_API_KEY \"$SUNDY_KEY_VALUE\""

case "$SHELL_NAME" in
  *fish)
    mkdir -p "$(dirname "$SHELL_RC")"
    cat >> "$SHELL_RC" <<EOF

# >>> claude-provider-switch >>>
$FISH_TUMPAI_LINE
$FISH_SUNDY_LINE
set -gx ANTHROPIC_AUTH_TOKEN "$TARGET_KEY"
set -gx ANTHROPIC_BASE_URL "$BASE_URL"
set -gx ANTHROPIC_DEFAULT_FABLE_MODEL "$FABLE_MODEL_ID"
set -gx ANTHROPIC_DEFAULT_FABLE_MODEL_NAME "$FABLE_MODEL_NAME"
set -gx ANTHROPIC_DEFAULT_FABLE_MODEL_DESCRIPTION "$FABLE_MODEL_DESCRIPTION"
set -e ANTHROPIC_DEFAULT_OPUS_MODEL
set -e ANTHROPIC_DEFAULT_SONNET_MODEL
set -e ANTHROPIC_DEFAULT_HAIKU_MODEL
set -e ANTHROPIC_MODEL
set -e ANTHROPIC_SMALL_FAST_MODEL
set -e ANTHROPIC_CUSTOM_MODEL_OPTION
set -e ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
set -e ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
set -e ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES
set -e CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY
# <<< claude-provider-switch <<<
EOF
    ;;
  *)
    for rc in "${RC_FILES[@]}"; do
      mkdir -p "$(dirname "$rc")"
      cat >> "$rc" <<EOF

# >>> claude-provider-switch >>>
$TUMPAI_LINE
$SUNDY_LINE
export ANTHROPIC_AUTH_TOKEN="$TARGET_KEY"
export ANTHROPIC_BASE_URL="$BASE_URL"
export ANTHROPIC_DEFAULT_FABLE_MODEL="$FABLE_MODEL_ID"
export ANTHROPIC_DEFAULT_FABLE_MODEL_NAME="$FABLE_MODEL_NAME"
export ANTHROPIC_DEFAULT_FABLE_MODEL_DESCRIPTION="$FABLE_MODEL_DESCRIPTION"
unset ANTHROPIC_DEFAULT_OPUS_MODEL
unset ANTHROPIC_DEFAULT_SONNET_MODEL
unset ANTHROPIC_DEFAULT_HAIKU_MODEL
unset ANTHROPIC_MODEL
unset ANTHROPIC_SMALL_FAST_MODEL
unset ANTHROPIC_CUSTOM_MODEL_OPTION
unset ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
unset ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
unset ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES
unset CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY
# <<< claude-provider-switch <<<
EOF
    done
    ;;
esac

[ -n "$TUMPAI_KEY_VALUE" ] && export TUMPAI_API_KEY="$TUMPAI_KEY_VALUE"
[ -n "$SUNDY_KEY_VALUE" ] && export SUNDY_API_KEY="$SUNDY_KEY_VALUE"
export ANTHROPIC_AUTH_TOKEN="$TARGET_KEY"
export ANTHROPIC_BASE_URL="$BASE_URL"
export ANTHROPIC_DEFAULT_FABLE_MODEL="$FABLE_MODEL_ID"
export ANTHROPIC_DEFAULT_FABLE_MODEL_NAME="$FABLE_MODEL_NAME"
export ANTHROPIC_DEFAULT_FABLE_MODEL_DESCRIPTION="$FABLE_MODEL_DESCRIPTION"
unset ANTHROPIC_DEFAULT_OPUS_MODEL
unset ANTHROPIC_DEFAULT_SONNET_MODEL
unset ANTHROPIC_DEFAULT_HAIKU_MODEL
unset ANTHROPIC_MODEL
unset ANTHROPIC_SMALL_FAST_MODEL
unset ANTHROPIC_CUSTOM_MODEL_OPTION
unset ANTHROPIC_CUSTOM_MODEL_OPTION_NAME
unset ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION
unset ANTHROPIC_CUSTOM_MODEL_OPTION_SUPPORTED_CAPABILITIES
unset CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY

ok "已写入 ${RC_FILES[*]}（重新打开终端即可生效）"

title "3/4 清理 Claude Code 网关模型缓存"
CLAUDE_GATEWAY_MODELS_CACHE="$HOME/.claude/cache/gateway-models.json"
if [ -f "$CLAUDE_GATEWAY_MODELS_CACHE" ]; then
  rm -f "$CLAUDE_GATEWAY_MODELS_CACHE"
  ok "已清理 $CLAUDE_GATEWAY_MODELS_CACHE"
else
  info "未发现旧网关模型缓存"
fi

if command -v claude >/dev/null 2>&1; then
  ok "检测到 claude：$(claude --version 2>/dev/null || echo 已安装)"
else
  warn "当前终端未检测到 claude；本脚本只负责切换配置，不安装 Claude Code"
fi

title "4/4 验证中转站连通性"
if command -v curl >/dev/null 2>&1; then
  CHECK_FILE="$(mktemp "${TMPDIR:-/tmp}/claude_provider_switch.XXXXXX")"
  HTTP_CODE="$(curl -s -o "$CHECK_FILE" -w "%{http_code}" --max-time 15 \
    -H "Authorization: Bearer $TARGET_KEY" \
    "$BASE_URL/v1/models" 2>/dev/null || true)"
  [ -n "$HTTP_CODE" ] || HTTP_CODE="000"
  case "$HTTP_CODE" in
    200) ok "${DISPLAY_NAME} 中转站连接正常" ;;
    401|403) warn "${DISPLAY_NAME} 中转站返回 ${HTTP_CODE}，请确认 API Key 是否正确" ;;
    000) warn "无法连接 ${BASE_URL}，请检查网络或稍后重试" ;;
    *) warn "${DISPLAY_NAME} 中转站返回 HTTP ${HTTP_CODE}，配置已写入，可稍后再试" ;;
  esac
  rm -f "$CHECK_FILE"
else
  warn "未找到 curl，跳过连通性验证"
fi

echo
cat <<DONE
${C_BLD}${C_GRN}已切换 Claude Code 到 ${DISPLAY_NAME}。${C_RST}

当前配置：
  ANTHROPIC_BASE_URL=$BASE_URL
  ANTHROPIC_AUTH_TOKEN 使用 $ENV_KEY_NAME 的值
  Fable alias: $FABLE_MODEL_NAME -> $FABLE_MODEL_ID

下一步：
  1. 关闭当前终端并重新打开，然后运行：claude
  2. 当前终端立即生效：source $SHELL_RC && claude
DONE
