#!/bin/bash
### CleanFnOS lifecycle script
### - strict error handling
### - use lsof + pkill (not fuser — psmisc may be missing)
### - exec node so PID in PID_FILE is the actual node process
set -euo pipefail

LOG_FILE="${TRIM_PKGVAR}/info.log"
PID_FILE="${TRIM_PKGVAR}/app.pid"

# 读取持久化的向导端口（install_callback 写入 $TRIM_PKGETC/config.conf），环境变量优先
PORT=""
[ -r "${TRIM_PKGETC}/config.conf" ] && . "${TRIM_PKGETC}/config.conf"
PORT="${wizard_app_port:-${PORT:-47939}}"

# 依赖 nodejs_v24 提供的 node
export PATH=/var/apps/nodejs_v24/target/bin:$PATH
CMD="node ${TRIM_APPDEST}/ui/server.js"

log_msg() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${LOG_FILE}"
}

# Clean up any zombie holding the port
cleanup_port() {
    if command -v lsof >/dev/null 2>&1; then
        local pids
        pids=$(lsof -ti :"${PORT}" 2>/dev/null || true)
        if [ -n "${pids}" ]; then
            log_msg "Killing port ${PORT} holders: ${pids}"
            # shellcheck disable=SC2086
            kill -TERM ${pids} 2>/dev/null || true
            sleep 0.5
            pids=$(lsof -ti :"${PORT}" 2>/dev/null || true)
            [ -n "${pids}" ] && kill -KILL ${pids} 2>/dev/null || true
        fi
    else
        pkill -TERM -f "node.*ui/server\\.js" 2>/dev/null || true
        sleep 0.5
        pkill -KILL -f "node.*ui/server\\.js" 2>/dev/null || true
    fi
}

check_process() {
    local pid=$1
    if kill -0 "${pid}" 2>/dev/null; then
        return 0
    else
        return 1
    fi
}

status() {
    if [ -f "${PID_FILE}" ]; then
        local pid
        pid=$(head -n 1 "${PID_FILE}" | tr -d '[:space:]')
        if check_process "${pid}"; then
            return 0
        else
            rm -f "${PID_FILE}"
        fi
    fi
    return 1
}

start_process() {
    if status; then
        return 0
    fi
    log_msg "Starting process on port ${PORT} ..."
    cleanup_port
    sleep 0.3
    # exec node so the PID recorded is the actual node process
    # 统一网关（fnOS 1.2.0401+）：注入 unix socket 路径与前缀，登录飞牛后免密访问
    GATEWAY_SOCKET="${TRIM_APPDEST}/cleanfnos.sock"
    rm -f "${GATEWAY_SOCKET}" 2>/dev/null || true
    PORT="${PORT}" GATEWAY_SOCKET="${GATEWAY_SOCKET}" GATEWAY_PREFIX="/app/cleanfnos" bash -c "exec ${CMD}" >> "${LOG_FILE}" 2>&1 &
    local pid=$!
    printf "%s" "${pid}" > "${PID_FILE}"
    log_msg "pid=${pid}"
    sleep 1
    if ! check_process "${pid}"; then
        echo "Failed to start CleanFnOS server, see ${LOG_FILE}" > "${TRIM_TEMP_LOGFILE}"
        return 1
    fi
    return 0
}

stop_process() {
    log_msg "Stopping process ..."

    if [ -r "${PID_FILE}" ]; then
        local pid
        pid=$(head -n 1 "${PID_FILE}" | tr -d '[:space:]')

        log_msg "pid=${pid}"
        if ! check_process "${pid}"; then
            rm -f "${PID_FILE}"
            log_msg "remove pid file (process not exist)"
            return
        fi

        log_msg "send TERM signal to PID:${pid}..."
        kill -TERM "${pid}" >> "${LOG_FILE}" 2>&1

        local count=0
        while check_process "${pid}" && [ $count -lt 10 ]; do
            sleep 1
            count=$((count + 1))
            log_msg "waiting process terminal... (${count}s/10s)"
        done

        if check_process "${pid}"; then
            log_msg "send KILL signal to PID:${pid}..."
            kill -KILL "${pid}"
            sleep 1
        fi
        rm -f "${PID_FILE}"
    fi

    return 0
}

case "$1" in
start)
    # run start command. exit 0 if success, exit 1 if failed
    start_process
    ;;
stop)
    # run stop command. exit 0 if success, exit 1 if failed
    stop_process
    ;;
status)
    # check application status command. exit 0 if running, exit 3 if not running
    if status; then
        exit 0
    else
        exit 3
    fi
    ;;
*)
    echo "Unknown command: $1" > "${TRIM_TEMP_LOGFILE:-/dev/null}" 2>/dev/null || true
    exit 1
    ;;
esac
