#!/bin/bash
#
# Octop 本地版（原生 app）— 生命周期管理
# 直接以进程方式运行在飞牛主机上（非 Docker），监听 0.0.0.0:8089。
# start:  启动 Octop（后台，写 PID 文件）
# stop:   发送 SIGTERM，超时 SIGKILL
# status: 查询进程状态
#

set -uo pipefail

APPDEST="${TRIM_APPDEST:-/var/apps/octop-native}"
PKGVAR="${TRIM_PKGVAR:-/var/apps/octop-native/var}"
LOG_FILE="${PKGVAR}/info.log"
PID_FILE="${PKGVAR}/octop.pid"
PORT="${OCTOP_PORT:-8089}"
BIN="$APPDEST/bin/octop"

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

start_process() {
    if status; then return 0; fi
    mkdir -p "${PKGVAR}"
    log_msg "Starting Octop (native) on port ${PORT} ..."

    # 以最低权限用户 octop-native 运行 Octop 服务（安全：web 服务与工作台终端
    # 不以 root 身份暴露）。若该用户不存在（个别 FnOS 版本在 run-as=root 时不
    # 创建包用户），则回退以当前身份（root）运行，保证服务一定起得来。
    # 注意：本包 run-as=root 是为了让 install_callback 能以 root 写入
    # /etc/sudoers.d/octop-native（授予 octop-native 免密 sudo），从而使远程桌面
    # /浏览器安装这类需要 root 的操作可用；服务本身仍尽量降权运行。
    local -a RUN_AS=()
    if id octop-native >/dev/null 2>&1 && command -v runuser >/dev/null 2>&1; then
        RUN_AS=(runuser -u octop-native --)
        log_msg "将以 octop-native 低权限用户运行 Octop 服务"
    else
        log_msg "octop-native 用户不可用，回退以当前身份运行 Octop 服务"
    fi

    # 启动 Octop 监听所有接口（供飞牛直接通过端口访问）
    OCTOP_PORT="$PORT" OCTOP_BIND_HOST=0.0.0.0 ${RUN_AS[@]+"${RUN_AS[@]}"} "$BIN" --host 0.0.0.0 --port "$PORT" >> "${LOG_FILE}" 2>&1 &
    octop_pid=$!

    # 等待 Octop TCP 端口就绪（最多 30 秒）
    for i in $(seq 1 30); do
        if nc -z 127.0.0.1 "$PORT" 2>/dev/null || (exec 3<>/dev/tcp/127.0.0.1/"$PORT") 2>/dev/null; then
            break
        fi
        if ! kill -0 "$octop_pid" 2>/dev/null; then
            log_msg "Octop process exited early"
            return 1
        fi
        sleep 1
    done

    printf "%s" "$octop_pid" > "${PID_FILE}"
    log_msg "Octop pid=$octop_pid"
    return 0
}

stop_process() {
    log_msg "Stopping Octop (native) ..."

    if [ -r "${PID_FILE}" ]; then
        pid=$(head -n 1 "${PID_FILE}" | tr -d '[:space:]')
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
            # 杀整个进程组（包括可能的子进程）
            kill -TERM "-$pid" 2>/dev/null || kill -TERM "$pid" 2>/dev/null || true
            for i in $(seq 1 10); do
                sleep 1
                if ! kill -0 "$pid" 2>/dev/null; then
                    break
                fi
            done
            if kill -0 "$pid" 2>/dev/null; then
                kill -KILL "-$pid" 2>/dev/null || kill -KILL "$pid" 2>/dev/null || true
            fi
        fi
        rm -f "${PID_FILE}"
    fi

    return 0
}

status() {
    [ -f "${PID_FILE}" ] && pid=$(head -n 1 "${PID_FILE}" | tr -d '[:space:]') && [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
}

case $1 in
    start)  start_process ;;
    stop)   stop_process ;;
    status) status && exit 0 || exit 3 ;;
    *)      exit 1 ;;
esac
