#!/bin/sh

set -eu

APP_ROOT="${APP_ROOT:-/app}"
STATE_DIR="${WORK_SERVER_STATE_DIR:-/tmp/work-server-runtime}"
DIST_DIR="${WORK_SERVER_DIST_DIR:-dist}"
DIST_ENTRY="$DIST_DIR/server.js"
LOCK_FILE="$APP_ROOT/package-lock.json"
LOCK_HASH_FILE="$STATE_DIR/package-lock.sha256"
CHILD_PID=""
STOP_REQUESTED="0"
RELOAD_REQUESTED="0"

mkdir -p "$STATE_DIR"
cd "$APP_ROOT"

log() {
  printf '[work-server-supervisor] %s\n' "$*"
}

ensure_dependencies() {
  if [ ! -f "$LOCK_FILE" ]; then
    log "package-lock.json not found; skipping npm ci"
    return 0
  fi

  CURRENT_HASH=$(sha256sum "$LOCK_FILE" | awk '{print $1}')
  PREVIOUS_HASH=""

  if [ -f "$LOCK_HASH_FILE" ]; then
    PREVIOUS_HASH=$(cat "$LOCK_HASH_FILE")
  fi

  if [ ! -d "$APP_ROOT/node_modules" ] || [ "$CURRENT_HASH" != "$PREVIOUS_HASH" ]; then
    log "installing dependencies"
    npm ci --legacy-peer-deps
    printf '%s' "$CURRENT_HASH" >"$LOCK_HASH_FILE"
  fi
}

prepare_runtime() {
  ensure_dependencies
  log "building latest source"
  npm run build
}

prepare_runtime_or_fallback() {
  if prepare_runtime; then
    return 0
  fi

  if [ -f "$DIST_ENTRY" ]; then
    log "build failed; using existing dist at $DIST_ENTRY"
    return 0
  fi

  return 1
}

start_child() {
  log "starting server process"
  npm run start &
  CHILD_PID=$!
}

request_reload() {
  log "reload requested"
  if prepare_runtime; then
    RELOAD_REQUESTED="1"
    if [ -n "$CHILD_PID" ]; then
      kill -TERM "$CHILD_PID" 2>/dev/null || true
    fi
  else
    log "reload aborted because build failed; keeping current process"
  fi
}

request_stop() {
  STOP_REQUESTED="1"
  log "shutdown requested"
  if [ -n "$CHILD_PID" ]; then
    kill -TERM "$CHILD_PID" 2>/dev/null || true
  fi
}

trap 'request_reload' HUP
trap 'request_stop' INT TERM

prepare_runtime_or_fallback

while :; do
  start_child
  set +e
  wait "$CHILD_PID"
  EXIT_CODE=$?
  set -e
  CHILD_PID=""

  if [ "$STOP_REQUESTED" = "1" ]; then
    exit "$EXIT_CODE"
  fi

  if [ "$RELOAD_REQUESTED" = "1" ]; then
    RELOAD_REQUESTED="0"
    continue
  fi

  log "server exited unexpectedly with code $EXIT_CODE; restarting in 2 seconds"
  sleep 2
done
