#!/usr/bin/env bash
# TokenomixAI: install Claude Code + konfigurasi API key (Linux & macOS).
# Pakai: bash <(curl -fsSL https://tokenomixai.com/install/claude.sh)
# Balik ke akun/config semula: bash <(curl -fsSL https://tokenomixai.com/install/claude.sh) --restore
#   atau: RESTORE=1 bash <(curl -fsSL https://tokenomixai.com/install/claude.sh)
# Opsional: API_KEY="sk-tkx-..." BASE_URL="https://api.tokenomixai.com/v1" bash <(curl -fsSL ...)
set -euo pipefail

BASE_URL="${BASE_URL:-https://api.tokenomixai.com/v1}"
BASE_URL="${BASE_URL%/}"
# Claude Code menambahkan /v1/messages sendiri, jadi base-nya origin tanpa /v1.
ORIGIN="${BASE_URL%/v1}"
SITE_URL="${SITE_URL:-https://tokenomixai.com}"

echo "=== TokenomixAI x Claude Code ==="

# Mode restore: hapus setting Tokenomix dari settings.json, balik ke akun/config semula.
RESTORE="${RESTORE:-}"
if [ "${1:-}" = "--restore" ]; then RESTORE=1; fi
if [ -n "$RESTORE" ]; then
  SETTINGS_RESTORE="$HOME/.claude/settings.json"
  TOKENOMIX_KEYS="ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN ANTHROPIC_MODEL ANTHROPIC_DEFAULT_HAIKU_MODEL ANTHROPIC_DEFAULT_SONNET_MODEL ANTHROPIC_DEFAULT_OPUS_MODEL CLAUDE_CODE_AUTO_COMPACT_WINDOW"
  if [ ! -f "$SETTINGS_RESTORE" ]; then
    echo "OK: $SETTINGS_RESTORE tidak ada, tidak ada yang diubah."
    exit 0
  fi
  if command -v python3 >/dev/null 2>&1; then
    REMOVED=$(KEYS="$TOKENOMIX_KEYS" python3 - "$SETTINGS_RESTORE" <<'PY'
import json, os, sys
path = sys.argv[1]
try:
    with open(path) as f:
        data = json.load(f)
except (OSError, ValueError) as e:
    print(f"Error: {path} tidak bisa dibaca sebagai JSON: {e}", file=sys.stderr)
    raise SystemExit(2)
env = data.get("env")
removed = [k for k in os.environ["KEYS"].split() if isinstance(env, dict) and k in env]
for k in removed:
    del env[k]
sl = data.get("statusLine")
if isinstance(sl, dict) and "tokenomix-statusline" in str(sl.get("command", "")):
    del data["statusLine"]
    removed.append("statusLine")
if removed:
    with open(path, "w") as f:
        json.dump(data, f, indent=2)
        f.write("\n")
print(" ".join(removed) if removed else "tidak ada")
PY
)
  elif command -v node >/dev/null 2>&1; then
    REMOVED=$(KEYS="$TOKENOMIX_KEYS" node -e '
const fs = require("fs");
const p = process.argv[1];
let data;
try { data = JSON.parse(fs.readFileSync(p, "utf8")); }
catch (e) { console.error("Error: " + p + " tidak bisa dibaca sebagai JSON: " + e.message); process.exit(2); }
const env = data.env && typeof data.env === "object" ? data.env : {};
const removed = process.env.KEYS.split(" ").filter((k) => k in env);
removed.forEach((k) => { delete env[k]; });
if (data.statusLine && String(data.statusLine.command || "").includes("tokenomix-statusline")) { delete data.statusLine; removed.push("statusLine"); }
if (removed.length) fs.writeFileSync(p, JSON.stringify(data, null, 2) + "\n");
console.log(removed.length ? removed.join(" ") : "tidak ada");
' "$SETTINGS_RESTORE")
  else
    echo "Error: butuh python3 atau node untuk restore. Hapus manual 6 kunci ANTHROPIC_* dari blok env di $SETTINGS_RESTORE." >&2
    exit 1
  fi
  rm -f "$HOME/.claude/tokenomix-statusline.sh" "$HOME/.claude/tokenomix-quota.cache"
  if command -v claude >/dev/null 2>&1 && claude plugin list 2>/dev/null | grep -q 'tokenomixai@tokenomixai'; then
    claude plugin uninstall tokenomixai@tokenomixai >/dev/null 2>&1 || true
    claude plugin marketplace remove tokenomixai >/dev/null 2>&1 || true
    if [ "$REMOVED" = "tidak ada" ]; then REMOVED="plugin tokenomixai"; else REMOVED="$REMOVED plugin tokenomixai"; fi
  fi
  if [ "$REMOVED" = "tidak ada" ]; then
    echo "OK: tidak ada setting Tokenomix di $SETTINGS_RESTORE, tidak ada yang diubah."
  else
    chmod 600 "$SETTINGS_RESTORE"
    echo "OK: setting Tokenomix dihapus dari $SETTINGS_RESTORE ($REMOVED)."
  fi
  echo "Buka terminal baru, jalankan claude, lalu /logout dan /login untuk balik ke akun berbayar."
  exit 0
fi

API_KEY="${API_KEY:-}"
if [ -z "$API_KEY" ]; then
  printf "Tempel API key TokenomixAI (sk-tkx-..., tidak tampil saat diketik): "
  read -rs API_KEY < /dev/tty
  echo
fi
API_KEY="$(printf '%s' "$API_KEY" | tr -d '[:space:]')"
if ! printf '%s' "$API_KEY" | grep -Eq '^sk-tkx-[A-Za-z0-9]+$'; then
  echo "Error: API key harus diawali sk-tkx-. Cek lagi key dari halaman sukses order atau bot Telegram." >&2
  exit 1
fi

echo "-> Mengecek API key..."
TMP_BODY=$(mktemp)
HTTP_CODE=$(curl -sS -o "$TMP_BODY" -w '%{http_code}' "$BASE_URL/models" -H "Authorization: Bearer $API_KEY" || echo 000)
# ID model ditulis mentah ke JSON: buang yang bukan karakter ID biasa supaya tidak bisa menyisipkan setting.
MODEL_IDS=$(grep -o '"id":"[^"]*"' "$TMP_BODY" | sed 's/"id":"//; s/"$//' | grep -E '^[A-Za-z0-9._:/-]+$' || true)
rm -f "$TMP_BODY"
case "$HTTP_CODE" in
  200) ;;
  401) echo "Error: API key salah atau tidak dikenal." >&2; exit 1 ;;
  403) echo "Error: API key nonaktif. Hubungi admin TokenomixAI." >&2; exit 1 ;;
  *) echo "Error: gagal menghubungi $BASE_URL (HTTP $HTTP_CODE). Cek koneksi lalu coba lagi." >&2; exit 1 ;;
esac

# Pilih model pertama dari daftar preferensi yang benar-benar tersedia.
pick() {
  for m in "$@"; do
    if printf '%s\n' "$MODEL_IDS" | grep -Fxq "$m"; then echo "$m"; return; fi
  done
  printf '%s\n' "$MODEL_IDS" | head -n1
}
MODEL_FAST=$(pick deepseek-v4-flash-0731 deepseek-v4.1-flash-1017 deepseek-v4-flash glm-5.1)
MODEL_BALANCED=$(pick deepseek-v4-pro deepseek-v4-pro-0813 glm-5.2)
MODEL_POWERFUL=$(pick deepseek-v4-pro-0813 deepseek-v4-pro glm-5.3)
echo "OK: fast=$MODEL_FAST, balanced=$MODEL_BALANCED, powerful=$MODEL_POWERFUL"

if command -v claude >/dev/null 2>&1; then
  echo "OK: claude sudah terpasang"
else
  if ! command -v npm >/dev/null 2>&1; then
    echo "Error: npm belum ada. Install Node.js LTS dari https://nodejs.org lalu jalankan command ini lagi." >&2
    exit 1
  fi
  echo "-> Menginstall Claude Code..."
  npm install -g @anthropic-ai/claude-code
  echo "OK: claude terpasang"
fi

CONFIG_DIR="$HOME/.claude"
SETTINGS="$CONFIG_DIR/settings.json"
mkdir -p "$CONFIG_DIR"
if [ -f "$SETTINGS" ]; then
  BACKUP="$SETTINGS.bak-$(date +%Y%m%d-%H%M%S)"
  cp "$SETTINGS" "$BACKUP"
  echo "Backup: $BACKUP"
fi

# Model katalog tidak dikenal Claude Code (dianggap context 1M). Compact di 200rb: aman untuk model
# ber-context kecil dan chat panjang tidak membakar kuota sebesar seluruh context tiap pesan.
ENV_JSON=$(cat <<EOF
{
  "ANTHROPIC_BASE_URL": "$ORIGIN",
  "ANTHROPIC_AUTH_TOKEN": "$API_KEY",
  "ANTHROPIC_MODEL": "$MODEL_BALANCED",
  "ANTHROPIC_DEFAULT_HAIKU_MODEL": "$MODEL_FAST",
  "ANTHROPIC_DEFAULT_SONNET_MODEL": "$MODEL_BALANCED",
  "ANTHROPIC_DEFAULT_OPUS_MODEL": "$MODEL_POWERFUL",
  "CLAUDE_CODE_AUTO_COMPACT_WINDOW": "200000"
}
EOF
)

# Setting lain milik user dipertahankan kalau python3 ada; hanya blok env yang diisi.
if [ -f "$SETTINGS" ] && command -v python3 >/dev/null 2>&1 && ENV_JSON="$ENV_JSON" python3 - "$SETTINGS" <<'PY'
import json, os, sys
path = sys.argv[1]
with open(path) as f:
    data = json.load(f)
if not isinstance(data, dict):
    raise SystemExit(1)
env = data.get("env") if isinstance(data.get("env"), dict) else {}
env.pop("ANTHROPIC_API_KEY", None)
env.update(json.loads(os.environ["ENV_JSON"]))
data["env"] = env
with open(path, "w") as f:
    json.dump(data, f, indent=2)
    f.write("\n")
PY
then
  :
else
  printf '{\n  "env": %s\n}\n' "$ENV_JSON" > "$SETTINGS"
fi
chmod 600 "$SETTINGS"

echo "OK: config ditulis ke $SETTINGS"

# Sisa kuota di bawah kotak input. Claude Code versi baru: plugin (tampil di terminal dan VS Code).
# Versi yang belum bisa memuat plugin ini: status line (terminal saja). Dicek dulu dengan claude plugin validate.
PLUGIN_REPO="sagarasea/tokenomixai-claude"
PLUGIN_OK=""
PLUGIN_TMP=$(mktemp -d)
mkdir -p "$PLUGIN_TMP/.claude-plugin" "$PLUGIN_TMP/hooks"
RAW="https://raw.githubusercontent.com/$PLUGIN_REPO/main"
if curl -fsSL "$RAW/.claude-plugin/plugin.json" -o "$PLUGIN_TMP/.claude-plugin/plugin.json" \
  && curl -fsSL "$RAW/hooks/hooks.json" -o "$PLUGIN_TMP/hooks/hooks.json" \
  && curl -fsSL "$RAW/hooks/register.ts" -o "$PLUGIN_TMP/hooks/register.ts" \
  && claude plugin validate "$PLUGIN_TMP" >/dev/null 2>&1; then
  claude plugin marketplace add "$PLUGIN_REPO" >/dev/null 2>&1 || true # sudah terdaftar = lanjut
  claude plugin install tokenomixai@tokenomixai --scope user >/dev/null 2>&1 || true
  if claude plugin list 2>/dev/null | grep -q 'tokenomixai@tokenomixai'; then PLUGIN_OK=1; fi
fi
rm -rf "$PLUGIN_TMP"

# Status line sisa kuota. statusLine milik user sendiri tidak ditimpa.
STATUSLINE="$CONFIG_DIR/tokenomix-statusline.sh"
if [ -n "$PLUGIN_OK" ]; then
  # Plugin sudah menampilkan baris yang sama; status line lama dari installer dilepas supaya tidak dobel.
  SL_DROP='
import json, sys
p = sys.argv[1]
data = json.load(open(p))
sl = data.get("statusLine")
if isinstance(sl, dict) and "tokenomix-statusline" in str(sl.get("command", "")):
    del data["statusLine"]
    with open(p, "w") as f:
        json.dump(data, f, indent=2); f.write("\n")'
  SL_DROP_JS='
const fs = require("fs");
const p = process.argv[1];
const data = JSON.parse(fs.readFileSync(p, "utf8"));
if (data.statusLine && String(data.statusLine.command || "").includes("tokenomix-statusline")) {
  delete data.statusLine;
  fs.writeFileSync(p, JSON.stringify(data, null, 2) + "\n");
}'
  if command -v python3 >/dev/null 2>&1; then python3 -c "$SL_DROP" "$SETTINGS" 2>/dev/null || true
  else node -e "$SL_DROP_JS" "$SETTINGS" 2>/dev/null || true; fi
  rm -f "$STATUSLINE" "$CONFIG_DIR/tokenomix-quota.cache"
  echo "OK: sisa kuota tampil di bawah kotak input Claude Code (terminal dan VS Code)"
elif curl -fsSL "$SITE_URL/install/statusline.sh" -o "$STATUSLINE.tmp" && head -n1 "$STATUSLINE.tmp" | grep -q '^#!/usr/bin/env bash'; then
  mv "$STATUSLINE.tmp" "$STATUSLINE"
  chmod 700 "$STATUSLINE"
  SL_SCRIPT='
const fs = require("fs");
const p = process.argv[1];
const data = JSON.parse(fs.readFileSync(p, "utf8"));
const cur = data.statusLine;
if (cur && !String((cur && cur.command) || "").includes("tokenomix-statusline")) { console.log("kept"); process.exit(0); }
data.statusLine = { type: "command", command: "bash " + JSON.stringify(process.env.SL), padding: 0 };
fs.writeFileSync(p, JSON.stringify(data, null, 2) + "\n");
console.log("set");'
  SL_PY='
import json, os, sys
p = sys.argv[1]
data = json.load(open(p))
cur = data.get("statusLine")
if cur and "tokenomix-statusline" not in str((cur or {}).get("command", "") if isinstance(cur, dict) else cur):
    print("kept"); raise SystemExit(0)
data["statusLine"] = {"type": "command", "command": "bash " + json.dumps(os.environ["SL"]), "padding": 0}
with open(p, "w") as f:
    json.dump(data, f, indent=2); f.write("\n")
print("set")'
  if command -v python3 >/dev/null 2>&1; then
    SL_RESULT=$(SL="$STATUSLINE" python3 -c "$SL_PY" "$SETTINGS" 2>/dev/null || echo fail)
  else
    SL_RESULT=$(SL="$STATUSLINE" node -e "$SL_SCRIPT" "$SETTINGS" 2>/dev/null || echo fail)
  fi
  case "$SL_RESULT" in
    set) echo "OK: sisa kuota tampil di status line Claude Code terminal (bawah kotak input)"
      echo "Info: supaya juga tampil di VS Code, update Claude Code (npm install -g @anthropic-ai/claude-code) lalu jalankan installer ini lagi" ;;
    kept) echo "Info: kamu sudah punya statusLine sendiri, tidak diubah. Sisa kuota: bash $STATUSLINE" ;;
    *) echo "Info: status line kuota tidak terpasang otomatis. Cek sisa kuota di https://tokenomixai.com/portal" ;;
  esac
else
  rm -f "$STATUSLINE.tmp"
  echo "Info: skrip status line kuota gagal diunduh, dilewati. Cek sisa kuota di https://tokenomixai.com/portal"
fi
echo
echo "=== Selesai ==="
echo "Buka terminal baru lalu jalankan: claude"
echo "Model default: $MODEL_BALANCED"
echo "/model haiku, sonnet, opus = $MODEL_FAST, $MODEL_BALANCED, $MODEL_POWERFUL (bukan model Claude asli)"
echo "Model lain dari katalog, termasuk Claude: /model <model-id> (daftar di https://tokenomixai.com/#models)"
echo
echo "Mau balik ke akun semula? Jalankan:"
echo "  bash <(curl -fsSL https://tokenomixai.com/install/claude.sh) --restore"
echo "  lalu di dalam claude: /logout dan /login"
