#!/usr/bin/env bash
# prewarm-bundle — curl the Metro bundle URL before the dev client opens.
#
# Triggers Metro to compile and cache the bundle so the app connects instantly.
# Streams progress from the Metro log every 30s until the bundle curl finishes
# or MOBILE_BUNDLE_PREWARM_TIMEOUT seconds elapse.
# Set MOBILE_BUNDLE_PREWARM=0 to skip.
#
# Inputs:
#   --platform ios|android          (default ios)
#   --target <metamask-mobile dir>  (default $PWD)
#   --port <number>                 (default WATCHER_PORT env, else METRO_PORT, else 8081)
# Outputs:
#   Progress on stderr; exit 0 bundle ready; 1 timeout or curl error; 2 bad args.
#
# Single device op: prewarm the bundle. Does not start Metro or open the dev client.
set -uo pipefail

PLATFORM="ios"
TARGET="$PWD"
PORT="${WATCHER_PORT:-${METRO_PORT:-8081}}"

while [ "$#" -gt 0 ]; do
  case "$1" in
    --platform) PLATFORM="$2"; shift 2 ;;
    --target)   TARGET="$2"; shift 2 ;;
    --port)     PORT="$2"; shift 2 ;;
    -h|--help)
      printf 'Usage: prewarm-bundle.sh [--platform ios|android] [--target <dir>] [--port <n>]\n'
      exit 0
      ;;
    *) printf 'prewarm-bundle: unknown arg: %s\n' "$1" >&2; exit 2 ;;
  esac
done

case "$PLATFORM" in
  ios|android) ;;
  *) printf 'prewarm-bundle: --platform must be ios or android (got: %s)\n' "$PLATFORM" >&2; exit 2 ;;
esac

TARGET="$(cd "$TARGET" && pwd)"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
. "$SCRIPT_DIR/../shared/harness-path.sh"
if ! command -v recipe_runtime_dir >/dev/null 2>&1; then
  echo "prewarm-bundle: shared lib adapters/shared/harness-path.sh not found; reinstall the runner." >&2
  exit 1
fi
LOG_DIR="$TARGET/$(recipe_runtime_dir)" || exit 1
mkdir -p "$LOG_DIR"
METRO_LOG="$LOG_DIR/metro.log"

if [ "${MOBILE_BUNDLE_PREWARM:-1}" = "0" ]; then
  printf 'Skipping %s bundle prewarm (MOBILE_BUNDLE_PREWARM=0)\n' "$PLATFORM" >&2
  exit 0
fi

TIMEOUT="${MOBILE_BUNDLE_PREWARM_TIMEOUT:-900}"

BUNDLE_URL="http://localhost:${PORT}/index.bundle?platform=${PLATFORM}&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=1&transform.routerRoot=app&unstable_transformProfile=hermes-stable"

printf 'Prewarming %s bundle before launching dev client (set MOBILE_BUNDLE_PREWARM=0 to skip)\n' "$PLATFORM" >&2
printf '  url: %s\n' "$BUNDLE_URL" >&2

curl -sfL --connect-timeout 5 --max-time "$TIMEOUT" -o /dev/null "$BUNDLE_URL" &
BUNDLE_PID=$!

ELAPSED=0
LAST_PROGRESS=""
while kill -0 "$BUNDLE_PID" 2>/dev/null; do
  PROGRESS=""
  if [ -f "$METRO_LOG" ]; then
    PROGRESS="$(grep -E '^[[:space:]]*(iOS|Android).*index\.(js|tsx?).*%|Bundl(ed|ing)|Finished' "$METRO_LOG" 2>/dev/null | tail -1 | tr -d '\r' || true)"
  fi
  if [ -n "$PROGRESS" ] && [ "$PROGRESS" != "$LAST_PROGRESS" ]; then
    printf 'Bundle progress: %s\n' "$PROGRESS" >&2
    LAST_PROGRESS="$PROGRESS"
  elif [ $((ELAPSED % 30)) -eq 0 ] && [ "$ELAPSED" -gt 0 ]; then
    printf 'Waiting for %s bundle (%ss/%ss)%s\n' "$PLATFORM" "$ELAPSED" "$TIMEOUT" \
      "${LAST_PROGRESS:+ — $LAST_PROGRESS}" >&2
  fi
  if [ "$ELAPSED" -ge "$TIMEOUT" ]; then
    kill "$BUNDLE_PID" 2>/dev/null || true
    wait "$BUNDLE_PID" 2>/dev/null || true
    printf 'prewarm-bundle: %s bundle did not become ready before timeout (%ss)\n' "$PLATFORM" "$TIMEOUT" >&2
    [ -f "$METRO_LOG" ] && tail -80 "$METRO_LOG" >&2 || true
    printf '  Next: check %s for errors or reduce MOBILE_BUNDLE_PREWARM_TIMEOUT\n' "$METRO_LOG" >&2
    exit 1
  fi
  sleep 3
  ELAPSED=$((ELAPSED + 3))
done

if wait "$BUNDLE_PID"; then
  printf '%s bundle ready\n' "$PLATFORM" >&2
  exit 0
fi

printf 'prewarm-bundle: %s bundle curl failed\n' "$PLATFORM" >&2
[ -f "$METRO_LOG" ] && tail -80 "$METRO_LOG" >&2 || true
printf '  Next: check %s for Metro errors\n' "$METRO_LOG" >&2
exit 1
