#!/bin/sh

# =========================================================
# lq10_daemon
# 用途：
#   管理 watchdog 脚本与主程序 lq10_link
# 设计原则：
#   1. shell 脚本进程不使用 pidof/killall 脚本名判断
#   2. watchdog 按命令行匹配 PID
#   3. 主程序按进程名处理
#   4. stop 先停 watchdog，再停 app，避免被重新拉起
# =========================================================

WATCHDOG_BIN="/app/current/bin/lq10_watchdog.sh"
APP_BIN="/app/current/bin/lq10_link"
APP_NAME="lq10_link"

LOG_TAG="[lq10_daemon]"

log_info() {
    echo "$LOG_TAG $*"
}

log_warn() {
    echo "$LOG_TAG WARN: $*"
}

log_error() {
    echo "$LOG_TAG ERROR: $*" >&2
}

# ---------------------------------------------------------
# 获取 watchdog 脚本 PID
# 注意：
#   lq10_watchdog.sh 实际可能以：
#       /bin/sh /app/current/bin/lq10_watchdog.sh
#   的形式运行，因此不能用 pidof lq10_watchdog.sh
# ---------------------------------------------------------
get_watchdog_pids() {
    ps | grep "$WATCHDOG_BIN" | grep -v grep | awk '{print $1}'
}

# ---------------------------------------------------------
# 判断 watchdog 是否正在运行
# ---------------------------------------------------------
is_watchdog_running() {
    [ -n "$(get_watchdog_pids)" ]
}

# ---------------------------------------------------------
# 判断 app 是否正在运行
# ---------------------------------------------------------
is_app_running() {
    pidof "$APP_NAME" >/dev/null 2>&1
}

# ---------------------------------------------------------
# 停止 watchdog
# 参数：
#   $1 = 信号，默认 TERM
# ---------------------------------------------------------
stop_watchdog_once() {
    sig="${1:-TERM}"
    pids="$(get_watchdog_pids)"
    [ -z "$pids" ] && return 0

    for pid in $pids; do
        kill "-$sig" "$pid" 2>/dev/null
    done
    return 0
}

# ---------------------------------------------------------
# 停止 app
# 参数：
#   $1 = 信号，默认 TERM
# ---------------------------------------------------------
stop_app_once() {
    sig="${1:-TERM}"
    if is_app_running; then
        killall "-$sig" "$APP_NAME" 2>/dev/null
    fi
    return 0
}

# ---------------------------------------------------------
# 等待 watchdog 退出
# ---------------------------------------------------------
wait_watchdog_exit() {
    timeout="${1:-3}"
    while [ "$timeout" -gt 0 ]; do
        if ! is_watchdog_running; then
            return 0
        fi
        sleep 1
        timeout=$((timeout - 1))
    done
    return 1
}

# ---------------------------------------------------------
# 等待 app 退出
# ---------------------------------------------------------
wait_app_exit() {
    timeout="${1:-3}"
    while [ "$timeout" -gt 0 ]; do
        if ! is_app_running; then
            return 0
        fi
        sleep 1
        timeout=$((timeout - 1))
    done
    return 1
}

# ---------------------------------------------------------
# 启动
# ---------------------------------------------------------
start() {
    if [ ! -f "$WATCHDOG_BIN" ]; then
        log_error "watchdog not found: $WATCHDOG_BIN"
        return 1
    fi

    if is_watchdog_running; then
        log_info "already running."
        return 0
    fi

    chmod +x "$WATCHDOG_BIN" 2>/dev/null

    log_info "starting watchdog..."
    "$WATCHDOG_BIN" >/dev/null 2>&1 &
    sleep 1

    if is_watchdog_running; then
        log_info "started."
        return 0
    fi

    log_error "failed to start watchdog."
    return 1
}

# ---------------------------------------------------------
# 停止
# 顺序：
#   1. 先停 watchdog，防止 app 被重新拉起
#   2. 再停 lq10_link
#   3. 若未退出，再升级为 KILL
# ---------------------------------------------------------
stop() {
    log_info "stopping watchdog and application..."

    # 1) 先停 watchdog
    if is_watchdog_running; then
        log_info "stopping watchdog..."
        stop_watchdog_once TERM
        if ! wait_watchdog_exit 3; then
            log_warn "watchdog still running, force kill."
            stop_watchdog_once KILL
            if ! wait_watchdog_exit 2; then
                log_error "failed to stop watchdog."
                return 1
            fi
        fi
    fi

    # 2) 再停 app
    if is_app_running; then
        log_info "stopping app..."
        stop_app_once TERM
        if ! wait_app_exit 3; then
            log_warn "app still running, force kill."
            stop_app_once KILL
            if ! wait_app_exit 2; then
                log_error "failed to stop app."
                return 1
            fi
        fi
    fi

    # 3) 再次确认，避免 watchdog 退出前拉起残留
    if is_watchdog_running; then
        log_warn "watchdog appeared again, force kill once more."
        stop_watchdog_once KILL
        wait_watchdog_exit 2 || {
            log_error "watchdog still running after retry."
            return 1
        }
    fi

    if is_app_running; then
        log_warn "app appeared again, force kill once more."
        stop_app_once KILL
        wait_app_exit 2 || {
            log_error "app still running after retry."
            return 1
        }
    fi

    log_info "stopped."
    return 0
}

# ---------------------------------------------------------
# 重启
# ---------------------------------------------------------
restart() {
    stop || return 1
    sleep 1
    start
}

# ---------------------------------------------------------
# 状态查询
# ---------------------------------------------------------
status() {
    wd_state="stopped"
    app_state="stopped"

    if is_watchdog_running; then
        wd_state="running"
    fi

    if is_app_running; then
        app_state="running"
    fi

    echo "watchdog: $wd_state"
    echo "app:      $app_state"

    if is_watchdog_running; then
        echo "watchdog pid(s): $(get_watchdog_pids | tr '\n' ' ')"
    fi

    if is_app_running; then
        echo "app pid(s): $(pidof "$APP_NAME")"
    fi
}

# ---------------------------------------------------------
# 参数处理
# ---------------------------------------------------------
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    status)
        status
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

exit $?
