#!/bin/bash
# BTX Keeper run wrapper — launchd starts this once; it supervises the node.
#
# Rules it enforces (each one is a lesson with a receipt):
#   - power-aware: node runs on AC power, pauses cleanly on battery
#   - first-start sequencing: headers FIRST, then loadtxoutset IMMEDIATELY —
#     a trusted mirror left with full headers and no snapshot starts a
#     genesis download it cannot finish
#   - caffeinate -s scoped to the btxd pid (keeps the Mac awake on AC only;
#     display sleep is never blocked)
#   - clean stops only; NEVER kill -9 (unclean stops have bricked snapshot
#     datadirs); NEVER auto-restart a wedged node (the watchdog notifies)
#   - honors the watchdog's pause marker: when the watchdog fail-quiet
#     stopped the node, this wrapper must NOT start it again on the next
#     tick — that restart loop was exactly the hot-laptop-at-2am failure the
#     fail-quiet exists to prevent. `rm ~/.btx-keeper/keeper-paused` resumes.
set -u

KEEPER_HOME="$HOME/.btx-keeper"
BTXD="$KEEPER_HOME/bin/btxd"
CLI="$KEEPER_HOME/bin/btx-cli"
LOG="$KEEPER_HOME/logs/wrapper.log"
SNAPSHOT="$KEEPER_HOME/bootstrap/snapshot.dat"
SNAPSHOT_BASE_HEIGHT=191266
PAUSE_MARKER="$KEEPER_HOME/keeper-paused"

log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG"; }

on_ac_power() { pmset -g ps 2>/dev/null | head -1 | grep -q "AC Power"; }

btxd_pid() { pgrep -f "^$KEEPER_HOME/bin/btxd" | head -1; }

rpc() { "$CLI" -datadir="$KEEPER_HOME" "$@" 2>/dev/null; }

start_node() {
    [ -n "$(btxd_pid)" ] && return 0
    log "starting btxd (nice 10)"
    nohup nice -n 10 "$BTXD" -datadir="$KEEPER_HOME" >> "$KEEPER_HOME/logs/btxd-stdout.log" 2>&1 &
    local pid=$!
    nohup caffeinate -s -w "$pid" >/dev/null 2>&1 &
    if ! pgrep -f "btx-keeper-watchdog.sh" >/dev/null; then
        nohup "$KEEPER_HOME/btx-keeper-watchdog.sh" >> "$KEEPER_HOME/logs/watchdog.err" 2>&1 &
    fi
}

stop_node() {
    [ -z "$(btxd_pid)" ] && return 0
    log "battery — stopping btxd cleanly"
    rpc stop >/dev/null
    for _ in $(seq 1 120); do
        [ -z "$(btxd_pid)" ] && { log "btxd exited"; return 0; }
        sleep 5
    done
    log "WARNING: btxd still flushing after 10 min — leaving it to finish (never kill -9)"
}

# First-start bootstrap: block until headers cover the snapshot base, then
# load the snapshot at once. Idempotent — a marker file records success, and
# loadtxoutset against an already-loaded datadir just errors harmlessly.
maybe_load_snapshot() {
    [ -f "$KEEPER_HOME/.snapshot-loaded" ] && return 0
    [ -f "$SNAPSHOT" ] || { log "no snapshot.dat — skipping bootstrap (already synced?)"; return 0; }
    local h
    h=$(rpc getblockchaininfo | python3 -c "import json,sys; print(json.load(sys.stdin)['headers'])" 2>/dev/null)
    [ -n "$h" ] && [ "$h" -ge "$SNAPSHOT_BASE_HEIGHT" ] || return 1   # not yet — retry next tick
    log "headers=$h >= $SNAPSHOT_BASE_HEIGHT — loading snapshot"
    if "$CLI" -datadir="$KEEPER_HOME" -rpcclienttimeout=0 loadtxoutset "$SNAPSHOT" >> "$LOG" 2>&1; then
        log "snapshot loaded"
        touch "$KEEPER_HOME/.snapshot-loaded"
    else
        # Already loaded on a previous run counts as success.
        if rpc getblockchaininfo | python3 -c "import json,sys; d=json.load(sys.stdin); exit(0 if d['blocks'] > 0 else 1)" 2>/dev/null; then
            log "chain already active — marking snapshot as loaded"
            touch "$KEEPER_HOME/.snapshot-loaded"
        else
            log "loadtxoutset failed — will retry"
            return 1
        fi
    fi
}

log "wrapper start"
paused_logged=0
while true; do
    if on_ac_power; then
        if [ -f "$PAUSE_MARKER" ]; then
            if [ "$paused_logged" = 0 ]; then
                log "watchdog pause marker present ($PAUSE_MARKER) — not starting btxd until it is removed"
                paused_logged=1
            fi
        else
            paused_logged=0
            start_node
            maybe_load_snapshot || true
        fi
    else
        stop_node
    fi
    sleep 120
done
