#!/usr/bin/env bash
# Copyright 2024-2026 The DragonX Developers
# Released under GPLv3
#
# Monitors lightwalletd and restarts it automatically if it crashes.
# Usage: ./monitor_lwd.sh &
#   or:  nohup ./monitor_lwd.sh >> /tmp/lwd-monitor.log 2>&1 &

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LWD_BIN="$SCRIPT_DIR/lightwalletd"
LWD_ARGS="-bind-addr lite.dragonx.is:9069 -conf-file $HOME/.hush/DRAGONX/DRAGONX.conf -no-tls -lag-min 4 -lag-max 12 -lag-window 30 -cache-size 5000"
LOGFILE="$SCRIPT_DIR/lwd-monitor.log"
PIDFILE="/tmp/lwd-monitor.pid"
STOPPING=0
RESTART_DELAY=5        # seconds to wait before restarting after a crash
MAX_RAPID_RESTARTS=5   # max restarts within the rapid window before backing off
RAPID_WINDOW=120       # seconds — if this many restarts happen within this window, back off
BACKOFF_DELAY=60       # seconds to wait when backing off

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log() {
    echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOGFILE"
}

cleanup() {
    STOPPING=1
    log "${YELLOW}Monitor shutting down...${NC}"
    if [[ -n "${LWD_PID:-}" ]] && kill -0 "$LWD_PID" 2>/dev/null; then
        log "Stopping lightwalletd (PID $LWD_PID)..."
        kill "$LWD_PID" 2>/dev/null || true
        wait "$LWD_PID" 2>/dev/null || true
    fi
    rm -f "$PIDFILE"
    log "Monitor stopped."
    exit 0
}

trap cleanup SIGINT SIGTERM

# Prevent duplicate monitors
if [[ -f "$PIDFILE" ]]; then
    OLD_PID=$(cat "$PIDFILE")
    if kill -0 "$OLD_PID" 2>/dev/null; then
        echo "Monitor already running (PID $OLD_PID). Exiting."
        exit 1
    fi
    rm -f "$PIDFILE"
fi
echo $$ > "$PIDFILE"

# Check binary exists
if [[ ! -x "$LWD_BIN" ]]; then
    log "${RED}ERROR: lightwalletd binary not found at $LWD_BIN${NC}"
    log "Build it first with: make build"
    rm -f "$PIDFILE"
    exit 1
fi

# Check conf file exists
CONF_FILE="$HOME/.hush/DRAGONX/DRAGONX.conf"
if [[ ! -f "$CONF_FILE" ]]; then
    log "${RED}ERROR: DRAGONX.conf not found at $CONF_FILE${NC}"
    rm -f "$PIDFILE"
    exit 1
fi

log "${GREEN}DragonX lightwalletd monitor started (PID $$)${NC}"
log "Binary:  $LWD_BIN"
log "Args:    $LWD_ARGS"

restart_times=()
LWD_PID=""
STOPPING=0

while true; do
    # Start lightwalletd
    log "${GREEN}Starting lightwalletd...${NC}"
    $LWD_BIN $LWD_ARGS >> "$LOGFILE" 2>&1 &
    LWD_PID=$!
    log "lightwalletd started with PID $LWD_PID"

    # Wait for it to exit
    EXIT_CODE=0
    wait "$LWD_PID" || EXIT_CODE=$?
    LWD_PID=""

    if [[ $STOPPING -eq 1 ]]; then
        log "${YELLOW}lightwalletd stopped on request (code $EXIT_CODE). Not restarting.${NC}"
        break
    fi

    log "${RED}lightwalletd crashed with exit code $EXIT_CODE${NC}"

    # Track restart frequency for backoff
    NOW=$(date +%s)
    restart_times+=("$NOW")

    # Trim old entries outside the rapid window
    CUTOFF=$((NOW - RAPID_WINDOW))
    filtered=()
    for t in "${restart_times[@]}"; do
        if (( t >= CUTOFF )); then
            filtered+=("$t")
        fi
    done
    restart_times=("${filtered[@]}")

    if (( ${#restart_times[@]} >= MAX_RAPID_RESTARTS )); then
        log "${YELLOW}Too many restarts (${#restart_times[@]} in ${RAPID_WINDOW}s). Backing off for ${BACKOFF_DELAY}s...${NC}"
        sleep "$BACKOFF_DELAY"
        restart_times=()
    else
        log "Restarting in ${RESTART_DELAY}s..."
        sleep "$RESTART_DELAY"
    fi
done

rm -f "$PIDFILE"
log "Monitor exiting."
