#!/usr/bin/env sh
# install-fastrouter.sh — Configure FastRouter as the model provider in
# OpenAI Codex CLI.
#
# Usage:
#   sh install-fastrouter.sh <FASTROUTER_API_KEY> [<model>]
#   curl -fsSL https://fastrouter.ai/codex/install-fastrouter.sh \
#        | sh -s -- <FASTROUTER_API_KEY> [<model>]
#
# What it does (idempotent — safe to re-run):
#   1. Validates the FastRouter API key (rejects redacted / malformed keys).
#   2. Installs Codex CLI via `npm install -g @openai/codex` if missing.
#   3. Merges ~/.codex/config.toml so model_provider = "fastrouter" and a
#      [model_providers.fastrouter] block is present (preserves other keys).
#   4. Persists `export FASTROUTER_API_KEY=...` to the user's shell rc file.
#   5. Prints a masked-key confirmation. Never echoes the raw key.
#
# Hardcoded values (do not change without coordinating with FastRouter):
#   base_url       https://api.fastrouter.ai/api/v1
#   env_key        FASTROUTER_API_KEY
#   wire_api       responses
#   default model  openai/gpt-5.5  (override via second positional arg)

set -eu

FR_BASE_URL="https://api.fastrouter.ai/api/v1"
FR_DASHBOARD="https://dashboard.fastrouter.ai/"
FR_MODELS_PAGE="https://fastrouter.ai/models"
DEFAULT_MODEL="openai/gpt-5.5"

# ---------- 1. Validate input ----------

API_KEY="${1:-}"
if [ "${2:-}" != "" ]; then
  MODEL="${2}"
  MODEL_EXPLICIT=1
else
  MODEL="${DEFAULT_MODEL}"
  MODEL_EXPLICIT=0
fi

if [ -z "${API_KEY}" ]; then
  printf 'Error: FastRouter API key is required.\n' >&2
  printf 'Usage:\n' >&2
  printf '  sh install-fastrouter.sh <FASTROUTER_API_KEY> [<model>]\n' >&2
  printf 'Generate a key at %s\n' "${FR_DASHBOARD}" >&2
  exit 64
fi

# Reject redactions / placeholder garbage before they corrupt config.
case "${API_KEY}" in
  *REDACTED*|*redacted*|"<redacted>"|"***"|"")
    printf 'Error: API key looks redacted (got "%s").\n' "${API_KEY}" >&2
    printf 'Re-run from a terminal where the key is visible to the script.\n' >&2
    exit 65
    ;;
esac

case "${API_KEY}" in
  sk-v1-*) : ;;
  *)
    printf 'Error: API key must start with "sk-v1-".\n' >&2
    printf 'Generate one at %s\n' "${FR_DASHBOARD}" >&2
    exit 65
    ;;
esac

KEY_REST=${API_KEY#sk-v1-}
if [ -z "${KEY_REST}" ]; then
  printf 'Error: API key has nothing after "sk-v1-" prefix.\n' >&2
  exit 65
fi

# Compute masked form for confirmations (POSIX: avoid bash ${var: -4})
KEY_LEN=$(printf '%s' "${API_KEY}" | wc -c | tr -d ' ')
LAST4=$(printf '%s' "${API_KEY}" | awk '{print substr($0, length-3)}')
MASKED="****${LAST4}"

printf 'FastRouter installer for Codex CLI\n'
printf '  Key:   %s  (len=%s)\n' "${MASKED}" "${KEY_LEN}"
printf '  Model: %s\n' "${MODEL}"
printf '\n'

# ---------- 2. Ensure Codex CLI is installed ----------

if ! command -v codex >/dev/null 2>&1; then
  printf 'Codex CLI not found — installing via npm...\n'
  if ! command -v npm >/dev/null 2>&1; then
    printf 'Error: npm is required but not installed.\n' >&2
    printf 'Install Node.js (>=20) first: https://nodejs.org/\n' >&2
    exit 127
  fi
  npm install -g @openai/codex
fi

CODEX_VERSION=$(codex --version 2>/dev/null || echo "unknown")
printf 'Codex CLI:    %s\n' "${CODEX_VERSION}"

# ---------- 3. Merge ~/.codex/config.toml ----------

CODEX_DIR="${HOME}/.codex"
CONFIG_FILE="${CODEX_DIR}/config.toml"

mkdir -p "${CODEX_DIR}"
if [ ! -f "${CONFIG_FILE}" ]; then
  : > "${CONFIG_FILE}"
fi

# Backup once per day at most.
BACKUP="${CONFIG_FILE}.bak.$(date +%Y%m%d)"
if [ ! -f "${BACKUP}" ]; then
  cp "${CONFIG_FILE}" "${BACKUP}"
fi

if ! command -v python3 >/dev/null 2>&1; then
  printf 'Error: python3 is required for safe TOML merging.\n' >&2
  exit 127
fi

# Robust merge: replace any existing [model_providers.fastrouter] block,
# upsert the three top-level keys, append the canonical provider block.
# All values are constants (NOT the API key) — safe to inline.
MODEL_ARG="${MODEL}" MODEL_EXPLICIT="${MODEL_EXPLICIT}" python3 - "${CONFIG_FILE}" <<'PY'
import os, re, sys, pathlib

path     = pathlib.Path(sys.argv[1])
text     = path.read_text() if path.exists() else ""
model    = os.environ["MODEL_ARG"]
explicit = os.environ.get("MODEL_EXPLICIT", "0") == "1"

# 1. Drop any existing [model_providers.fastrouter] block.
text = re.sub(
    r'(?ms)^\[model_providers\.fastrouter\][^\[]*?(?=^\[|\Z)',
    '',
    text,
).rstrip()

# 2. Upsert top-level keys (preserve order naturally).
def upsert(t, key, value):
    pat = re.compile(rf'^{re.escape(key)}\s*=.*$', re.MULTILINE)
    line = f'{key} = "{value}"'
    return pat.sub(line, t, count=1) if pat.search(t) else line + ("\n" + t if t else "")

def has_key(t, key):
    return re.search(rf'^{re.escape(key)}\s*=', t, re.MULTILINE) is not None

# Apply in reverse so that any newly-inserted (prepended) keys end up in
# the canonical order at the top: model_provider, model_reasoning_effort, model.

# model: override only when explicitly requested; otherwise insert default
# only if missing entirely.
if explicit or not has_key(text, "model"):
    text = upsert(text, "model", model)

# model_reasoning_effort: insert default only if missing (preserve user value).
if not has_key(text, "model_reasoning_effort"):
    text = upsert(text, "model_reasoning_effort", "high")

# model_provider is the whole point of this installer — always force it.
text = upsert(text, "model_provider", "fastrouter")

# 3. Append canonical provider block (separated from prior content by blank line).
if text and not text.endswith("\n"):
    text += "\n"
text += (
    ("\n" if text else "") +
    "[model_providers.fastrouter]\n"
    'name = "fastrouter"\n'
    'base_url = "https://api.fastrouter.ai/api/v1"\n'
    'env_key = "FASTROUTER_API_KEY"\n'
    'wire_api = "responses"\n'
)

path.write_text(text)
PY

printf 'Config:       %s\n' "${CONFIG_FILE}"

# ---------- 4. Persist FASTROUTER_API_KEY to shell rc ----------

SHELL_NAME=${SHELL##*/}
case "${SHELL_NAME}" in
  zsh)  RC_FILE="${HOME}/.zshrc" ;;
  bash) RC_FILE="${HOME}/.bashrc" ;;
  fish) RC_FILE="${HOME}/.config/fish/config.fish" ;;
  *)    RC_FILE="${HOME}/.profile" ;;
esac
[ -d "${HOME}/.config/fish" ] || [ "${SHELL_NAME}" != "fish" ] || mkdir -p "${HOME}/.config/fish"

# Touch rc file if missing
[ -f "${RC_FILE}" ] || : > "${RC_FILE}"

# Idempotent: replace any existing FASTROUTER_API_KEY line, else append.
# Pass key via env (NOT argv) so it doesn't show up in `ps`.
TMP=$(mktemp)
API_KEY="${API_KEY}" awk -v shell="${SHELL_NAME}" '
  BEGIN { found = 0 }
  /^[[:space:]]*export[[:space:]]+FASTROUTER_API_KEY=/ {
    print "export FASTROUTER_API_KEY=\"" ENVIRON["API_KEY"] "\""
    found = 1; next
  }
  /^[[:space:]]*set[[:space:]]+-gx[[:space:]]+FASTROUTER_API_KEY/ {
    print "set -gx FASTROUTER_API_KEY \"" ENVIRON["API_KEY"] "\""
    found = 1; next
  }
  { print }
  END {
    if (!found) {
      if (shell == "fish")
        print "set -gx FASTROUTER_API_KEY \"" ENVIRON["API_KEY"] "\""
      else
        print "export FASTROUTER_API_KEY=\"" ENVIRON["API_KEY"] "\""
    }
  }
' "${RC_FILE}" > "${TMP}"
mv "${TMP}" "${RC_FILE}"
chmod 600 "${RC_FILE}" 2>/dev/null || true

printf 'Persisted:    %s\n' "${RC_FILE}"

# Export for current shell too (only useful if script was sourced, but harmless).
export FASTROUTER_API_KEY="${API_KEY}"

# ---------- 5. Report success ----------

printf '\n'
printf '✓ FastRouter is configured for Codex CLI (%s).\n' "${MASKED}"
printf '\n'
printf 'Open a NEW terminal (so the env var loads) and run:\n'
printf '  cd /path/to/your/project\n'
printf '  codex\n'
printf '\n'
printf 'Switch models by editing model = "..." in %s.\n' "${CONFIG_FILE}"
printf 'Browse slugs at %s.\n' "${FR_MODELS_PAGE}"

