#!/bin/bash
# Claude Key Tool (Mac) — double-click là chạy, không cần cài gì thêm.
set -euo pipefail
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8

CONFIG_ID="7c4a2f91-3b8e-4d6a-9f21-a1b2c3d4e5f6"
GATEWAY="https://api.nghimmo.com"
LIB="$HOME/Library/Application Support/Claude-3p/configLibrary"
MARKER="$HOME/Library/Application Support/Claude-3p/.claude-key-tool.json"
SETTINGS="$HOME/.claude/settings.json"
CLAUDE_JSON="$HOME/.claude.json"
LOG="$HOME/Library/Logs/claude-key-tool.log"

log() {
  mkdir -p "$(dirname "$LOG")"
  printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1" >>"$LOG"
}

alert() {
  osascript -e "display alert \"Claude Key Tool\" message \"$1\" as ${2:-informational}" >/dev/null 2>&1 || true
}

confirm() {
  osascript -e "display dialog \"$1\" buttons {\"Huỷ\", \"OK\"} default button \"OK\" with icon caution" 2>/dev/null | grep -q "OK"
}

enable_dev_mode() {
  local body='{
  "allowDevTools": true
}'
  for p in \
    "$HOME/Library/Application Support/Claude/developer_settings.json" \
    "$HOME/Library/Application Support/Claude-3p/developer_settings.json"
  do
    mkdir -p "$(dirname "$p")"
    printf '%s\n' "$body" >"$p"
  done
}

clear_extension_cache() {
  local rel="User/globalStorage/anthropic.claude-code"
  for base in "$HOME/Library/Application Support/Code" \
              "$HOME/Library/Application Support/Cursor" \
              "$HOME/Library/Application Support/Code - Insiders"
  do
    [ -d "$base/$rel" ] && rm -rf "$base/$rel"
  done
}

# Xoa session claude.ai cu (giu configLibrary) de app doc lai gateway khi cold launch.
clear_claude_session() {
  local base rel
  for base in \
    "$HOME/Library/Application Support/Claude-3p" \
    "$HOME/Library/Application Support/Claude"
  do
    [ -d "$base" ] || continue
    for rel in Cookies "Local Storage" "Session Storage" Cache "Code Cache"; do
      if [ -e "$base/$rel" ]; then
        rm -rf "$base/$rel"
        log "cleared session: $base/$rel"
      fi
    done
  done
}

write_desktop_config() {
  local key="$1"
  mkdir -p "$LIB" "$(dirname "$MARKER")"
  if command -v python3 >/dev/null 2>&1; then
    LIB="$LIB" MARKER="$MARKER" CONFIG_ID="$CONFIG_ID" GATEWAY="$GATEWAY" KEY="$key" python3 <<'PY'
import json, os
from pathlib import Path
lib = Path(os.environ["LIB"])
cid = os.environ["CONFIG_ID"]
key = os.environ["KEY"]
gw = os.environ["GATEWAY"]
cfg = {
    "inferenceProvider": "gateway",
    "inferenceGatewayBaseUrl": gw,
    "inferenceGatewayApiKey": key,
    "inferenceGatewayAuthScheme": "x-api-key",
    "inferenceCredentialKind": "static",
    "modelDiscoveryEnabled": True,
    "inferenceModels": [
        {"name": "nghi/claude-opus-4.8"},
        {"name": "nghi/claude-sonnet-4.6"},
        {"name": "nghi/claude-haiku-4.5"},
    ],
    "chatTabEnabled": True,
    "coworkTabEnabled": True,
    "isClaudeCodeForDesktopEnabled": True,
}
meta = {"appliedId": cid, "entries": [{"id": cid, "name": "Claude Key Tool"}]}
(lib / f"{cid}.json").write_text(json.dumps(cfg, indent=2) + "\n", encoding="utf-8")
(lib / "_meta.json").write_text(json.dumps(meta, indent=2) + "\n", encoding="utf-8")
Path(os.environ["MARKER"]).write_text(json.dumps({"version": "1.2.0", "key": key, "gateway": gw}, indent=2) + "\n", encoding="utf-8")
PY
  else
    local esc
    esc=$(printf '%s' "$key" | sed 's/\\/\\\\/g; s/"/\\"/g')
    cat >"$LIB/$CONFIG_ID.json" <<EOF
{
  "inferenceProvider": "gateway",
  "inferenceGatewayBaseUrl": "$GATEWAY",
  "inferenceGatewayApiKey": "$esc",
  "inferenceGatewayAuthScheme": "x-api-key",
  "inferenceCredentialKind": "static",
  "modelDiscoveryEnabled": true,
  "inferenceModels": [
    {"name": "nghi/claude-opus-4.8"},
    {"name": "nghi/claude-sonnet-4.6"},
    {"name": "nghi/claude-haiku-4.5"}
  ],
  "chatTabEnabled": true,
  "coworkTabEnabled": true,
  "isClaudeCodeForDesktopEnabled": true
}
EOF
    cat >"$LIB/_meta.json" <<EOF
{
  "appliedId": "$CONFIG_ID",
  "entries": [
    {
      "id": "$CONFIG_ID",
      "name": "Claude Key Tool"
    }
  ]
}
EOF
    printf '{\n  "version": "1.2.0",\n  "key": "%s",\n  "gateway": "%s"\n}\n' "$esc" "$GATEWAY" >"$MARKER"
  fi
}

write_claude_code() {
  local key="$1"
  mkdir -p "$(dirname "$SETTINGS")"
  clear_extension_cache
  if command -v python3 >/dev/null 2>&1; then
    SETTINGS="$SETTINGS" CLAUDE_JSON="$CLAUDE_JSON" GATEWAY="$GATEWAY" KEY="$key" python3 <<'PY'
import json, os
from pathlib import Path
sf = Path(os.environ["SETTINGS"])
data = {}
if sf.exists():
    try:
        data = json.loads(sf.read_text(encoding="utf-8"))
    except json.JSONDecodeError:
        data = {}
if not isinstance(data, dict):
    data = {}
env = data.get("env")
if not isinstance(env, dict):
    env = {}
env["ANTHROPIC_BASE_URL"] = os.environ["GATEWAY"]
env["ANTHROPIC_AUTH_TOKEN"] = os.environ["KEY"]
env["ANTHROPIC_MODEL"] = "nghi/claude-opus-4.8"
env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = "nghi/claude-opus-5"
env["ANTHROPIC_SMALL_FAST_MODEL"] = "nghi/claude-haiku-4.5"
env.pop("ANTHROPIC_API_KEY", None)
data["env"] = env
sf.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
cj = Path(os.environ["CLAUDE_JSON"])
if cj.exists():
    try:
        cdata = json.loads(cj.read_text(encoding="utf-8"))
        if isinstance(cdata, dict):
            for k in ("primaryApiKey", "customApiKeyResponses"):
                cdata.pop(k, None)
            cj.write_text(json.dumps(cdata, indent=2) + "\n", encoding="utf-8")
    except json.JSONDecodeError:
        pass
PY
  else
    cat >"$SETTINGS" <<EOF
{
  "env": {
    "ANTHROPIC_BASE_URL": "$GATEWAY",
    "ANTHROPIC_AUTH_TOKEN": "$key",
    "ANTHROPIC_MODEL": "nghi/claude-opus-4.8",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "nghi/claude-opus-5",
    "ANTHROPIC_SMALL_FAST_MODEL": "nghi/claude-haiku-4.5"
  }
}
EOF
  fi
}

reset_all() {
  rm -f "$LIB/$CONFIG_ID.json" "$MARKER"
  if [ -f "$LIB/_meta.json" ]; then
    printf '{\n  "appliedId": "",\n  "entries": []\n}\n' >"$LIB/_meta.json"
  fi
  clear_extension_cache
  if command -v python3 >/dev/null 2>&1 && [ -f "$SETTINGS" ]; then
    SETTINGS="$SETTINGS" CLAUDE_JSON="$CLAUDE_JSON" python3 <<'PY'
import json, os
from pathlib import Path
for path_key in ("SETTINGS", "CLAUDE_JSON"):
    p = Path(os.environ[path_key])
    if not p.exists():
        continue
    try:
        data = json.loads(p.read_text(encoding="utf-8"))
    except json.JSONDecodeError:
        continue
    if path_key == "SETTINGS" and isinstance(data.get("env"), dict):
        for k in ("ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_API_KEY", "ANTHROPIC_BASE_URL", "ANTHROPIC_MODEL", "ANTHROPIC_DEFAULT_OPUS_MODEL", "ANTHROPIC_SMALL_FAST_MODEL"):
            data["env"].pop(k, None)
    if path_key == "CLAUDE_JSON" and isinstance(data, dict):
        for k in ("primaryApiKey", "customApiKeyResponses"):
            data.pop(k, None)
    p.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
PY
  fi
}

pick_action() {
  osascript <<'APPLE' 2>/dev/null || echo "apply"
set choices to {"Áp dụng key", "Reset cấu hình", "Thoát"}
set picked to choose from list choices with prompt "Claude Key Tool — chọn thao tác:" default items {"Áp dụng key"}
if picked is false then return "exit"
if item 1 of picked is "Reset cấu hình" then return "reset"
if item 1 of picked is "Thoát" then return "exit"
return "apply"
APPLE
}

ask_key() {
  osascript <<'APPLE' 2>/dev/null || true
set dlg to display dialog "Dán API key Claude (sk-...):" default answer "" with hidden answer buttons {"Huỷ", "OK"} default button "OK" with title "Claude Key Tool"
return text returned of dlg
APPLE
}

claude_running() {
  pgrep -x Claude >/dev/null 2>&1
}

quit_claude() {
  local i
  if claude_running; then
    log "quit: Claude running before quit"
  fi
  osascript -e 'tell application "Claude" to quit' >/dev/null 2>&1 || true
  sleep 1
  killall Claude >/dev/null 2>&1 || true
  pkill -x Claude >/dev/null 2>&1 || true
  for i in $(seq 1 20); do
    claude_running || break
    sleep 0.5
  done
  if claude_running; then
    log "warn: Claude still running after quit attempts"
  else
    log "quit: Claude stopped"
  fi
  sleep 3
}

verify_desktop_config() {
  [ -f "$LIB/$CONFIG_ID.json" ] && [ -f "$LIB/_meta.json" ] && [ -f "$MARKER" ]
}

check_managed_profile() {
  [ -f "/Library/Managed Preferences/com.anthropic.claudefordesktop.plist" ]
}

open_claude() {
  if [ -d "/Applications/Claude.app" ]; then
    open -n -a "Claude"
    return 0
  fi
  if [ -d "$HOME/Applications/Claude.app" ]; then
    open -n -a "$HOME/Applications/Claude.app"
    return 0
  fi
  return 1
}

check_claude_app() {
  [ -d "/Applications/Claude.app" ] || [ -d "$HOME/Applications/Claude.app" ]
}

# --- main ---
log "=== Claude Key Tool start (pid $$, user=$USER, home=$HOME) ==="
action="$(pick_action)"
case "$action" in
  exit|"") exit 0 ;;
  reset)
    if confirm "Xóa cấu hình Claude Desktop + Claude Code trên máy này?"; then
      reset_all
      alert "Đã reset. Mở lại Claude Desktop / reload VS Code nếu đang mở." "informational"
    fi
    exit 0
    ;;
esac

key="$(ask_key)"
key="$(printf '%s' "$key" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"

if [ -z "$key" ]; then
  log "abort: empty key"
  alert "Chưa nhập key." "warning"
  exit 1
fi
if [ "${#key}" -lt 8 ] || [[ "$key" == *YOUR_API_KEY* ]]; then
  log "abort: invalid key"
  alert "Key không hợp lệ. Kiểm tra lại." "warning"
  exit 1
fi

if ! check_claude_app; then
  log "abort: Claude.app not installed"
  alert "Chưa cài Claude Desktop.\n\nTải từ claude.com/download (file .dmg, không dùng App Store) rồi chạy lại tool." "warning"
  exit 1
fi

if check_managed_profile; then
  log "abort: managed profile present"
  alert "Máy có profile MDM quản lý Claude Desktop — configLibrary bị bỏ qua. Cần admin gỡ profile hoặc cấu hình gateway qua MDM." "warning"
  exit 1
fi

quit_claude
clear_claude_session
reset_all
enable_dev_mode
write_desktop_config "$key"
write_claude_code "$key"

if ! verify_desktop_config; then
  log "fail: config files missing under $LIB"
  alert "Không ghi được cấu hình Claude Desktop.\n\nChạy lại từ Terminal:\nbash \"$0\"\n\nXem log: $LOG\nClaude log: ~/Library/Logs/Claude-3p/main.log" "warning"
  exit 1
fi

if [ -f "$LIB/_meta.json" ]; then
  log "meta: $(tr -d '\n' <"$LIB/_meta.json" | head -c 200)"
fi

log "ok: wrote $LIB/$CONFIG_ID.json"
if open_claude; then
  alert "Xong! Claude đã được mở lại (cold launch).\n\nTrên màn hình đăng nhập chọn Continue with Gateway — KHÔNG đăng nhập claude.ai.\n\nNếu vẫn thấy màn claude.ai: Cmd+Q thoát hẳn → chạy lại tool từ Terminal:\nbash \"$0\"\n\nVS Code/Cursor: Cmd+Shift+P → Reload Window." "informational"
else
  alert "Xong! Cài Claude Desktop từ claude.com/download (không dùng App Store) rồi mở app → Continue with Gateway." "informational"
fi
log "=== done ==="
