#!/usr/bin/env sh
set -eu

cd /workspace
/bin/sh ./scripts/sync_userfront_locales.sh

cd /workspace/userfront
USERFRONT_INTERNAL_PORT="${USERFRONT_INTERNAL_PORT:-5000}"
USERFRONT_FLUTTER_RUN_FLAGS="${USERFRONT_FLUTTER_RUN_FLAGS:---debug}"
USERFRONT_BOOT_WARMUP_ATTEMPTS="${USERFRONT_BOOT_WARMUP_ATTEMPTS:-120}"
USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS="${USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS:-0.5}"
USERFRONT_BOOT_WARMUP_LOCALES="${USERFRONT_BOOT_WARMUP_LOCALES:-ko en}"
USERFRONT_BOOT_WARMUP_VIEWPORTS="${USERFRONT_BOOT_WARMUP_VIEWPORTS:-mobile:390 desktop:1440}"
USERFRONT_BOOT_BUILD_MARKER="${USERFRONT_BOOT_BUILD_MARKER:-build/.userfront-boot-build-start}"
USERFRONT_BOOT_LOG="${USERFRONT_BOOT_LOG:-build/userfront-boot-flutter.log}"
USERFRONT_BOOT_LOG_PIPE="${USERFRONT_BOOT_LOG_PIPE:-build/userfront-boot-flutter.pipe}"

echo "[userfront-boot] removing stale build/web before flutter run" >&2
rm -rf build/web
mkdir -p "$(dirname "$USERFRONT_BOOT_BUILD_MARKER")"
: > "$USERFRONT_BOOT_BUILD_MARKER"

warm_get() {
  path="$1"
  locale="$2"
  viewport="$3"
  width="${viewport#*:}"
  if [ "$width" = "$viewport" ]; then
    width=""
  fi

  wget -qO- \
    --header="Accept-Language: $locale" \
    --header="Viewport-Width: $width" \
    "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}${path}" >/dev/null 2>&1
}

wait_for_userfront_build() {
  flutter_pid="$1"
  attempt=1

  while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do
    if [ -f "build/web/index.html" ] && [ "build/web/index.html" -nt "$USERFRONT_BOOT_BUILD_MARKER" ]; then
      return 0
    fi
    if ! kill -0 "$flutter_pid" 2>/dev/null; then
      echo "[userfront-boot] warmup skipped because flutter exited before build/web/index.html was ready" >&2
      return 1
    fi
    attempt=$((attempt + 1))
    sleep "$USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS"
  done

  echo "[userfront-boot] warmup skipped after ${USERFRONT_BOOT_WARMUP_ATTEMPTS} build readiness attempts" >&2
  return 1
}

wait_for_userfront_serve_log() {
  flutter_pid="$1"
  attempt=1

  while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do
    if [ -f "$USERFRONT_BOOT_LOG" ] && grep -Fq "lib/main.dart is being served at" "$USERFRONT_BOOT_LOG"; then
      return 0
    fi
    if ! kill -0 "$flutter_pid" 2>/dev/null; then
      echo "[userfront-boot] warmup skipped because flutter exited before serve log was ready" >&2
      return 1
    fi
    attempt=$((attempt + 1))
    sleep "$USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS"
  done

  echo "[userfront-boot] warmup skipped after ${USERFRONT_BOOT_WARMUP_ATTEMPTS} serve readiness attempts" >&2
  return 1
}

disable_userfront_dev_service_worker() {
  cat > build/web/flutter_service_worker.js <<'EOF'
self.addEventListener("install", (event) => {
  self.skipWaiting();
});

self.addEventListener("activate", (event) => {
  event.waitUntil(self.registration.unregister());
});
EOF
}

warm_flutter_bootstrap_assets() {
  if [ ! -f build/web/flutter_bootstrap.js ]; then
    return 0
  fi

  grep -Eo 'main\.dart\.[^"]+\.(js|mjs|wasm)' build/web/flutter_bootstrap.js \
    | sort -u \
    | while IFS= read -r asset; do
        [ -n "$asset" ] || continue
        wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}/${asset}" >/dev/null 2>&1 || \
          echo "[userfront-boot] warmup warning: failed to load /${asset}" >&2
      done
}

warm_userfront_once() {
  flutter_pid="$1"
  attempt=1

  if ! wait_for_userfront_serve_log "$flutter_pid"; then
    return 0
  fi
  if ! wait_for_userfront_build "$flutter_pid"; then
    return 0
  fi
  disable_userfront_dev_service_worker

  while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do
    if wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}/flutter_bootstrap.js" >/dev/null 2>&1; then
      break
    fi
    if ! kill -0 "$flutter_pid" 2>/dev/null; then
      echo "[userfront-boot] warmup skipped because flutter exited before readiness" >&2
      return 0
    fi
    attempt=$((attempt + 1))
    sleep "$USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS"
  done

  if [ "$attempt" -gt "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; then
    echo "[userfront-boot] warmup skipped after ${USERFRONT_BOOT_WARMUP_ATTEMPTS} readiness attempts" >&2
    return 0
  fi

  started_at="$(date +%s)"
  echo "[userfront-boot] one-shot warmup starting locales=\"${USERFRONT_BOOT_WARMUP_LOCALES}\" viewports=\"${USERFRONT_BOOT_WARMUP_VIEWPORTS}\"" >&2

  for locale in $USERFRONT_BOOT_WARMUP_LOCALES; do
    for viewport in $USERFRONT_BOOT_WARMUP_VIEWPORTS; do
      warm_get "/${locale}/signin" "$locale" "$viewport" || true
    done
  done

  for asset in \
    / \
    /flutter_bootstrap.js \
    /canvaskit/skwasm.js \
    /canvaskit/skwasm.wasm \
    /canvaskit/skwasm_heavy.js \
    /canvaskit/skwasm_heavy.wasm \
    /assets/AssetManifest.bin.json \
    /assets/FontManifest.json
  do
    wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}${asset}" >/dev/null 2>&1 || true
  done
  warm_flutter_bootstrap_assets

  finished_at="$(date +%s)"
  elapsed_seconds=$((finished_at - started_at))
  echo "[userfront-boot] one-shot warmup completed in ${elapsed_seconds}s" >&2
}

set -- flutter run \
  -d web-server \
  --web-hostname 0.0.0.0 \
  --web-port "${USERFRONT_INTERNAL_PORT}" \
  --wasm \
  --dart-define=BACKEND_URL="${BACKEND_URL:-}" \
  --dart-define=CLIENT_LOG_DEBUG="${CLIENT_LOG_DEBUG:-false}" \
  --dart-define=APP_ENV="${APP_ENV:-dev}" \
  --dart-define=USERFRONT_URL="${USERFRONT_URL:-}" \
  ${USERFRONT_FLUTTER_RUN_FLAGS} \
  --no-web-resources-cdn

mkdir -p "$(dirname "$USERFRONT_BOOT_LOG")"
rm -f "$USERFRONT_BOOT_LOG" "$USERFRONT_BOOT_LOG_PIPE"
mkfifo "$USERFRONT_BOOT_LOG_PIPE"
tee "$USERFRONT_BOOT_LOG" < "$USERFRONT_BOOT_LOG_PIPE" &
tee_pid="$!"

"$@" > "$USERFRONT_BOOT_LOG_PIPE" 2>&1 &
flutter_pid="$!"

terminate() {
  kill "$flutter_pid" 2>/dev/null || true
  kill "$tee_pid" 2>/dev/null || true
  wait "$flutter_pid" 2>/dev/null || true
  wait "$tee_pid" 2>/dev/null || true
  rm -f "$USERFRONT_BOOT_LOG_PIPE"
}

trap terminate INT TERM
warm_userfront_once "$flutter_pid"
set +e
wait "$flutter_pid"
flutter_status="$?"
wait "$tee_pid" 2>/dev/null || true
rm -f "$USERFRONT_BOOT_LOG_PIPE"
exit "$flutter_status"
