#!/usr/bin/env bash

set -euo pipefail

TESTS_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "${TESTS_DIR}/.." && pwd)"
APT_DEPENDENCY_PACKAGES="${APT_DEPENDENCY_PACKAGES:-python3 cargo rustc llvm-17 llvm-17-tools curl wget ca-certificates}"
LOCAL_CARGO_HOME="${CARGO_HOME:-${REPO_ROOT}/.cargo-test-home}"
LOCAL_RUSTUP_HOME="${RUSTUP_HOME:-${REPO_ROOT}/.rustup-test-home}"
LOCAL_LLVM_BIN="${REPO_ROOT}/.llvm-bin"

export CARGO_HOME="${LOCAL_CARGO_HOME}"
export RUSTUP_HOME="${LOCAL_RUSTUP_HOME}"
export PATH="/usr/bin:${CARGO_HOME}/bin:${LOCAL_LLVM_BIN}:${HOME}/.cargo/bin:/usr/lib/llvm-17/bin:${PATH}"
export UNIT_TEST_TIMEOUT_SECONDS="${UNIT_TEST_TIMEOUT_SECONDS:-1200}"
export RUST_TEST_THREADS="${RUST_TEST_THREADS:-1}"
export MIN_AVG_COVERAGE="${MIN_AVG_COVERAGE:-70}"
export SONAR_XML="${SONAR_XML:-${REPO_ROOT}/kylin-patch-coverage.xml}"
export CARGO_LLVM_COV_VERSION="${CARGO_LLVM_COV_VERSION:-}"

run_apt_get() {
    if [ "$(id -u)" -ne 0 ]; then
        echo "错误: 当前脚本直接使用 apt-get，不会自动加 sudo，请在具备 root 权限的环境执行" >&2
        exit 1
    fi

    apt-get "$@"
}

setup_cargo_registry() {
    mkdir -p "${CARGO_HOME}"
    if [ ! -f "${CARGO_HOME}/config.toml" ]; then
        cat > "${CARGO_HOME}/config.toml" <<'EOF'
[source.crates-io]
replace-with = "kylin"

[source.kylin]
registry = "sparse+https://alimirror.kylinos.cn/crates.io-index/"
EOF
    fi
}

find_llvm_tool() {
    local base="$1"
    local candidate

    if command -v "${base}" >/dev/null 2>&1; then
        command -v "${base}"
        return 0
    fi

    for candidate in \
        "${LOCAL_LLVM_BIN}/${base}" \
        /usr/bin/"${base}" \
        /usr/bin/"${base}"-* \
        /usr/lib/llvm-*/bin/"${base}" \
        /usr/local/bin/"${base}"-*; do
        if [ -x "${candidate}" ]; then
            echo "${candidate}"
            return 0
        fi
    done

    return 1
}

select_cargo_llvm_cov_version() {
    if [ -n "${CARGO_LLVM_COV_VERSION}" ]; then
        echo "${CARGO_LLVM_COV_VERSION}"
        return 0
    fi

    local rust_minor
    rust_minor="$(rustc --version | sed -n 's/^rustc 1\.\([0-9][0-9]*\)\..*/\1/p')"
    if [ -n "${rust_minor}" ] && [ "${rust_minor}" -lt 87 ]; then
        echo "0.6.15"
    fi
}

cargo_llvm_cov_version() {
    cargo llvm-cov --version 2>/dev/null | sed -n 's/^cargo-llvm-cov \([^ ]*\).*/\1/p'
}

install_cargo_llvm_cov() {
    local required_version
    local installed_version
    required_version="$(select_cargo_llvm_cov_version)"
    CARGO_LLVM_COV_VERSION="${required_version}"

    if command -v cargo-llvm-cov >/dev/null 2>&1; then
        if [ -z "${required_version}" ]; then
            return 0
        fi

        installed_version="$(cargo_llvm_cov_version)"
        if [ "${installed_version}" = "${required_version}" ]; then
            return 0
        fi
    fi

    if [ -n "${required_version}" ]; then
        echo "[INFO] 安装 cargo-llvm-cov ${required_version}..."
        cargo install cargo-llvm-cov --version "${required_version}" --locked --force
        return 0
    fi

    echo "[INFO] 安装 cargo-llvm-cov..."
    cargo install cargo-llvm-cov --locked
}

ensure_llvm_backend() {
    local llvm_cov_bin=""
    local llvm_profdata_bin=""

    llvm_cov_bin="$(find_llvm_tool llvm-cov || true)"
    llvm_profdata_bin="$(find_llvm_tool llvm-profdata || true)"

    if [ -n "${llvm_cov_bin}" ] && [ -n "${llvm_profdata_bin}" ]; then
        export LLVM_COV="${llvm_cov_bin}"
        export LLVM_PROFDATA="${llvm_profdata_bin}"
        export PATH="$(dirname "${llvm_cov_bin}"):${PATH}"
        return 0
    fi

    if [ -z "${llvm_cov_bin}" ] || [ -z "${llvm_profdata_bin}" ]; then
        echo "错误: 未找到可用的 llvm-cov / llvm-profdata" >&2
        exit 1
    fi

    export LLVM_COV="${llvm_cov_bin}"
    export LLVM_PROFDATA="${llvm_profdata_bin}"
    export PATH="$(dirname "${llvm_cov_bin}"):${PATH}"
}

ensure_system_dependencies() {
    local missing=0
    if ! command -v python3 >/dev/null 2>&1 || ! command -v cargo >/dev/null 2>&1 || ! command -v rustc >/dev/null 2>&1; then
        missing=1
    fi

    if ! find_llvm_tool llvm-cov >/dev/null 2>&1 || ! find_llvm_tool llvm-profdata >/dev/null 2>&1; then
        missing=1
    fi

    if [ "${missing}" -eq 0 ]; then
        return 0
    fi

    echo "[INFO] 安装系统依赖: ${APT_DEPENDENCY_PACKAGES}"
    if ! command -v apt-get >/dev/null 2>&1; then
        echo "错误: 未找到 apt-get，无法自动安装系统依赖" >&2
        exit 1
    fi

    run_apt_get update
    run_apt_get install -y ${APT_DEPENDENCY_PACKAGES}
}

ensure_system_dependencies
setup_cargo_registry
install_cargo_llvm_cov
ensure_llvm_backend

echo "[INFO] REPO_ROOT=${REPO_ROOT}"
echo "[INFO] UNIT_TEST_TIMEOUT_SECONDS=${UNIT_TEST_TIMEOUT_SECONDS}"
echo "[INFO] RUST_TEST_THREADS=${RUST_TEST_THREADS}"
echo "[INFO] MIN_AVG_COVERAGE=${MIN_AVG_COVERAGE}"
echo "[INFO] SONAR_XML=${SONAR_XML}"
echo "[INFO] APT_DEPENDENCY_PACKAGES=${APT_DEPENDENCY_PACKAGES}"
echo "[INFO] CARGO_HOME=${CARGO_HOME}"
echo "[INFO] RUSTUP_HOME=${RUSTUP_HOME}"
echo "[INFO] CARGO_LLVM_COV_VERSION=${CARGO_LLVM_COV_VERSION:-latest}"

exec "${TESTS_DIR}/runUnitTest.sh"
