#!/usr/bin/env bash
# scripts/reauth-providers.sh
# Guided re-authentication for OpenLife LLM providers: Codex (gpt-5.5), Gemini, Anthropic.
# Idempotent. Per-provider menu (reauth/skip/edit-key). Validates each via real API call.
# Restarts daemon if running. Final status table.

set -u
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

# Matrix-green ANSI palette (matches the new TUI theme)
GREEN=$'\033[38;5;46m'
GREEN_HI=$'\033[38;5;82m\033[1m'
GREEN_DIM=$'\033[38;5;22m'
RED=$'\033[38;5;196m'
YELLOW=$'\033[38;5;226m'
RESET=$'\033[0m'

say()  { printf '%s%s%s\n' "$GREEN"     "$*" "$RESET"; }
hi()   { printf '%s%s%s\n' "$GREEN_HI"  "$*" "$RESET"; }
warn() { printf '%s%s%s\n' "$YELLOW"    "$*" "$RESET"; }
err()  { printf '%s%s%s\n' "$RED"       "$*" "$RESET" 1>&2; }
hr()   { printf '%s' "$GREEN_DIM"; printf '─%.0s' $(seq 1 60); printf '%s\n' "$RESET"; }

# ─────────────────────────────────────────────────────────────
# Probe — current credential state
# ─────────────────────────────────────────────────────────────
probe_codex() {
  command -v codex >/dev/null 2>&1 || { echo "missing"; return; }
  if codex login status 2>/dev/null | grep -qi 'logged in'; then
    # Cached status doesn't guarantee the refresh token is valid. Do a 8s probe.
    if timeout 8 codex exec --model gpt-5.5 --skip-git-repo-check 'OK' >/dev/null 2>&1; then
      echo "ok"
    else
      echo "stale"
    fi
  else
    echo "logged-out"
  fi
}

probe_gemini() {
  command -v gemini >/dev/null 2>&1 || { echo "missing"; return; }
  if gemini login status 2>/dev/null | grep -qi 'logged in'; then
    echo "ok"
  else
    echo "logged-out"
  fi
}

probe_anthropic() {
  local key
  key="$(grep -E '^ANTHROPIC_API_KEY=' "$ROOT/.env" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
  if [[ -z "$key" ]]; then echo "missing"; return; fi
  local code
  code="$(curl -sS -o /dev/null -w '%{http_code}' --max-time 8 \
    -H "x-api-key: $key" -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{"model":"claude-haiku-4-5","max_tokens":4,"messages":[{"role":"user","content":"ok"}]}' \
    https://api.anthropic.com/v1/messages 2>/dev/null || echo 000)"
  case "$code" in
    200) echo "ok" ;;
    401|403) echo "auth-bad" ;;
    429) echo "rate-limited" ;;
    *)   echo "http-$code" ;;
  esac
}

print_status_table() {
  hr
  printf '%s%-12s %-12s %s%s\n' "$GREEN_HI" "PROVIDER" "STATUS" "DETAIL" "$RESET"
  hr
  printf '%-12s %-12s %s\n' "codex"     "$1" "(gpt-5.5 via Codex OAuth)"
  printf '%-12s %-12s %s\n' "gemini"    "$2" "(google-genai OAuth)"
  printf '%-12s %-12s %s\n' "anthropic" "$3" "(ANTHROPIC_API_KEY in .env)"
  hr
}

# ─────────────────────────────────────────────────────────────
# Per-provider menus
# ─────────────────────────────────────────────────────────────
menu_for() {
  local name="$1" status="$2"
  echo
  hi "── $name ──"
  echo "  current status: $status"
  echo "  1) reauth     2) skip     3) edit key (anthropic only)"
  read -r -p "  choose [1/2/3]: " choice
  echo "$choice"
}

reauth_codex() {
  say "Logging out of Codex…"
  codex logout 2>/dev/null || true
  hi "Opening Codex login (browser). Complete the flow, then press ENTER here."
  codex login || { err "codex login failed"; return 1; }
  if timeout 12 codex exec --model gpt-5.5 --skip-git-repo-check 'OK' >/dev/null 2>&1; then
    hi "✓ codex gpt-5.5 responding"
    return 0
  fi
  err "codex still failing after login. Inspect: codex login status"
  return 1
}

reauth_gemini() {
  say "Logging out of Gemini…"
  gemini logout 2>/dev/null || true
  hi "Opening Gemini login (device-auth). Follow on-screen URL, then return."
  gemini login --device-auth || { err "gemini login failed"; return 1; }
  hi "✓ gemini login completed (quota state checked on next call)"
  return 0
}

reauth_anthropic_edit_key() {
  echo
  warn "Paste your ANTHROPIC_API_KEY (sk-ant-…). Input is hidden."
  read -r -s -p "  key: " newkey
  echo
  [[ -z "$newkey" ]] && { warn "(empty — keeping current key)"; return 0; }
  # Idempotent .env edit: remove existing line then append.
  local envfile="$ROOT/.env"
  touch "$envfile"
  grep -v -E '^ANTHROPIC_API_KEY=' "$envfile" > "$envfile.tmp" 2>/dev/null || true
  mv "$envfile.tmp" "$envfile"
  printf 'ANTHROPIC_API_KEY=%s\n' "$newkey" >> "$envfile"
  say "✓ .env updated"
}

# ─────────────────────────────────────────────────────────────
# Daemon restart helper
# ─────────────────────────────────────────────────────────────
maybe_restart_daemon() {
  local snapshot
  snapshot="$(node bin/openlife.js status 2>/dev/null || echo '{}')"
  if echo "$snapshot" | grep -q '"fresh":true'; then
    say "Daemon is running — restarting to pick up new credentials…"
    node bin/openlife.js restart >/dev/null 2>&1 || true
    nohup node bin/openlife.js start --daemon >/dev/null 2>&1 &
    disown 2>/dev/null || true
    # Give it 3 seconds to boot + revalidate executors
    sleep 3
    say "✓ daemon restarted"
  else
    say "Daemon not running — skipping restart"
  fi
}

# ─────────────────────────────────────────────────────────────
# Main
# ─────────────────────────────────────────────────────────────
hi "╔══════════════════════════════════════════════════════════╗"
hi "║  OPENLIFE  ·  provider reauth                            ║"
hi "╚══════════════════════════════════════════════════════════╝"
say "Probing current credentials…"

CODEX="$(probe_codex)"
GEMINI="$(probe_gemini)"
ANTHROPIC="$(probe_anthropic)"
print_status_table "$CODEX" "$GEMINI" "$ANTHROPIC"

# Codex
case "$CODEX" in ok) say "codex already healthy — skipping menu" ;; *)
  case "$(menu_for codex "$CODEX")" in
    1) reauth_codex && CODEX=ok || CODEX=failed ;;
    2) say "(skipped)" ;;
    *) say "(skipped)" ;;
  esac
;; esac

# Gemini
case "$GEMINI" in ok) say "gemini already healthy — skipping menu" ;; *)
  case "$(menu_for gemini "$GEMINI")" in
    1) reauth_gemini && GEMINI=ok || GEMINI=failed ;;
    2) say "(skipped)" ;;
    *) say "(skipped)" ;;
  esac
;; esac

# Anthropic
case "$ANTHROPIC" in ok) say "anthropic already healthy — skipping menu" ;; *)
  case "$(menu_for anthropic "$ANTHROPIC")" in
    1|3) reauth_anthropic_edit_key
         ANTHROPIC="$(probe_anthropic)" ;;
    2)   say "(skipped)" ;;
    *)   say "(skipped)" ;;
  esac
;; esac

# Final state
echo
hi "── final state ──"
print_status_table "$CODEX" "$GEMINI" "$ANTHROPIC"

# Restart daemon if running so executors revalidate
maybe_restart_daemon

# Show status snapshot
echo
hi "── openlife status ──"
node bin/openlife.js status 2>/dev/null \
  | node -e 'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>{try{const j=JSON.parse(d);console.log("heartbeat fresh:",j.heartbeat&&j.heartbeat.fresh);(j.executors||[]).forEach(e=>console.log(`  ${e.executor.padEnd(8)} avail=${e.available} reason=${e.reason}`));}catch(e){console.error("status parse failed");}});' \
  2>/dev/null || warn "status command unavailable"

# Exit code: 0 if at least one provider is ok
[[ "$CODEX" == "ok" || "$GEMINI" == "ok" || "$ANTHROPIC" == "ok" ]] && exit 0 || exit 1
