#!/bin/sh

set -eu

WEBAPP_ROOT="/home/webapp"
ENV_ROOT="$WEBAPP_ROOT/env"
APP_ROOT="$WEBAPP_ROOT/loan-pricing"
JAVA_HOME="$ENV_ROOT/jdk"
BACKEND_DIR="$APP_ROOT/backend"
LOG_DIR="$APP_ROOT/logs"
RUN_DIR="$APP_ROOT/run"
BACKEND_PID_FILE="$RUN_DIR/backend.pid"
BACKEND_JAR="$BACKEND_DIR/ruoyi-admin.jar"
BACKEND_CONSOLE_LOG="$LOG_DIR/backend-console.log"
BACKEND_PORT=63310
BACKEND_MARKER="-Dloan.pricing.home=$APP_ROOT"
JAVA_OPTS="$BACKEND_MARKER -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError"

timestamp() {
    date "+%Y-%m-%d %H:%M:%S"
}

log_info() {
    printf '[%s] %s\n' "$(timestamp)" "$1"
}

log_error() {
    printf '[%s] %s\n' "$(timestamp)" "$1" >&2
}

usage() {
    cat <<'EOF'
用法: ./restart_java.sh [start|stop|restart|status]

默认动作:
  restart  重启后端 Java 进程
EOF
}

ensure_runtime_dirs() {
    mkdir -p "$BACKEND_DIR" "$LOG_DIR" "$RUN_DIR"
}

is_managed_backend_pid() {
    pid="$1"
    if [ -z "${pid:-}" ] || ! kill -0 "$pid" 2>/dev/null; then
        return 1
    fi

    args=$(ps -o args= -p "$pid" 2>/dev/null || true)
    if [ -z "${args:-}" ]; then
        return 1
    fi

    case "$args" in
        *"$BACKEND_MARKER"*"$BACKEND_JAR"*|*"$BACKEND_JAR"*"$BACKEND_MARKER"*)
            return 0
            ;;
    esac

    return 1
}

collect_backend_pids() {
    pids=""

    if [ -f "$BACKEND_PID_FILE" ]; then
        file_pid=$(cat "$BACKEND_PID_FILE" 2>/dev/null || true)
        if [ -n "${file_pid:-}" ] && is_managed_backend_pid "$file_pid"; then
            pids="$pids $file_pid"
        fi
    fi

    marker_pids=$(ps -ef | awk -v marker="$BACKEND_MARKER" -v jar="$BACKEND_JAR" '
        index($0, "<defunct>") == 0 && index($0, marker) > 0 {
            for (i = 1; i < NF; i++) {
                if ($i == "-jar" && $(i + 1) == jar) {
                    print $2
                    break
                }
            }
        }
    ' | xargs 2>/dev/null || true)
    if [ -n "${marker_pids:-}" ]; then
        for pid in $marker_pids; do
            if is_managed_backend_pid "$pid"; then
                pids="$pids $pid"
            fi
        done
    fi

    printf '%s\n' "$(echo "$pids" | xargs 2>/dev/null || true)"
}

stop_backend() {
    pids=$(collect_backend_pids)

    if [ -z "${pids:-}" ]; then
        rm -f "$BACKEND_PID_FILE"
        log_info "未发现运行中的后端进程"
        return 0
    fi

    log_info "停止后端进程: $pids"
    for pid in $pids; do
        kill -TERM "$pid" 2>/dev/null || true
    done

    elapsed=0
    while [ "$elapsed" -lt 30 ]; do
        remaining=""
        for pid in $pids; do
            if kill -0 "$pid" 2>/dev/null; then
                remaining="$remaining $pid"
            fi
        done

        remaining=$(echo "$remaining" | xargs 2>/dev/null || true)
        if [ -z "${remaining:-}" ]; then
            break
        fi

        sleep 1
        elapsed=$((elapsed + 1))
    done

    if [ -n "${remaining:-}" ]; then
        log_info "执行强制停止: $remaining"
        for pid in $remaining; do
            kill -KILL "$pid" 2>/dev/null || true
        done
    fi

    rm -f "$BACKEND_PID_FILE"
}

start_backend() {
    ensure_runtime_dirs

    if [ ! -x "$JAVA_HOME/bin/java" ]; then
        log_error "未检测到可执行 Java: $JAVA_HOME/bin/java"
        exit 1
    fi

    if [ ! -f "$BACKEND_JAR" ]; then
        log_error "未找到后端 jar: $BACKEND_JAR"
        exit 1
    fi

    if [ -n "$(collect_backend_pids)" ]; then
        log_error "检测到后端已在运行，请先执行 stop 或 restart"
        exit 1
    fi

    printf '\n===== %s restart =====\n' "$(timestamp)" >> "$BACKEND_CONSOLE_LOG"

    (
        cd "$BACKEND_DIR"
        nohup "$JAVA_HOME/bin/java" $JAVA_OPTS -jar "$BACKEND_JAR" --spring.profiles.active=pro --server.port="$BACKEND_PORT" >> "$BACKEND_CONSOLE_LOG" 2>&1 &
        echo $! > "$BACKEND_PID_FILE"
    )

    sleep 3

    backend_pid=$(cat "$BACKEND_PID_FILE" 2>/dev/null || true)
    if [ -z "${backend_pid:-}" ] || ! kill -0 "$backend_pid" 2>/dev/null; then
        log_error "后端启动失败，请检查日志: $BACKEND_CONSOLE_LOG"
        exit 1
    fi

    log_info "后端已启动，PID: $backend_pid"
}

status_backend() {
    pids=$(collect_backend_pids)
    if [ -n "${pids:-}" ]; then
        log_info "后端正在运行，进程: $pids"
        return 0
    fi

    log_info "后端未运行"
}

main() {
    action="${1:-restart}"

    case "$action" in
        start)
            start_backend
            ;;
        stop)
            stop_backend
            ;;
        restart)
            stop_backend
            start_backend
            ;;
        status)
            status_backend
            ;;
        *)
            usage
            exit 1
            ;;
    esac
}

main "$@"
