
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077

BIN="/usr/local/bin/xray"

die() {
    echo "ERROR: $*" >&2
    exit 1
}

# 1. 检查 root 权限和 Xray 服务
[[ $EUID -eq 0 ]] || die "必须以 root 运行"

if ! systemctl list-unit-files \
    --type=service --no-legend --no-pager 'xray*.service' |
    awk '$1 ~ /^xray.*\.service$/ { found=1 }
         END { exit !found }'; then
    die "未找到任何 xray 开头的 systemd 服务"
fi

[[ -f "$BIN" && -x "$BIN" && ! -L "$BIN" ]] ||
    die "Xray 二进制不存在、不可执行或是符号链接：$BIN"

# 2. 检查 CPU 架构
case "$(uname -m)" in
    i386|i486|i586|i686)
        URL="https://fdcx.org/corelinux32.zip"
        ;;
    x86_64|amd64)
        URL="https://fdcx.org/corelinux64.zip"
        ;;
    aarch64|arm64)
        URL="https://fdcx.org/corev8a.zip"
        ;;
    *)
        die "不支持的 CPU 架构：$(uname -m)"
        ;;
esac

for cmd in curl unzip; do
    command -v "$cmd" >/dev/null 2>&1 ||
        die "缺少依赖：$cmd"
done

# 3. 记录当前正在运行的 Xray 服务
mapfile -t ACTIVE_UNITS < <(
    systemctl list-units \
        --type=service \
        --state=active \
        --plain --no-legend --no-pager \
        'xray*.service' |
    awk '$1 ~ /^xray.*\.service$/ { print $1 }'
)

echo "当前运行中的 Xray 服务："
if ((${#ACTIVE_UNITS[@]})); then
    printf '  %s\n' "${ACTIVE_UNITS[@]}"
else
    echo "  无"
fi

# 4. 临时目录和失败回滚
WORKDIR=$(mktemp -d)
STAGE=""
STOPPED=0
REPLACED=0

cleanup() {
    local rc=$?
    trap - EXIT

    if ((rc != 0 && STOPPED == 1)); then
        echo "升级失败，尝试恢复原版本..." >&2

        if ((REPLACED == 1)); then
            if ((${#ACTIVE_UNITS[@]})); then
                systemctl stop "${ACTIVE_UNITS[@]}" || true
            fi

            local rollback
            if rollback=$(mktemp /usr/local/bin/.xray-rollback.XXXXXX); then
                if install -m 0755 -o root -g root \
                    "$WORKDIR/xray.old" "$rollback"; then
                    mv -f "$rollback" "$BIN" ||
                        echo "ERROR: 回滚二进制失败！" >&2
                fi
                rm -f "$rollback"
            fi
        fi

        if ((${#ACTIVE_UNITS[@]})); then
            systemctl start "${ACTIVE_UNITS[@]}" ||
                echo "ERROR: 部分服务恢复失败，请手动检查！" >&2
        fi
    fi

    [[ -z "$STAGE" ]] || rm -f "$STAGE"
    rm -rf "$WORKDIR"
    exit "$rc"
}

trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM

# 5. 下载并验证安装包
echo "下载：$URL"
curl -fL --retry 3 --connect-timeout 15 \
    -o "$WORKDIR/core.zip" "$URL"

unzip -tqq "$WORKDIR/core.zip" ||
    die "ZIP 文件完整性检查失败"

# 查找 ZIP 内的 xray 可执行文件
mapfile -t ENTRIES < <(
    unzip -Z -1 "$WORKDIR/core.zip" |
    grep -E '(^|/)xray$' || true
)

((${#ENTRIES[@]} == 1)) ||
    die "ZIP 内未找到唯一的 xray 可执行文件"

unzip -p "$WORKDIR/core.zip" "${ENTRIES[0]}" \
    > "$WORKDIR/xray"

[[ -s "$WORKDIR/xray" ]] ||
    die "解压后的 Xray 文件为空"

chmod 0755 "$WORKDIR/xray"

echo "检查新版本："
"$WORKDIR/xray" version

# 备份原版本
cp -p "$BIN" "$WORKDIR/xray.old"

# 预先准备同文件系统的替换文件
STAGE=$(mktemp /usr/local/bin/.xray-update.XXXXXX)
install -m 0755 -o root -g root \
    "$WORKDIR/xray" "$STAGE"

# 6. 停止所有原本运行中的 Xray 服务
STOPPED=1

if ((${#ACTIVE_UNITS[@]})); then
    echo "停止 Xray 服务..."
    systemctl stop "${ACTIVE_UNITS[@]}"
fi

# 7. 原子替换二进制
echo "替换 Xray 二进制..."
mv -f "$STAGE" "$BIN"
STAGE=""
REPLACED=1

# 8. 恢复之前运行的服务
if ((${#ACTIVE_UNITS[@]})); then
    echo "启动 Xray 服务..."
    systemctl start "${ACTIVE_UNITS[@]}"

    sleep 1

    for unit in "${ACTIVE_UNITS[@]}"; do
        systemctl is-active --quiet "$unit" ||
            die "$unit 启动后未保持 active 状态"
    done
fi

STOPPED=0

echo
echo "Xray 升级成功！"
"$BIN" version
echo "所有原先运行的 Xray 服务已恢复。"
