#!/usr/bin/env bash
# Reconcile the OpenClaw po-gateway shared token from its SINGLE SOURCE OF TRUTH (M51-1, #942).
#
# The token is shared by two consumers that used to drift independently:
#   - bloom-server (the pod): reads it as BLOOM_OPENCLAW_API_KEY, delivered as the
#     bloom-api-secrets SealedSecret rendered from the repo Actions secret of the same name.
#   - the bloom-po-gateway service (bloom-engine VM): reads it as BLOOM_PO_GATEWAY_TOKEN from a
#     hand-managed env file, and 401s every request when it no longer matches the pod's value.
#
# The repo Actions secret BLOOM_OPENCLAW_API_KEY is the single source. The pod side already
# derives from it (render-k8s-secrets.sh <- toJSON(secrets)); this script derives the gateway
# side from the SAME value, so one rotation updates both and neither can silently drift.
#
# Modes (first arg, default "sync"):
#   sync   - write BLOOM_PO_GATEWAY_TOKEN into the gateway env file from the source (preserving
#            every other key), restart the gateway, and verify the written value's fingerprint
#            matches the source. Run alongside the secret sync whenever the token is rotated.
#   check  - compare the gateway env's current token fingerprint against the source and fail on a
#            mismatch. A read-only drift detector - no writes, no restart.
#
# The token itself never appears in argv, logs, or output: it is piped to the VM over stdin, and
# only its sha256 fingerprint (first 16 hex, the #942 evidence format) is ever printed.
#
# Source (one of, in precedence): SECRETS_JSON (toJSON(secrets), as the secret-sync workflows) or
# BLOOM_OPENCLAW_API_KEY in the environment.
# Engine target: ENGINE_HOST (default bloom-engine.exe.xyz), ENGINE_USER (exedev). Optional
# ENGINE_SSH_KEY (a CI deploy key; falls back to ambient ssh when unset, the manual-run path).
# Optional: PO_GATEWAY_ENV_FILE (/home/exedev/.config/bloom-po-gateway.env),
# PO_GATEWAY_SERVICE (bloom-po-gateway), RESTART_GATEWAY (1; set 0 to skip the restart).
#
# Offline tests (stubbed ssh): scripts/deploy/tests/test_sync_po_gateway_token.sh.
set -euo pipefail

mode="${1:-sync}"
case "$mode" in
  sync | check) ;;
  *) echo "::error::mode must be sync|check (got '$mode')" >&2; exit 2 ;;
esac

env_file="${PO_GATEWAY_ENV_FILE:-/home/exedev/.config/bloom-po-gateway.env}"
service="${PO_GATEWAY_SERVICE:-bloom-po-gateway}"
key_name="BLOOM_PO_GATEWAY_TOKEN"

# --- Resolve the token from the single source ---------------------------------------------
if [ -n "${SECRETS_JSON:-}" ]; then
  token="$(printf '%s' "$SECRETS_JSON" | jq -r '.BLOOM_OPENCLAW_API_KEY // empty')"
else
  token="${BLOOM_OPENCLAW_API_KEY:-}"
fi
if [ -z "$token" ]; then
  echo "::error::no BLOOM_OPENCLAW_API_KEY in SECRETS_JSON or the environment - nothing to sync" >&2
  exit 1
fi
fingerprint() { printf '%s' "$1" | sha256sum | cut -c1-16; }
source_fp="$(fingerprint "$token")"

# --- Engine SSH -----------------------------------------------------------------------------
engine_host="${ENGINE_HOST:-bloom-engine.exe.xyz}"
engine_user="${ENGINE_USER:-exedev}"
if [ -n "${ENGINE_SSH_KEY:-}" ]; then
  mkdir -p ~/.ssh && chmod 700 ~/.ssh
  printf '%s\n' "$ENGINE_SSH_KEY" | tr -d '\r' > ~/.ssh/po_gateway_key
  chmod 600 ~/.ssh/po_gateway_key
  if ! ssh-keygen -y -f ~/.ssh/po_gateway_key >/dev/null 2>&1; then
    echo "::error::ENGINE_SSH_KEY is not a loadable private key (full key, real newlines, no passphrase)." >&2
    exit 1
  fi
  ssh-keyscan -H "$engine_host" >> ~/.ssh/known_hosts 2>/dev/null || true
  ssh_cmd=(ssh -i ~/.ssh/po_gateway_key "${engine_user}@${engine_host}")
else
  # Manual-run path: use the operator's ambient ssh to the engine VM (as engine-runner/deploy.sh).
  ssh_cmd=(ssh "${engine_user}@${engine_host}")
fi

# The gateway's current token fingerprint (MISSING/EMPTY when the file/key is absent). Prints
# only the fingerprint, never the value. The ${...} below expand on the ENGINE VM, not here.
# shellcheck disable=SC2016
read_remote_fp='set -euo pipefail
ENV_FILE="'"$env_file"'"
KEY="'"$key_name"'"
if [ ! -f "$ENV_FILE" ]; then echo "fingerprint=MISSING"; exit 0; fi
val="$(sed -n "s/^${KEY}=//p" "$ENV_FILE" | tail -1)"
if [ -z "$val" ]; then echo "fingerprint=EMPTY"; exit 0; fi
printf "fingerprint=%s\n" "$(printf "%s" "$val" | sha256sum | cut -c1-16)"'

if [ "$mode" = "check" ]; then
  echo "==> po-gateway token check: comparing $engine_host:$env_file against the source"
  remote_fp="$("${ssh_cmd[@]}" "$read_remote_fp" | sed -n 's/^fingerprint=//p' | tail -1)"
  : "${remote_fp:=MISSING}"
  if [ "$remote_fp" = "$source_fp" ]; then
    echo "  ok: gateway token is in sync (fingerprint $source_fp)"
    exit 0
  fi
  echo "::error::po-gateway token DRIFT: source=$source_fp gateway=$remote_fp - run \
'bash scripts/deploy/sync-po-gateway-token.sh sync' to reconcile" >&2
  exit 1
fi

# --- sync: write the token from the source, preserving other keys ---------------------------
# The token arrives over stdin (never argv), so it stays out of process listings and logs. The
# ${...} below expand on the ENGINE VM, not here.
# shellcheck disable=SC2016
write_remote='set -euo pipefail
umask 077
ENV_FILE="'"$env_file"'"
KEY="'"$key_name"'"
NEW="$(cat)"
mkdir -p "$(dirname "$ENV_FILE")"
touch "$ENV_FILE"
tmp="$(mktemp)"
grep -v "^${KEY}=" "$ENV_FILE" > "$tmp" || true
printf "%s=%s\n" "$KEY" "$NEW" >> "$tmp"
chmod 600 "$tmp"
mv "$tmp" "$ENV_FILE"
printf "fingerprint=%s\n" "$(printf "%s" "$NEW" | sha256sum | cut -c1-16)"'

echo "==> po-gateway token sync: writing $key_name to $engine_host:$env_file from the source"
written_fp="$(printf '%s' "$token" | "${ssh_cmd[@]}" "$write_remote" | sed -n 's/^fingerprint=//p' | tail -1)"
if [ "$written_fp" != "$source_fp" ]; then
  echo "::error::verification failed: wrote fingerprint '$written_fp' but the source is \
'$source_fp' - the gateway env was NOT reconciled" >&2
  exit 1
fi
echo "  ok: gateway token written and verified (fingerprint $source_fp)"

if [ "${RESTART_GATEWAY:-1}" = "0" ]; then
  echo "  (RESTART_GATEWAY=0) skipping the restart - restart $service on the VM for it to take effect"
  exit 0
fi
echo "==> restarting $service so the new token takes effect"
if ! "${ssh_cmd[@]}" "sudo systemctl restart '$service'" >&2; then
  echo "::warning::could not restart '$service' - the token is written but the gateway must be \
restarted manually (sudo systemctl restart $service) for it to take effect" >&2
fi
echo "==> done. Gateway and pod now derive $key_name / BLOOM_OPENCLAW_API_KEY from the same source."
