#!/usr/bin/env bash
# scripts/devnet/start-devnet.sh
# Multi-client XDC devnet startup script (fix #91).
#
# Spins up a local XDC devnet with up to four clients:
#   - GP5 (go-ethereum XDC fork)   — mandatory, acts as bootnode
#   - Erigon-XDC                   — optional (ERIGON_BIN must be set)
#   - Nethermind-XDC               — optional (NETHERMIND_BIN must be set)
#   - Reth-XDC                     — optional (RETH_BIN must be set)
#
# USAGE
#   ./scripts/devnet/start-devnet.sh [--clean] [--network mainnet|apothem]
#
# OPTIONS
#   --clean              Remove all data directories before starting
#   --network <net>      Network to use: mainnet (50, default) or apothem (51)
#   --gp5-bin <path>     Path to GP5 binary (default: ./build/bin/geth)
#   --erigon-bin <path>  Path to Erigon-XDC binary
#   --neth-bin <path>    Path to Nethermind-XDC binary
#   --reth-bin <path>    Path to Reth-XDC binary
#   --data-dir <dir>     Base data directory (default: /tmp/xdc-devnet)
#   --help               Show this help message
#
# EXAMPLE
#   # Start GP5 + Erigon on Apothem:
#   ERIGON_BIN=/opt/erigon-xdc ./scripts/devnet/start-devnet.sh --network apothem

set -euo pipefail

# ---- Defaults ----------------------------------------------------------
NETWORK="mainnet"
NETWORK_ID=50
CLEAN=false
BASE_DATA="/tmp/xdc-devnet"
GP5_BIN="${GP5_BIN:-./build/bin/geth}"
ERIGON_BIN="${ERIGON_BIN:-}"
NETH_BIN="${NETHERMIND_BIN:-}"
RETH_BIN="${RETH_BIN:-}"

LOG_DIR=""
PIDS=()

# ---- Arg parsing -------------------------------------------------------
while [[ $# -gt 0 ]]; do
  case "$1" in
    --clean)       CLEAN=true; shift ;;
    --network)     NETWORK="$2"; shift 2 ;;
    --gp5-bin)     GP5_BIN="$2"; shift 2 ;;
    --erigon-bin)  ERIGON_BIN="$2"; shift 2 ;;
    --neth-bin)    NETH_BIN="$2"; shift 2 ;;
    --reth-bin)    RETH_BIN="$2"; shift 2 ;;
    --data-dir)    BASE_DATA="$2"; shift 2 ;;
    --help|-h)
      head -40 "$0" | grep '^#' | sed 's/^# \?//'
      exit 0
      ;;
    *) echo "Unknown option: $1"; exit 1 ;;
  esac
done

case "$NETWORK" in
  mainnet|xdc|50) NETWORK="mainnet"; NETWORK_ID=50 ;;
  apothem|51)     NETWORK="apothem"; NETWORK_ID=51 ;;
  *) echo "ERROR: unknown network '$NETWORK'"; exit 1 ;;
esac

# ---- Setup -------------------------------------------------------------
GP5_DATA="$BASE_DATA/gp5"
ERIGON_DATA="$BASE_DATA/erigon"
NETH_DATA="$BASE_DATA/nethermind"
RETH_DATA="$BASE_DATA/reth"
LOG_DIR="$BASE_DATA/logs"

if $CLEAN; then
  echo "==> Cleaning $BASE_DATA ..."
  rm -rf "$BASE_DATA"
fi

mkdir -p "$GP5_DATA" "$LOG_DIR"

# ---- Trap for cleanup --------------------------------------------------
cleanup() {
  echo ""
  echo "==> Shutting down devnet ..."
  for pid in "${PIDS[@]}"; do
    kill "$pid" 2>/dev/null || true
  done
  wait 2>/dev/null || true
  echo "==> Done."
}
trap cleanup INT TERM EXIT

# ---- GP5 (mandatory bootnode) ------------------------------------------
if [[ ! -x "$GP5_BIN" ]]; then
  echo "ERROR: GP5 binary not found at '$GP5_BIN'. Build with: make geth"
  exit 1
fi

echo "==> Starting GP5 ($NETWORK, networkId=$NETWORK_ID) ..."
"$GP5_BIN" \
  --networkid "$NETWORK_ID" \
  --datadir "$GP5_DATA" \
  --port 30303 \
  --http \
  --http.port 8545 \
  --http.api eth,net,web3,xdpos,debug \
  --ws \
  --ws.port 8546 \
  --ws.api eth,net,web3,xdpos \
  --syncmode full \
  --gcmode archive \
  --nodiscover \
  --maxpeers 10 \
  --verbosity 3 \
  &> "$LOG_DIR/gp5.log" &
GP5_PID=$!
PIDS+=("$GP5_PID")
echo "    GP5 PID=$GP5_PID  log=$LOG_DIR/gp5.log"
echo "    RPC: http://localhost:8545  WS: ws://localhost:8546"

# Wait for GP5 to start and get its enode
sleep 3
GP5_ENODE=$("$GP5_BIN" attach --exec "admin.nodeInfo.enode" "$GP5_DATA/geth.ipc" 2>/dev/null | tr -d '"' || echo "")
if [[ -z "$GP5_ENODE" ]]; then
  echo "WARN: could not get GP5 enode — peers will need to be added manually"
else
  echo "    Enode: $GP5_ENODE"
fi

# ---- Erigon-XDC (optional) ---------------------------------------------
if [[ -n "$ERIGON_BIN" && -x "$ERIGON_BIN" ]]; then
  echo "==> Starting Erigon-XDC ..."
  mkdir -p "$ERIGON_DATA"
  ERIGON_ARGS=(
    --chain xdc
    --datadir "$ERIGON_DATA"
    --port 30304
    --http
    --http.port 8547
    --http.api eth,net,web3,debug
    --ws
    --ws.port 8548
    --verbosity 3
    --nodiscover
  )
  [[ -n "$GP5_ENODE" ]] && ERIGON_ARGS+=(--staticpeers "$GP5_ENODE")
  "$ERIGON_BIN" "${ERIGON_ARGS[@]}" &> "$LOG_DIR/erigon.log" &
  ERIGON_PID=$!
  PIDS+=("$ERIGON_PID")
  echo "    Erigon PID=$ERIGON_PID  RPC: http://localhost:8547"
else
  [[ -n "$ERIGON_BIN" ]] && echo "WARN: ERIGON_BIN=$ERIGON_BIN not executable — skipping"
  echo "    Erigon: not configured (set ERIGON_BIN to enable)"
fi

# ---- Nethermind-XDC (optional) -----------------------------------------
if [[ -n "$NETH_BIN" && -x "$NETH_BIN" ]]; then
  echo "==> Starting Nethermind-XDC ..."
  mkdir -p "$NETH_DATA"
  NETH_ARGS=(
    --config "xdc-$NETWORK"
    --datadir "$NETH_DATA"
    --JsonRpc.Enabled true
    --JsonRpc.Port 8549
    --JsonRpc.WebSocketsPort 8550
    --Network.DiscoveryPort 30305
    --Network.P2PPort 30305
  )
  [[ -n "$GP5_ENODE" ]] && NETH_ARGS+=(--Discovery.Bootnodes "$GP5_ENODE")
  "$NETH_BIN" "${NETH_ARGS[@]}" &> "$LOG_DIR/nethermind.log" &
  NETH_PID=$!
  PIDS+=("$NETH_PID")
  echo "    Nethermind PID=$NETH_PID  RPC: http://localhost:8549"
else
  echo "    Nethermind: not configured (set NETHERMIND_BIN to enable)"
fi

# ---- Reth-XDC (optional) -----------------------------------------------
if [[ -n "$RETH_BIN" && -x "$RETH_BIN" ]]; then
  echo "==> Starting Reth-XDC ..."
  mkdir -p "$RETH_DATA"
  RETH_ARGS=(
    node
    --chain xdc-"$NETWORK"
    --datadir "$RETH_DATA"
    --port 30306
    --http
    --http.port 8551
    --ws
    --ws.port 8552
    --log.level info
  )
  [[ -n "$GP5_ENODE" ]] && RETH_ARGS+=(--bootnodes "$GP5_ENODE")
  "$RETH_BIN" "${RETH_ARGS[@]}" &> "$LOG_DIR/reth.log" &
  RETH_PID=$!
  PIDS+=("$RETH_PID")
  echo "    Reth PID=$RETH_PID  RPC: http://localhost:8551"
else
  echo "    Reth: not configured (set RETH_BIN to enable)"
fi

# ---- Status summary ----------------------------------------------------
echo ""
echo "==> XDC devnet running (network=$NETWORK, networkId=$NETWORK_ID)"
echo "    Logs: $LOG_DIR/"
echo "    Press Ctrl+C to stop all clients."
echo ""

# ---- Health monitor loop ----------------------------------------------
while true; do
  sleep 30
  for pid in "${PIDS[@]}"; do
    if ! kill -0 "$pid" 2>/dev/null; then
      echo "WARN: process PID=$pid has exited — check logs in $LOG_DIR/"
    fi
  done
done
