#!/bin/bash
set -eu

PACKAGE_ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
APP_ROOT="${TRIM_APPDEST:-$PACKAGE_ROOT/app}"
DATA_ROOT="${TRIM_PKGVAR:-$PACKAGE_ROOT/var}"
RUN_ROOT="$DATA_ROOT/run"
LOG_ROOT="$DATA_ROOT/log"
PID_FILE="$RUN_ROOT/imagefind.pid"
LOG_FILE="$LOG_ROOT/imagefind.log"
ACCESS_CONFIG="$DATA_ROOT/access.json"
GATEWAY_SOCKET="$APP_ROOT/imagefind.sock"

mkdir -p "$RUN_ROOT" "$LOG_ROOT" "$DATA_ROOT/data" "$DATA_ROOT/tmp"

is_running() {
    [ -f "$PID_FILE" ] || return 1
    PID=$(sed -n '1p' "$PID_FILE")
    [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null
}

report_start_failure() {
    MESSAGE="ImageFind failed to start. Runtime log: $LOG_FILE"
    printf '%s\n' "$MESSAGE" >&2
    if [ -n "${TRIM_TEMP_LOGFILE:-}" ]; then
        {
            printf '%s\n' "$MESSAGE"
            printf '%s\n' '--- imagefind.log (last 100 lines) ---'
            tail -n 100 "$LOG_FILE" 2>/dev/null || true
        } >>"$TRIM_TEMP_LOGFILE" 2>&1 || true
    fi
}

start_app() {
    if is_running; then
        return 0
    fi
    rm -f "$PID_FILE"
    if ! TRIM_APPDEST="$APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" "$PACKAGE_ROOT/cmd/runtime_bootstrap" \
        >>"$LOG_FILE" 2>&1; then
        report_start_failure
        return 1
    fi
    SERVER="$DATA_ROOT/runtime/current/bin/python"
    export IMAGEFIND_DATA_DIR="$DATA_ROOT/data"
    export IMAGEFIND_FRONTEND_DIR="$APP_ROOT/frontend"
    export IMAGEFIND_BUNDLED_AI_RUNTIME=false
    export IMAGEFIND_RUNTIME_REQUIREMENTS_DIR="$APP_ROOT/runtime/ai"
    export IMAGEFIND_BUNDLED_TOOLS_DIR="$APP_ROOT/bin"
    export IMAGEFIND_POSTGRES_CONF="$DATA_ROOT/postgres-client.conf"
    export IMAGEFIND_POSTGRES_ENROLLMENT_TOKEN_SEED="$DATA_ROOT/postgres-enrollment-token.seed"
    export PYTHONPATH="$DATA_ROOT/runtime/ai-current${PYTHONPATH:+:$PYTHONPATH}"
    export XDG_CACHE_HOME="$DATA_ROOT/cache"
    # Model conversion can temporarily exceed the small system /tmp volume.
    # Keep all large, recoverable conversion files on the application data volume.
    export TMPDIR="$DATA_ROOT/tmp"
    DIRECT_ENABLED=true
    DIRECT_PORT=8765
    if [ -f "$ACCESS_CONFIG" ]; then
        CONFIG_ENABLED=$(sed -n 's/.*"enabled"[[:space:]]*:[[:space:]]*\(true\|false\).*/\1/p' "$ACCESS_CONFIG" | head -n 1)
        CONFIG_PORT=$(sed -n 's/.*"port"[[:space:]]*:[[:space:]]*\([0-9][0-9]*\).*/\1/p' "$ACCESS_CONFIG" | head -n 1)
        [ -z "$CONFIG_ENABLED" ] || DIRECT_ENABLED="$CONFIG_ENABLED"
        [ -z "$CONFIG_PORT" ] || DIRECT_PORT="$CONFIG_PORT"
    fi
    export IMAGEFIND_HOST="0.0.0.0"
    export IMAGEFIND_PORT="$DIRECT_PORT"
    export IMAGEFIND_DIRECT_ACCESS="$DIRECT_ENABLED"
    export IMAGEFIND_GATEWAY_PREFIX="/app/imagefind"
    export IMAGEFIND_GATEWAY_SOCKET="$GATEWAY_SOCKET"
    # Keep CPU fallback responsive on a NAS. Administrators can override any
    # value before launch, while the default avoids saturating every core.
    export IMAGEFIND_AI_CPU_THREADS="${IMAGEFIND_AI_CPU_THREADS:-1}"
    export OMP_NUM_THREADS="${OMP_NUM_THREADS:-$IMAGEFIND_AI_CPU_THREADS}"
    export OPENBLAS_NUM_THREADS="${OPENBLAS_NUM_THREADS:-$IMAGEFIND_AI_CPU_THREADS}"
    export MKL_NUM_THREADS="${MKL_NUM_THREADS:-$IMAGEFIND_AI_CPU_THREADS}"
    export LD_LIBRARY_PATH="$APP_ROOT/bin${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
    if [ ! -f "$IMAGEFIND_POSTGRES_CONF" ] && [ -f "$IMAGEFIND_POSTGRES_ENROLLMENT_TOKEN_SEED" ]; then
        if ! "$SERVER" -m imagefind.main postgres-enroll >>"$LOG_FILE" 2>&1; then
            report_start_failure
            return 1
        fi
    fi
    nohup "$SERVER" -m imagefind.main >>"$LOG_FILE" 2>&1 &
    printf '%s\n' "$!" > "$PID_FILE"
    sleep 1
    if ! is_running; then
        report_start_failure
        return 1
    fi
}

stop_pid() {
    FILE="$1"
    [ -f "$FILE" ] || return 0
    PID=$(sed -n '1p' "$FILE")
    if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
        kill "$PID" 2>/dev/null || true
        COUNT=0
        while kill -0 "$PID" 2>/dev/null && [ "$COUNT" -lt 20 ]; do
            sleep 1
            COUNT=$((COUNT + 1))
        done
        kill -9 "$PID" 2>/dev/null || true
    fi
    rm -f "$FILE"
}

case "${1:-status}" in
    start) start_app ;;
    stop) stop_pid "$PID_FILE"; rm -f "$GATEWAY_SOCKET" ;;
    restart) "$0" stop; "$0" start ;;
    status)
        if is_running; then
            exit 0
        fi
        # fnOS reserves 3 for a valid status check whose service is stopped.
        exit 3
        ;;
    *) printf 'usage: %s {start|stop|restart|status}\n' "$0" >&2; exit 2 ;;
esac
