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

PACK_DIR=${PACK_DIR:-"$DEVENV_ROOT"}
PORT=${PORT:-8080}
WORLD=${WORLD:-aeroslop-test}
MEMORY=${MEMORY:-4G}
DISPLAY_MODE=${DISPLAY_MODE:-xwayland}
BOOT_TIMEOUT=${BOOT_TIMEOUT:-1800}
CACHE_DIR=${PACK_TEST_CACHE:-"${XDG_CACHE_HOME:-$HOME/.cache}/aeroslop-pack-test"}
GAME_DIR="$CACHE_DIR/minecraft-$(basename "$PACK_DIR")-$(printf '%s' "$PACK_DIR" | sha256sum | cut -c1-8)"

if [[ ! -f "$PACK_DIR/pack.toml" ]]; then
  echo "error: $PACK_DIR/pack.toml not found (set PACK_DIR)" >&2
  exit 1
fi

MC_VERSION=$(sed -n 's/^minecraft = "\(.*\)"$/\1/p' "$PACK_DIR/pack.toml")
NEOFORGE_VERSION=$(sed -n 's/^neoforge = "\(.*\)"$/\1/p' "$PACK_DIR/pack.toml")
if [[ -z "$MC_VERSION" || -z "$NEOFORGE_VERSION" ]]; then
  echo "error: could not read minecraft/neoforge versions from $PACK_DIR/pack.toml" >&2
  exit 1
fi

JAVA=$(command -v java)
mkdir -p "$CACHE_DIR"
LOG="$GAME_DIR/logs/latest.log"

cleanup() {
  set +e
  if [[ -n "${LAUNCH_PID:-}" ]] && kill -0 "$LAUNCH_PID" 2>/dev/null; then
    kill -TERM -- -"$LAUNCH_PID" 2>/dev/null
    wait "$LAUNCH_PID" 2>/dev/null
  fi
  if [[ -n "${SERVE_PID:-}" ]]; then
    kill "$SERVE_PID" 2>/dev/null
    wait "$SERVE_PID" 2>/dev/null
  fi
}
trap cleanup EXIT

echo "== packwiz serve (port $PORT)"
(cd "$PACK_DIR" && exec packwiz serve --port "$PORT" >"$CACHE_DIR/serve.log" 2>&1) &
SERVE_PID=$!

for i in $(seq 1 30); do
  if curl -fs "http://127.0.0.1:$PORT/pack.toml" >/dev/null 2>&1; then
    break
  fi
  if ! kill -0 "$SERVE_PID" 2>/dev/null; then
    echo "error: packwiz serve failed:" >&2
    cat "$CACHE_DIR/serve.log" >&2
    exit 1
  fi
  sleep 1
done
if ! curl -fs "http://127.0.0.1:$PORT/pack.toml" -o "$CACHE_DIR/served-pack.toml" 2>/dev/null; then
  echo "error: packwiz serve did not come up" >&2
  exit 1
fi
if ! cmp -s "$CACHE_DIR/served-pack.toml" "$PACK_DIR/pack.toml"; then
  echo "error: port $PORT is serving a different pack (stale serve process?)" >&2
  kill -0 "$SERVE_PID" 2>/dev/null || true
  exit 1
fi

echo "== fresh logs"
mkdir -p "$GAME_DIR"
rm -rf "$GAME_DIR/logs" "$GAME_DIR/crash-reports"
printf 'renderDistance:2\n' >"$GAME_DIR/options.txt"

echo "== launching headless client (mc=$MC_VERSION, neoforge=$NEOFORGE_VERSION, display=$DISPLAY_MODE)"
ASSETS_SOURCE=${MC_ASSETS_DIR:-}
if [[ -z "$ASSETS_SOURCE" ]]; then
  for d in "$HOME/.local/share/PrismLauncher/assets" "$HOME/.minecraft/assets"; do
    [[ -d "$d/objects" ]] && ASSETS_SOURCE="$d" && break
  done
fi
RUN=()
case "$DISPLAY_MODE" in
  wayland)
    ;;
  xvfb)
    unset WAYLAND_DISPLAY XDG_SESSION_TYPE
    export LIBGL_ALWAYS_SOFTWARE=1
    RUN=(xvfb-run -a -s "-screen 0 1024x768x24")
    ;;
  xwayland|*)
    unset WAYLAND_DISPLAY XDG_SESSION_TYPE
    ;;
esac
tail -f /dev/null | setsid "${RUN[@]}" \
  python3 "$DEVENV_ROOT/scripts/launch-client.py" \
    --game-dir "$GAME_DIR" \
    ${ASSETS_SOURCE:+--assets-source "$ASSETS_SOURCE"} \
    --mc-version "$MC_VERSION" \
    --neoforge-version "$NEOFORGE_VERSION" \
    --pack-url "http://127.0.0.1:$PORT/pack.toml" \
    --world "$WORLD" \
    --java "$JAVA" \
    --memory "$MEMORY" \
    >"$CACHE_DIR/client-launch.log" 2>&1 &
LAUNCH_PID=$!

echo "== waiting for client boot (up to ${BOOT_TIMEOUT}s)"
markers() {
  { cat "$LOG" 2>/dev/null; cat "$CACHE_DIR/client-launch.log" 2>/dev/null; } | grep -a "$1" >/dev/null 2>&1
}
deadline=$((SECONDS + BOOT_TIMEOUT))
while (( SECONDS < deadline )); do
  if ! kill -0 "$LAUNCH_PID" 2>/dev/null; then
    echo "error: game exited during boot" >&2
    tail -60 "$LOG" >&2 2>/dev/null || tail -c 4000 "$CACHE_DIR/client-launch.log" >&2 2>/dev/null
    exit 1
  fi
  if markers "Loaded.*entity animations"; then
    break
  fi
  sleep 2
done

if ! markers "Loaded.*entity animations"; then
  echo "error: client did not finish booting within ${BOOT_TIMEOUT}s" >&2
  tail -60 "$LOG" >&2 2>/dev/null || tail -c 4000 "$CACHE_DIR/client-launch.log" >&2 2>/dev/null
  exit 1
fi

echo "== client booted; letting it settle 10s"
sleep 10
if ! kill -0 "$LAUNCH_PID" 2>/dev/null; then
  echo "error: game crashed after boot" >&2
  tail -60 "$LOG" >&2
  exit 1
fi

mod_count=$(ls "$PACK_DIR"/mods/*.pw.toml 2>/dev/null | wc -l)
if [[ $mod_count -gt 0 ]] && ! ls "$GAME_DIR"/mods/*.jar >/dev/null 2>&1; then
  echo "error: pack has $mod_count mods but no mods were installed into the game" >&2
  exit 1
fi

echo "== stopping game"
kill -TERM -- -"$LAUNCH_PID" 2>/dev/null || true
wait "$LAUNCH_PID" 2>/dev/null || true
LAUNCH_PID=""

if ls "$GAME_DIR/crash-reports"/*.txt >/dev/null 2>&1; then
  echo "error: crash report generated:" >&2
  ls "$GAME_DIR/crash-reports"/*.txt >&2
  exit 1
fi

echo "== PASS: client booted with pack (mods loaded, mc=$MC_VERSION, neoforge=$NEOFORGE_VERSION)"
