#!/bin/bash
# ThoughtFrame runtime entrypoint.
#
#   First install: unpack the baked WAR into the mount.
#   Upgrade:       overlay only the product code (WEB-INF/lib, WEB-INF/base, web.xml,
#                  startup.xconf, oemounts.xml) so catalog data/elastic and site-local
#                  files on the mounts survive.
#   Then:          supervise Jetty, forwarding stop signals so `docker stop` is clean.
set -euo pipefail

APP_DIR="${APP_DIR:-/opt/jetty-base/webapps/ROOT}"
BAKED_WAR="${BAKED_WAR:-/opt/thoughtframe/ROOT.war}"
BOOTSTRAP_URL="${BOOTSTRAP_WAR_URL:-}"
BOOTSTRAP_RESOLVE="${BOOTSTRAP_RESOLVE:-}"
JAVA_OPTS="${JAVA_OPTS:-}"

# JNA / Jetty use restricted native methods; enable access so JDK 25 doesn't warn (and
# won't hard-fail once that becomes enforced).
if [[ "$JAVA_OPTS" != *"--enable-native-access"* ]]; then
	JAVA_OPTS="$JAVA_OPTS --enable-native-access=ALL-UNNAMED"
fi

echo "Starting ThoughtFrame runtime container..."

mkdir -p "$APP_DIR"

resolve_war() {
	if [ -f "$BAKED_WAR" ]; then
		echo "$BAKED_WAR"
		return 0
	fi
	if [ -n "$BOOTSTRAP_URL" ]; then
		echo "Fetching WAR from BOOTSTRAP_WAR_URL..." >&2
		mkdir -p /tmp/bootstrap
		if [ -n "$BOOTSTRAP_RESOLVE" ]; then
			curl -fL --resolve "$BOOTSTRAP_RESOLVE" "$BOOTSTRAP_URL" -o /tmp/bootstrap/ROOT.war
		else
			curl -fL "$BOOTSTRAP_URL" -o /tmp/bootstrap/ROOT.war
		fi
		echo "/tmp/bootstrap/ROOT.war"
		return 0
	fi
	return 1
}

LIB_DIR="$APP_DIR/WEB-INF/lib"
FIRST_INSTALL=0
if [ ! -d "$LIB_DIR" ] || [ -z "$(ls -A "$LIB_DIR" 2>/dev/null)" ]; then
	FIRST_INSTALL=1
fi

WAR_FILE="$(resolve_war || true)"
if [ -z "$WAR_FILE" ]; then
	echo "WARNING: no baked WAR at $BAKED_WAR and no BOOTSTRAP_WAR_URL — starting as-is." >&2
elif [ "$FIRST_INSTALL" -eq 1 ]; then
	echo "First install: unpacking $WAR_FILE into $APP_DIR"
	unzip -q -o "$WAR_FILE" -d "$APP_DIR"
	echo "Bootstrap complete."
else
	# Overlay upgrade: product code only. Never wipe webapp/, data/ or elastic/ trees.
	echo "Existing site: overlaying product code from $WAR_FILE"
	rm -rf "$APP_DIR/WEB-INF/lib" "$APP_DIR/WEB-INF/base"
	# unzip exits 11 when a listed member is absent (no oemounts.xml in the WAR); the
	# matched members are still extracted, so only a real error (2+) stops the container.
	OVERLAY_STATUS=0
	unzip -q -o "$WAR_FILE" \
		"WEB-INF/lib/*" "WEB-INF/base/*" "WEB-INF/web.xml" "WEB-INF/startup.xconf" \
		"WEB-INF/oemounts.xml" -d "$APP_DIR" || OVERLAY_STATUS=$?
	if [ "$OVERLAY_STATUS" -ne 0 ] && [ "$OVERLAY_STATUS" -ne 11 ]; then
		echo "ERROR: overlay of $WAR_FILE failed (status $OVERLAY_STATUS)" >&2
		exit "$OVERLAY_STATUS"
	fi
	echo "Overlay complete."
fi

# WEB-INF/classes shadows WEB-INF/lib on the classpath and is never refreshed by the
# overlay above; drop it if an older image left one behind.
if [ -d "$APP_DIR/WEB-INF/classes" ]; then
	echo "Removing stale $APP_DIR/WEB-INF/classes (it would shadow WEB-INF/lib)"
	rm -rf "$APP_DIR/WEB-INF/classes"
fi

# --- supervisor: keep Jetty up, forward stop signals so `docker stop` is clean ---
JETTY_PID=""
shutdown() {
	echo "Stop signal received — shutting Jetty down."
	if [ -n "$JETTY_PID" ] && kill -0 "$JETTY_PID" 2>/dev/null; then
		kill -TERM "$JETTY_PID" 2>/dev/null || true
		wait "$JETTY_PID" 2>/dev/null || true
	fi
	exit 0
}
trap shutdown TERM INT

while true; do
	echo "Launching Jetty..."
	java $JAVA_OPTS -jar "$JETTY_HOME/start.jar" "jetty.base=$JETTY_BASE" &
	JETTY_PID=$!
	echo "Jetty PID: $JETTY_PID"

	EXIT_CODE=0
	wait "$JETTY_PID" || EXIT_CODE=$?
	JETTY_PID=""

	echo "Jetty exited with code $EXIT_CODE"
	if [ "$EXIT_CODE" -eq 0 ]; then
		echo "Clean exit — stopping container."
		exit 0
	fi
	sleep 2
	echo "Restarting Jetty..."
done
