#!/bin/bash
set -euo pipefail

export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"

OPENCLAW_CONFIG="/Users/openclaw/.openclaw/openclaw.json"
ROUTER_HEALTH_URL="http://127.0.0.1:8080/health"
ROUTER_SELFTEST_URL="http://127.0.0.1:8080/selftest/forward"
HOOK_URL="http://127.0.0.1:18789/hooks/agent"
WORKSPACE_TMP="/Users/openclaw/.openclaw/workspace/tmp"
BACKUP_DIR="$WORKSPACE_TMP/notion-webhook-token-rotation"
REPORT_PATH="$BACKUP_DIR/last-rotation-report.md"

mkdir -p "$BACKUP_DIR"

stamp() { date '+%Y%m%d-%H%M%S'; }
now_iso() { date -u '+%Y-%m-%dT%H:%M:%SZ'; }
log() { printf '[%s] %s\n' "$(now_iso)" "$1"; }

NEW_TOKEN="${1:-}"
if [[ -z "$NEW_TOKEN" ]]; then
  NEW_TOKEN="$(openssl rand -hex 32)"
fi

if [[ ${#NEW_TOKEN} -lt 32 ]]; then
  echo "ERROR: token too short; expected >=32 chars" >&2
  exit 1
fi

BACKUP_PATH="$BACKUP_DIR/openclaw.json.$(stamp).bak"
cp "$OPENCLAW_CONFIG" "$BACKUP_PATH"
chmod 600 "$BACKUP_PATH"

OLD_HOOK_TOKEN="$(python3 - <<'PY'
import json
p='/Users/openclaw/.openclaw/openclaw.json'
obj=json.load(open(p))
print(obj.get('hooks',{}).get('token',''))
PY
)"

python3 - <<'PY' "$OPENCLAW_CONFIG" "$NEW_TOKEN"
import json, sys
p, tok = sys.argv[1], sys.argv[2]
obj=json.load(open(p))
obj.setdefault('hooks', {})['token']=tok
obj.setdefault('gateway', {}).setdefault('auth', {})['token']=tok
obj.setdefault('gateway', {}).setdefault('remote', {})['token']=tok
with open(p,'w') as f:
    json.dump(obj,f,indent=2)
    f.write('\n')
PY
chmod 600 "$OPENCLAW_CONFIG"

ROLLBACK_NOTE="$BACKUP_DIR/ROLLBACK-$(stamp).md"
cat > "$ROLLBACK_NOTE" <<EOF
# Rollback Notes

If verification fails after token rotation:

1) Restore config backup:
   cp "$BACKUP_PATH" "$OPENCLAW_CONFIG"
2) Restart gateway:
   openclaw gateway restart
3) Restart event-router:
   launchctl kickstart -k "gui/$(id -u)/ai.openclaw.event-router"
4) Re-run verification section in runbook.
EOF

log "Restarting gateway"
openclaw gateway restart >/dev/null

log "Restarting event-router"
launchctl kickstart -k "gui/$(id -u)/ai.openclaw.event-router"
sleep 2

log "Verifying router endpoint reachable"
curl -fsS "$ROUTER_HEALTH_URL" >/dev/null

log "Verifying new hook token accepted"
new_status="$(curl -s -o /dev/null -w "%{http_code}" -X POST "$HOOK_URL" \
  -H "Authorization: Bearer $NEW_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"message":"token-rotation-verify:new","agentId":"main","deliver":false}')"

log "Verifying old hook token rejected"
old_status="000"
if [[ -n "$OLD_HOOK_TOKEN" ]]; then
  old_status="$(curl -s -o /dev/null -w "%{http_code}" -X POST "$HOOK_URL" \
    -H "Authorization: Bearer $OLD_HOOK_TOKEN" \
    -H 'Content-Type: application/json' \
    --data '{"message":"token-rotation-verify:old","agentId":"main","deliver":false}')"
fi

log "Verifying forward path via router self-test"
forward_status="$(curl -s -o /dev/null -w "%{http_code}" -X POST "$ROUTER_SELFTEST_URL" \
  -H 'Content-Type: application/json' \
  --data '{"reason":"token-rotation"}')"

verdict="PASS"
if [[ "$new_status" != "200" ]]; then
  verdict="FAIL"
fi
if [[ -n "$OLD_HOOK_TOKEN" && "$old_status" != "401" ]]; then
  verdict="FAIL"
fi
if [[ "$forward_status" != "200" ]]; then
  verdict="FAIL"
fi

cat > "$REPORT_PATH" <<EOF
# Notion Webhook Token Rotation Report

- Time (UTC): $(now_iso)
- Config backup: $BACKUP_PATH
- Rollback notes: $ROLLBACK_NOTE
- New token accepted status: $new_status
- Old token rejected status: $old_status
- Router forward self-test status: $forward_status
- Verdict: **$verdict**

## Safety
- Token values are intentionally not logged.
- If verdict is FAIL, rollback using the rollback notes before further retries.
EOF

if [[ "$verdict" != "PASS" ]]; then
  echo "Verification failed. See $REPORT_PATH" >&2
  exit 1
fi

echo "Rotation and verification PASS. Report: $REPORT_PATH"
