#!/bin/bash

set -u

APP_DEST="${TRIM_APPDEST:?缺少 TRIM_APPDEST}"
APP_VAR="${TRIM_PKGVAR:?缺少 TRIM_PKGVAR}"
APP_ETC="${TRIM_PKGETC:?缺少 TRIM_PKGETC}"
APP_HOME="${TRIM_PKGHOME:-${APP_VAR}/home}"
BIN="${APP_DEST}/zfile/zfile-pro"
PID_FILE="${APP_VAR}/zfile.pid"
CONFIG_FILE="${APP_ETC}/application.properties"
CONSOLE_LOG="${APP_VAR}/logs/console.log"
SERVER_PORT="8899"

write_message() {
    if [[ -n "${TRIM_TEMP_LOGFILE:-}" ]]; then
        printf '%s\n' "$1" > "$TRIM_TEMP_LOGFILE"
    fi
}

read_pid() {
    [[ -r "$PID_FILE" ]] || return 1
    sed -n '1{s/[[:space:]]//g;p;}' "$PID_FILE"
}

process_running() {
    local pid="$1"
    [[ "$pid" =~ ^[0-9]+$ ]] || return 1
    kill -0 "$pid" 2>/dev/null || return 1
    [[ -r "/proc/${pid}/cmdline" ]] || return 1
    tr '\000' ' ' < "/proc/${pid}/cmdline" | grep -F "$BIN" >/dev/null 2>&1
}

status_process() {
    local pid
    pid="$(read_pid 2>/dev/null || true)"
    if process_running "$pid"; then
        return 0
    fi
    rm -f "$PID_FILE"
    return 1
}

readiness_probe_available() {
    command -v curl >/dev/null 2>&1 || command -v wget >/dev/null 2>&1 || command -v nc >/dev/null 2>&1
}

service_ready() {
    if command -v curl >/dev/null 2>&1; then
        curl --connect-timeout 1 --max-time 2 --silent --output /dev/null "http://127.0.0.1:${SERVER_PORT}/"
    elif command -v wget >/dev/null 2>&1; then
        wget -T 2 -t 1 -q -O /dev/null "http://127.0.0.1:${SERVER_PORT}/"
    else
        nc -z -w 2 127.0.0.1 "$SERVER_PORT" >/dev/null 2>&1
    fi
}

start_process() {
    local pid
    if status_process; then
        return 0
    fi
    if [[ ! -x "$BIN" ]]; then
        write_message "ZFile Pro 可执行文件不存在或不可执行。"
        return 1
    fi
    if [[ ! -f "$CONFIG_FILE" ]]; then
        write_message "ZFile Pro 配置文件不存在，请重新安装应用。"
        return 1
    fi

    mkdir -p "$APP_VAR/db" "$APP_VAR/logs" "$APP_HOME"
    umask 077
    if [[ -n "${LD_LIBRARY_PATH:-}" ]]; then
        export LD_LIBRARY_PATH="${APP_DEST}/zfile:${LD_LIBRARY_PATH}"
    else
        export LD_LIBRARY_PATH="${APP_DEST}/zfile"
    fi
    export HOME="$APP_HOME"

    nohup "$BIN" \
        --spring.config.additional-location="optional:file:${CONFIG_FILE}" \
        --spring.web.resources.static-locations="file:${APP_DEST}/static/" \
        >> "$CONSOLE_LOG" 2>&1 &
    pid=$!
    printf '%s\n' "$pid" > "$PID_FILE"

    count=0
    while (( count < 30 )); do
        sleep 1
        if ! process_running "$pid"; then
            rm -f "$PID_FILE"
            write_message "ZFile Pro 启动失败，请查看 ${CONSOLE_LOG}。"
            return 1
        fi
        if readiness_probe_available && service_ready; then
            return 0
        fi
        count=$((count + 1))
    done

    if ! readiness_probe_available && process_running "$pid"; then
        return 0
    fi

    stop_process
    write_message "ZFile Pro 启动超时，端口 ${SERVER_PORT} 未就绪，请查看 ${CONSOLE_LOG}。"
    return 1
}

stop_process() {
    local pid count
    pid="$(read_pid 2>/dev/null || true)"
    if ! process_running "$pid"; then
        rm -f "$PID_FILE"
        return 0
    fi

    kill -TERM "$pid" 2>/dev/null || true
    count=0
    while process_running "$pid" && (( count < 30 )); do
        sleep 1
        count=$((count + 1))
    done
    if process_running "$pid"; then
        kill -KILL "$pid" 2>/dev/null || true
        sleep 1
    fi
    if process_running "$pid"; then
        write_message "ZFile Pro 进程无法停止，PID: ${pid}。"
        return 1
    fi
    rm -f "$PID_FILE"
    return 0
}

case "${1:-}" in
    start)
        start_process
        ;;
    stop)
        stop_process
        ;;
    status)
        if status_process; then
            exit 0
        fi
        exit 3
        ;;
    *)
        exit 1
        ;;
esac
