#!/usr/bin/env bash
#
# Reaper's Sky - dedicated server deploy script (Debian 13 / trixie)
#
# Installs everything needed to run the Reaper's Sky NeoForge 21.1.248 server:
#   - OpenJDK 21 (JRE, headless) + curl/unzip
#   - NeoForge 21.1.248 server via its official installer
#   - the server-safe mods (pinned in mods.json, verified by sha1)
#   - eula.txt + server.properties (IP reaperofveriod.nl)
#   - run.sh (8 GB, G1GC)
#
# Usage:  sudo ./deploy.sh          (installs packages, needs root/sudo)
#         ./deploy.sh               (idempotent; safe to re-run)
#
# Defaults:
#   DIR       = "$HOME/reaper-sky-server"
#   MEMORY    = 8G
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
NEOFORGE_VERSION="21.1.248"
MC_VERSION="1.21.1"
INSTALLER_URL="https://maven.neoforged.net/releases/net/neoforged/neoforge/${NEOFORGE_VERSION}/neoforge-${NEOFORGE_VERSION}-installer.jar"

# --- config (override via env if you want) ------------------------------------
SERVER_DIR="${DIR:-$HOME/reaper-sky-server}"
MEMORY="${MEMORY:-8G}"
SERVER_IP="${SERVER_IP:-}"  # empty = bind all interfaces; reach server via edge port-forward
DEFAULT_MOTD="Reaper's Sky"
MOTD="${MOTD:-$DEFAULT_MOTD}"
MAX_PLAYERS="${MAX_PLAYERS:-10}"

log()  { printf '\033[1;34m[deploy]\033[0m %s\n' "$*"; }
die()  { printf '\033[1;31m[deploy] ERROR:\033[0m %s\n' "$*" >&2; exit 1; }

# --- 1. system packages (Debian 13 ships OpenJDK 21) --------------------------
install_packages() {
  if [ "$(id -u)" -ne 0 ]; then
    if command -v sudo >/dev/null 2>&1; then SUDO="sudo"; else SUDO=""; fi
  else
    SUDO=""
  fi
  if command -v java >/dev/null 2>&1; then
    log "Java already present: $(java -version 2>&1 | head -1)"
  else
    log "Installing openjdk-21-jre-headless, curl, unzip (apt)..."
    ${SUDO:+sudo} apt-get update -qq
    ${SUDO:+sudo} apt-get install -y -qq openjdk-21-jre-headless curl unzip
  fi
  java -version >/dev/null 2>&1 || die "Java 21 not available after install"
}

# --- 2. NeoForge server --------------------------------------------------------
install_neoforge() {
  mkdir -p "$SERVER_DIR"
  cd "$SERVER_DIR"
  if [ -f "run.sh" ] && [ -d "libraries/net/neoforged/neoforge/$NEOFORGE_VERSION" ]; then
    log "NeoForge $NEOFORGE_VERSION already installed."
    return
  fi
  log "Downloading NeoForge $NEOFORGE_VERSION installer..."
  curl -fL --retry 3 -o "neoforge-${NEOFORGE_VERSION}-installer.jar" "$INSTALLER_URL"
  log "Running installer --installServer ..."
  java -jar "neoforge-${NEOFORGE_VERSION}-installer.jar" --installServer
  rm -f "neoforge-${NEOFORGE_VERSION}-installer.jar"
  chmod +x run.sh
}

# --- 3. server mods (verified by sha1) -----------------------------------------
install_mods() {
  [ -f "$SCRIPT_DIR/mods.json" ] || die "mods.json not found next to deploy.sh"
  mkdir -p "$SERVER_DIR/mods"
  cd "$SERVER_DIR/mods"
  python3 - "$SCRIPT_DIR/mods.json" <<'PY'
import json, sys, hashlib, subprocess, os
manifest = json.load(open(sys.argv[1]))
keep = set()
for m in manifest["mods"]:
    fname, url, want = m["file"], m["url"], m["sha1"]
    keep.add(fname)
    tmp = fname + ".part"
    if os.path.exists(fname):
        h = hashlib.sha1()
        with open(fname, "rb") as fh:
            for b in iter(lambda: fh.read(65536), b""):
                h.update(b)
        if h.hexdigest() == want:
            continue  # already present & correct
    if not url:
        raise SystemExit(f"no download URL for {fname}")
    subprocess.run(["curl", "-fsSL", "--retry", "3", "-o", tmp, url], check=True)
    h = hashlib.sha1()
    with open(tmp, "rb") as fh:
        for b in iter(lambda: fh.read(65536), b""):
            h.update(b)
    if h.hexdigest() != want:
        os.unlink(tmp)
        raise SystemExit(f"sha1 mismatch for {fname}")
    os.rename(tmp, fname)
    print(f"  + {fname}")
# remove jars that are no longer part of the pack
for f in sorted(os.listdir(".")):
    if f.endswith(".jar") and f not in keep:
        os.unlink(f)
        print(f"  - {f} (stale)")
PY
  log "Mods ready: $(ls -1 "$SERVER_DIR/mods"/*.jar | wc -l) jars installed."
}

# --- 4. eula + server.properties -----------------------------------------------
write_config() {
  cd "$SERVER_DIR"
  if [ ! -f eula.txt ]; then
    printf 'eula=true\n' > eula.txt
    log "Accepted Minecraft EULA (eula.txt)."
  fi
  cat > server.properties <<EOF
# Generated by Reaper's Sky deploy.sh
server-ip=$SERVER_IP
server-port=25565
motd=$MOTD
max-players=$MAX_PLAYERS
online-mode=true
difficulty=hard
level-type=default
allow-nether=true
spawn-protection=0
view-distance=10
simulation-distance=10
EOF
  log "Wrote server.properties (IP=$SERVER_IP, max=$MAX_PLAYERS)."
}

# --- 5. run script ---------------------------------------------------------------
write_run() {
  cat > "$SERVER_DIR/run.sh" <<'EOF'
#!/usr/bin/env bash
cd "$(dirname "$(readlink -f "$0")")"
exec java -XmsMEMORY -XmxMEMORY -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 \
  @libraries/net/neoforged/neoforge/NEOFORGE_VERSION/unix_args.txt nogui
EOF
  sed -i "s/MEMORY/$MEMORY/g; s/NEOFORGE_VERSION/$NEOFORGE_VERSION/g" "$SERVER_DIR/run.sh"
  chmod +x "$SERVER_DIR/run.sh"
  log "Wrote run.sh ($MEMORY RAM). Start with:  cd $SERVER_DIR && ./run.sh"
}

install_packages
install_neoforge
install_mods
write_config
write_run

log "Done. Reaper's Sky server is at: $SERVER_DIR"
log "First boot generates the world. Run it with:  cd $SERVER_DIR && ./run.sh"
log "Console: run inside tmux/screen so it keeps running when you disconnect."
log "To stop later: use the server console command  stop"