#!/usr/bin/env bash
set -Eeuo pipefail

BASE=/opt/telos-evm-3
URL=${URL:-https://storage.telos.net/latest-reth.tar.zst}
ARCHIVE=$BASE/downloads/latest-reth.tar.zst
DEST=$BASE/telos-reth-data-seeded
EXTRACT=$BASE/telos-reth-data-seeded.extracting
LOG=$BASE/logs/bootstrap-seeded-reth-sidecar.log
LOCK=/run/lock/telos-seeded-bootstrap.lock

mkdir -p "$BASE/downloads" "$BASE/logs" "$BASE/etc" /run/lock
exec >>"$LOG" 2>&1

log() { printf "[%s] %s\n" "$(date -Is)" "$*"; }

rpc() {
  local payload=$1
  curl -fsS --max-time 15 -H "Content-Type: application/json" --data "$payload" http://127.0.0.1:8645
}

if [ "${1:-}" != "--inside-lock" ]; then
  exec flock -n "$LOCK" "$0" --inside-lock
fi

log "bootstrap starting"
log "source url: $URL"

cat > "$BASE/etc/reth-seeded.env" <<ENV
RETH_DATADIR=$DEST
RETH_HTTP_ADDR=127.0.0.1
RETH_RPC_PORT=8645
RETH_WS_ADDR=127.0.0.1
RETH_WS_PORT=8646
RETH_AUTH_ADDR=127.0.0.1
RETH_AUTH_RPC_PORT=8651
RETH_DISCOVERY_PORT=30304
RETH_METRICS_ADDR=127.0.0.1
RETH_METRICS_PORT=9102
RETH_PERSISTENCE_THRESHOLD=20
RETH_PERSISTENCE_BACKPRESSURE_THRESHOLD=30
RETH_MEMORY_BLOCK_BUFFER_TARGET=30
ENV
chmod 600 "$BASE/etc/reth-seeded.env"

cat > /etc/systemd/system/telos-evm3-reth-seeded.service <<SERVICE
[Unit]
Description=TelosEVM 3.0 reth v2 seeded sidecar
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
EnvironmentFile=$BASE/etc/reth.env
EnvironmentFile=$BASE/etc/reth-seeded.env
WorkingDirectory=$BASE/telos-reth-v2
ExecStartPre=$BASE/bin/wait-external-telos.sh http
ExecStart=$BASE/bin/telos-reth-v2.sh
Restart=always
RestartSec=10
TimeoutStartSec=0
LimitNOFILE=1048576
StandardOutput=append:$BASE/logs/reth-seeded.log
StandardError=append:$BASE/logs/reth-seeded.log

[Install]
WantedBy=multi-user.target
SERVICE

cat > /etc/systemd/system/telos-evm3-consensus-seeded.service <<SERVICE
[Unit]
Description=TelosEVM 3.0 consensus client seeded sidecar
After=network-online.target telos-evm3-reth-seeded.service
Wants=network-online.target telos-evm3-reth-seeded.service

[Service]
Type=simple
Environment=RETH_RPC=http://127.0.0.1:8645
WorkingDirectory=$BASE/telos-consensus-client
ExecStartPre=$BASE/bin/wait-external-telos.sh ship
ExecStartPre=$BASE/bin/wait-external-telos.sh reth
ExecStart=$BASE/telos-consensus-client/target/release/telos-consensus-client --config $BASE/etc/consensus-seeded.toml
Restart=always
RestartSec=10
TimeoutStartSec=0
LimitNOFILE=1048576
StandardOutput=append:$BASE/logs/consensus-seeded.log
StandardError=append:$BASE/logs/consensus-seeded.log

[Install]
WantedBy=multi-user.target
SERVICE

systemctl daemon-reload

log "fetching headers"
curl -fsSIL --retry 5 --retry-delay 5 "$URL" > "$ARCHIVE.headers"
expected_bytes=$(awk 'BEGIN{IGNORECASE=1} /^content-length:/ {gsub("\r", "", $2); v=$2} END{print v}' "$ARCHIVE.headers")
last_modified=$(awk 'BEGIN{IGNORECASE=1} /^last-modified:/ {sub(/^[^:]+:[[:space:]]*/, ""); gsub("\r", ""); v=$0} END{print v}' "$ARCHIVE.headers")
etag=$(awk 'BEGIN{IGNORECASE=1} /^etag:/ {gsub("\r", "", $2); v=$2} END{print v}' "$ARCHIVE.headers")
log "expected bytes: ${expected_bytes:-unknown}; last-modified: ${last_modified:-unknown}; etag: ${etag:-unknown}"

if [ -s "$ARCHIVE" ] && [ -n "${expected_bytes:-}" ] && [ "$(stat -c%s "$ARCHIVE")" = "$expected_bytes" ]; then
  log "archive already complete: $ARCHIVE"
else
  log "downloading archive to $ARCHIVE"
  curl -fL --retry 999 --retry-delay 20 --retry-all-errors --continue-at - -o "$ARCHIVE" "$URL"
fi

actual_bytes=$(stat -c%s "$ARCHIVE")
if [ -n "${expected_bytes:-}" ] && [ "$actual_bytes" != "$expected_bytes" ]; then
  log "size mismatch: expected $expected_bytes got $actual_bytes"
  exit 10
fi
log "archive size verified: $actual_bytes bytes"
sha256sum "$ARCHIVE" > "$ARCHIVE.sha256"
log "archive sha256: $(cut -d' ' -f1 "$ARCHIVE.sha256")"

if [ -d "$DEST/db" ] && [ -d "$DEST/static_files" ]; then
  log "seeded datadir already present at $DEST; skipping extract"
else
  if [ -e "$DEST" ]; then
    backup="$DEST.prebootstrap-$(date -u +%Y%m%dT%H%M%SZ)"
    log "preserving existing destination as $backup"
    mv "$DEST" "$backup"
  fi
  rm -rf "$EXTRACT"
  mkdir -p "$EXTRACT"
  log "extracting archive"
  tar --use-compress-program=unzstd -xf "$ARCHIVE" -C "$EXTRACT"

  candidate=""
  for path in "$EXTRACT" "$EXTRACT/telos-reth-data" "$EXTRACT/reth-data" "$EXTRACT/opt/telos-evm-3/telos-reth-data"; do
    if [ -d "$path/db" ] && [ -d "$path/static_files" ]; then
      candidate="$path"
      break
    fi
  done
  if [ -z "$candidate" ]; then
    candidate=$(find "$EXTRACT" -maxdepth 5 -type d -name db -printf "%h\n" | while read -r p; do [ -d "$p/static_files" ] && { printf "%s\n" "$p"; break; }; done)
  fi
  if [ -z "$candidate" ]; then
    log "could not identify reth datadir inside archive"
    find "$EXTRACT" -maxdepth 3 -mindepth 1 -printf "%y %p\n" | sed -n "1,200p"
    exit 11
  fi
  log "identified datadir: $candidate"
  rm -f "$candidate/reth.ipc"
  if [ "$candidate" = "$EXTRACT" ]; then
    mv "$EXTRACT" "$DEST"
  else
    mv "$candidate" "$DEST"
    rm -rf "$EXTRACT"
  fi
fi

if [ ! -s "$DEST/jwt.hex" ]; then
  log "generating sidecar jwt"
  openssl rand -hex 32 > "$DEST/jwt.hex"
fi
chmod 600 "$DEST/jwt.hex"
rm -f "$DEST/reth.ipc"

log "running seeded reth consistency repair"
set -a
# shellcheck disable=SC1091
. "$BASE/etc/reth.env"
# shellcheck disable=SC1091
. "$BASE/etc/reth-seeded.env"
set +a
repair_log="$BASE/logs/reth-seeded-consistency-repair-$(date -u +%Y%m%dT%H%M%SZ).log"
repair_rc=0
timeout -s INT 180 "$RETH_BIN" node \
  --chain "$RETH_CHAIN" \
  --datadir "$RETH_DATADIR" \
  --http --http.addr "$RETH_HTTP_ADDR" --http.port "$RETH_RPC_PORT" --http.api eth,net,web3 \
  --authrpc.addr "$RETH_AUTH_ADDR" --authrpc.port "$RETH_AUTH_RPC_PORT" \
  --authrpc.jwtsecret "$RETH_DATADIR/jwt.hex" \
  --ipcpath "$RETH_DATADIR/reth.ipc" \
  --port "$RETH_DISCOVERY_PORT" --discovery.port "$RETH_DISCOVERY_PORT" \
  --metrics "$RETH_METRICS_ADDR:$RETH_METRICS_PORT" \
  --engine.persistence-threshold "$RETH_PERSISTENCE_THRESHOLD" \
  --engine.persistence-backpressure-threshold "$RETH_PERSISTENCE_BACKPRESSURE_THRESHOLD" \
  --engine.memory-block-buffer-target "$RETH_MEMORY_BLOCK_BUFFER_TARGET" \
  --telos.telos_endpoint "$TELOS_ENDPOINT" \
  --telos.signer_account "$SIGNER_ACCOUNT" \
  --telos.signer_permission "$SIGNER_PERMISSION" \
  --telos.signer_key "$SIGNER_KEY" \
  --telos.trust_consensus false \
  --telos.build_state \
  >"$repair_log" 2>&1 || repair_rc=$?
if [ "$repair_rc" != 0 ] && [ "$repair_rc" != 124 ] && [ "$repair_rc" != 130 ]; then
  log "seeded reth consistency repair failed rc=$repair_rc; see $repair_log"
  tail -n 80 "$repair_log" || true
  exit 13
fi
log "seeded reth consistency repair completed rc=$repair_rc; see $repair_log"
rm -f "$DEST/reth.ipc"

log "starting seeded reth sidecar"
systemctl enable telos-evm3-reth-seeded.service >/dev/null
systemctl restart telos-evm3-reth-seeded.service

log "waiting for seeded reth rpc"
for i in $(seq 1 120); do
  if rpc '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' >/tmp/seeded-reth-blocknumber.json 2>/dev/null; then
    break
  fi
  sleep 5
  if [ "$i" = 120 ]; then
    log "seeded reth rpc did not become ready"
    systemctl status telos-evm3-reth-seeded.service --no-pager -n 80 || true
    exit 12
  fi
done

block_json=$(rpc '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false],"id":1}')
meta=$(BLOCK_JSON="$block_json" python3 - <<'PY'
import json
import os

obj = json.loads(os.environ["BLOCK_JSON"])
res = obj.get("result") or {}
num = res.get("number")
block_hash = res.get("hash")
if not num or not block_hash:
    raise SystemExit("missing latest block/hash from seeded reth")
height = int(num, 16)
print(f"{height} {block_hash}")
PY
)
height=${meta%% *}
hash=${meta#* }
start=$((height + 1))
jwt=$(tr -d "\n\r" < "$DEST/jwt.hex")
log "seeded reth latest height=$height hash=$hash; consensus start=$start"

mkdir -p "$BASE/telos-consensus-client-data-seeded"
cat > "$BASE/etc/consensus-seeded.toml" <<TOML
log_level = "info"
chain_id = 40

execution_endpoint = "http://127.0.0.1:8651"
jwt_secret = "$jwt"

ship_endpoint = "ws://154.12.118.141:8080"
chain_endpoint = "http://154.12.118.141:8888"

evm_start_block = $start
evm_deploy_block = 180698896
prev_hash = "$hash"

batch_size = 250
data_path = "$BASE/telos-consensus-client-data-seeded/db"
block_checkpoint_interval = 5000
maximum_sync_range = 500000000
latest_blocks_in_db_num = 10000

rpc_fallback_endpoints = ["https://rpc.telos.net/evm", "https://telos.drpc.org/", "https://rpc1.us.telos.net/evm"]
rpc_fallback_quorum = 2
rpc_fallback_retry_interval_secs = 5
rpc_fallback_sample_every_n = 1

raw_message_channel_size = 5000
block_message_channel_size = 5000
final_message_channel_size = 5000
TOML
chmod 600 "$BASE/etc/consensus-seeded.toml"

log "starting seeded consensus sidecar"
systemctl enable telos-evm3-consensus-seeded.service >/dev/null
systemctl restart telos-evm3-consensus-seeded.service

log "bootstrap complete"
systemctl --no-pager --full status telos-evm3-reth-seeded.service telos-evm3-consensus-seeded.service |
  sed -E "s/(--telos.signer_key) [^ ]+/\1 [REDACTED]/g" |
  sed -n "1,120p" || true
