#!/bin/sh

set -eu

ROOT_DIR=$(CDPATH= cd -- "$(dirname "$0")/../.." && pwd)
SCRIPT_UNDER_TEST="$ROOT_DIR/bin/prod/restart_java.sh"

fail() {
    printf 'FAIL: %s\n' "$1" >&2
    exit 1
}

assert_grep() {
    pattern="$1"
    target="$2"
    if ! grep -Eq -- "$pattern" "$target"; then
        fail "expected pattern [$pattern] in $target"
    fi
}

assert_not_grep() {
    pattern="$1"
    target="$2"
    if grep -Eq -- "$pattern" "$target"; then
        fail "did not expect pattern [$pattern] in $target"
    fi
}

create_fake_java() {
    fake_java="$1"

    cat > "$fake_java" <<'EOF'
#!/bin/sh
set -eu

while :; do
    sleep 1
done
EOF

    chmod +x "$fake_java"
}

prepare_script_env() {
    work_dir="$1"

    mkdir -p "$work_dir/env/jdk/bin" "$work_dir/loan-pricing/backend" "$work_dir/loan-pricing/logs" "$work_dir/loan-pricing/run"
    create_fake_java "$work_dir/env/jdk/bin/java"
    printf 'fake-jar\n' > "$work_dir/loan-pricing/backend/ruoyi-admin.jar"
    cp "$SCRIPT_UNDER_TEST" "$work_dir/restart_java.sh"
    perl -0pi -e "s#WEBAPP_ROOT=\"/home/webapp\"#WEBAPP_ROOT=\"$work_dir\"#" "$work_dir/restart_java.sh"
    chmod +x "$work_dir/restart_java.sh"
}

cleanup_work_dir() {
    work_dir="$1"

    if [ -f "$work_dir/loan-pricing/run/backend.pid" ]; then
        backend_pid=$(cat "$work_dir/loan-pricing/run/backend.pid" 2>/dev/null || true)
        if [ -n "${backend_pid:-}" ]; then
            kill "$backend_pid" 2>/dev/null || true
            wait "$backend_pid" 2>/dev/null || true
        fi
    fi

    rm -rf "$work_dir"
}

test_script_contract() {
    assert_grep 'JAVA_HOME="\$ENV_ROOT/jdk"' "$SCRIPT_UNDER_TEST"
    assert_grep '--spring\.profiles\.active=pro' "$SCRIPT_UNDER_TEST"
    assert_grep 'ps -ef' "$SCRIPT_UNDER_TEST"
    assert_not_grep 'pgrep' "$SCRIPT_UNDER_TEST"
    assert_not_grep 'mvn' "$SCRIPT_UNDER_TEST"
    assert_not_grep 'require_root' "$SCRIPT_UNDER_TEST"
    assert_not_grep '\b(ss|lsof|netstat)\b' "$SCRIPT_UNDER_TEST"
}

test_restart_flow() {
    work_dir=$(mktemp -d)
    trap 'cleanup_work_dir "$work_dir"' EXIT INT TERM

    prepare_script_env "$work_dir"

    "$work_dir/restart_java.sh" start
    if [ ! -f "$work_dir/loan-pricing/run/backend.pid" ]; then
        fail "expected backend pid file after start"
    fi

    backend_pid=$(cat "$work_dir/loan-pricing/run/backend.pid")
    kill -0 "$backend_pid" 2>/dev/null || fail "expected backend process to be running after start"

    status_output=$("$work_dir/restart_java.sh" status 2>&1 || true)
    printf '%s\n' "$status_output" | grep -q '后端正在运行' || fail "expected status output to show running"

    "$work_dir/restart_java.sh" restart
    restarted_pid=$(cat "$work_dir/loan-pricing/run/backend.pid")
    kill -0 "$restarted_pid" 2>/dev/null || fail "expected backend process to be running after restart"

    "$work_dir/restart_java.sh" stop
    if [ -f "$work_dir/loan-pricing/run/backend.pid" ]; then
        fail "expected backend pid file to be removed after stop"
    fi

    trap - EXIT INT TERM
    cleanup_work_dir "$work_dir"
}

main() {
    [ -f "$SCRIPT_UNDER_TEST" ] || fail "script under test not found: $SCRIPT_UNDER_TEST"
    test_script_contract
    test_restart_flow
    printf 'PASS: restart_java tests\n'
}

main "$@"
