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

# Runtime launcher for the CoderAI OCI image.
# Keeps config/model/cache state in mounted volumes and exposes the server outside
# the container by default.

: "${CODERAI_CONFIG_DIR:=/config}"
: "${CODERAI_MODELS_DIR:=/models}"
: "${CODERAI_CACHE_DIR:=/cache}"
: "${CODERAI_HOST:=0.0.0.0}"
: "${CODERAI_PORT:=8776}"

export PYTHONHOME=/opt/coderai/python
export PATH="/opt/coderai/python/bin:$PATH"
export XDG_CONFIG_HOME="$CODERAI_CONFIG_DIR"
export XDG_DATA_HOME="$CODERAI_MODELS_DIR"
export XDG_CACHE_HOME="$CODERAI_CACHE_DIR"
export HF_HOME="${HF_HOME:-$CODERAI_CACHE_DIR/huggingface}"
export HUGGINGFACE_HUB_CACHE="${HUGGINGFACE_HUB_CACHE:-$HF_HOME/hub}"

NV="/opt/coderai/python/lib/python3.13/site-packages/nvidia"
LIBS="/opt/coderai/python/lib:/opt/coderai/local-libs"
if [ -d "$NV" ]; then
  for d in "$NV"/*/lib; do
    [ -d "$d" ] && LIBS="$LIBS:$d"
  done
fi
export LD_LIBRARY_PATH="$LIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"

mkdir -p "$CODERAI_CONFIG_DIR/coderai" "$CODERAI_MODELS_DIR/coderai" "$CODERAI_CACHE_DIR/coderai"
CONFIG_DIR="$CODERAI_CONFIG_DIR/coderai"
CONFIG_FILE="$CONFIG_DIR/config.json"

# Bind host/port are passed to coderai on the CLI (--host/--port below), which
# override config.server in memory WITHOUT modifying config.json. This keeps an
# in-place-mounted config dir untouched at startup. We only CREATE config.json on
# first run (when it doesn't exist yet) — that's not modifying user config.
if [ ! -f "$CONFIG_FILE" ]; then
  /opt/coderai/python/bin/python3 - "$CONFIG_FILE" "$CODERAI_HOST" "$CODERAI_PORT" <<'PY'
import json
import sys
from pathlib import Path

path = Path(sys.argv[1])
host = sys.argv[2]
port = int(sys.argv[3])
path.write_text(json.dumps({"server": {"host": host, "port": port}}, indent=2) + "\n")
PY
fi

# Optional debug logging. CODERAI_DEBUG selects coderai's --debug* flags:
#   all              -> every debug flag
#   1|true|yes|on    -> just --debug
#   "engine,ws,..."  -> --debug-engine --debug-ws ...  (bare names get --debug- prefixed;
#                       full "--debug-foo" tokens are passed through; comma OR space separated)
DEBUG_ARGS=""
case "${CODERAI_DEBUG:-}" in
  "") : ;;
  all|ALL|All)
    DEBUG_ARGS="--debug --debug-ws --debug-web --debug-thermal --debug-lora --debug-requests --debug-engine --debug-engine-web" ;;
  1|true|TRUE|yes|YES|on|ON)
    DEBUG_ARGS="--debug" ;;
  *)
    for _f in $(echo "$CODERAI_DEBUG" | tr ',' ' '); do
      case "$_f" in
        --*)  DEBUG_ARGS="$DEBUG_ARGS $_f" ;;
        debug) DEBUG_ARGS="$DEBUG_ARGS --debug" ;;
        *)    DEBUG_ARGS="$DEBUG_ARGS --debug-$_f" ;;
      esac
    done ;;
esac
# --debug-* flags need --debug present to take effect; add it if the user picked
# only sub-flags.
case " $DEBUG_ARGS " in *" --debug "*) : ;; *[!\ ]*) DEBUG_ARGS="--debug$DEBUG_ARGS" ;; esac

# Assemble the server argv: --config, --host/--port (override config.server in
# memory, never written to config.json), optional --tmp, debug flags, passthrough.
set -- --config "$CONFIG_DIR" --host "$CODERAI_HOST" --port "$CODERAI_PORT" "$@"
[ -n "${CODERAI_TMP:-}" ] && set -- "$@" --tmp "$CODERAI_TMP"

# Extra coderai CLI flags passed straight through from the host launcher
# (coderai-docker --coderai-arg / --coderai-args -> CODERAI_EXTRA_ARGS). supervisord
# runs this script with a fixed command, so arbitrary server flags arrive via this
# env var rather than argv. Word-split intentionally (like DEBUG_ARGS below).

CODERAI_BIN="/opt/coderai/python/bin/python3 /opt/coderai/app/coderai"

# Optional host-tailable file log. CODERAI_LOG_FILE should point under a mounted
# volume (e.g. /cache/logs/coderai.log) so it's visible + tailable on the host.
# We tee so output still reaches `docker logs` too. (supervisord runs this script
# with killasgroup, so the coderai front + its engine subprocesses + tee are all
# torn down together on stop.)
if [ -n "${CODERAI_LOG_FILE:-}" ]; then
  mkdir -p "$(dirname "$CODERAI_LOG_FILE")" 2>/dev/null || true
  # Only use the file log if we can actually write it. When the container runs as
  # --user but the log dir/file was created by an earlier ROOT run, it's root-owned
  # and not writable — previously `tee` then spammed "Permission denied" and the
  # file stayed empty. Detect that and fall back to plain stdout with a clear note,
  # so output is never lost and the terminal isn't polluted by tee errors.
  if ( : >> "$CODERAI_LOG_FILE" ) 2>/dev/null; then
    echo "[coderai-oci] debug='${CODERAI_DEBUG:-off}' → logging to $CODERAI_LOG_FILE" >&2
    # shellcheck disable=SC2086
    exec $CODERAI_BIN "$@" $DEBUG_ARGS ${CODERAI_EXTRA_ARGS:-} 2>&1 | tee -a "$CODERAI_LOG_FILE"
  else
    echo "[coderai-oci] WARNING: cannot write $CODERAI_LOG_FILE (not writable by uid $(id -u)) —" >&2
    echo "[coderai-oci]   logging to stdout only. Fix: remove the root-owned path on the host," >&2
    echo "[coderai-oci]   e.g. 'sudo rm -rf <cache>/logs', or run without --user." >&2
  fi
fi
# shellcheck disable=SC2086
exec $CODERAI_BIN "$@" $DEBUG_ARGS ${CODERAI_EXTRA_ARGS:-}
