#!/bin/bash
set -euo pipefail

INSTALL_DIR="/usr/local/bin"
BINARY_NAME="borg1"
SYMLINK_NAME="borg"
GITHUB_API="https://api.github.com/repos/borgbackup/borg/releases/tags"
GITHUB_DL="https://github.com/borgbackup/borg/releases/download"

# --- Helper functions --------------------------------------------------------

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

usage() {
    cat <<EOF
Usage: $(basename "$0") <version>

Install BorgBackup from GitHub releases.

Arguments:
  version    Borg version to install (e.g. 1.4.3)

The script detects the installed glibc version, picks the matching
(or next-lower) binary from the GitHub release, and installs it to
${INSTALL_DIR}/${BINARY_NAME} with a symlink ${INSTALL_DIR}/${SYMLINK_NAME}.

Examples:
  $(basename "$0") 1.4.3
EOF
    exit 1
}

# --- Argument handling -------------------------------------------------------

[[ $# -eq 1 ]] || usage
[[ "$1" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || die "Invalid version format: $1 (expected: X.Y.Z)"

VERSION="$1"

# --- Root check --------------------------------------------------------------

[[ "$(id -u)" -eq 0 ]] || die "This script must be run as root"

# --- Detect system glibc version ---------------------------------------------

info "Detecting glibc version ..."
GLIBC_VERSION=$(dpkg -l libc-bin 2>/dev/null | awk '/^ii/{print $3}' | grep -oP '^\d+\.\d+')
[[ -n "${GLIBC_VERSION}" ]] || die "Could not detect glibc version from dpkg"
# Convert to integer for comparison (e.g. 2.35 -> 235)
GLIBC_INT=$(echo "${GLIBC_VERSION}" | tr -d '.')
info "System glibc: ${GLIBC_VERSION}"

# --- Query available binaries from GitHub ------------------------------------

info "Fetching release assets for borg ${VERSION} ..."
ASSETS=$(curl -sfL "${GITHUB_API}/${VERSION}" \
    | python3 -c "
import sys, json
assets = json.load(sys.stdin).get('assets', [])
for a in assets:
    name = a['name']
    if 'linux' in name and 'x86_64' in name and not name.endswith(('.asc', '.tgz', '.tgz.asc')):
        print(name)
") || die "Release ${VERSION} not found on GitHub"

[[ -n "${ASSETS}" ]] || die "No Linux x86_64 binaries found for version ${VERSION}"

# --- Select best matching glibc binary ---------------------------------------

BEST_ASSET=""
BEST_GLIBC=0

while IFS= read -r asset; do
    asset_glibc=$(echo "${asset}" | grep -oP 'glibc\K\d+')
    [[ -n "${asset_glibc}" ]] || continue

    if (( asset_glibc <= GLIBC_INT && asset_glibc > BEST_GLIBC )); then
        BEST_GLIBC=${asset_glibc}
        BEST_ASSET="${asset}"
    fi
done <<< "${ASSETS}"

[[ -n "${BEST_ASSET}" ]] || die "No compatible binary found (system glibc ${GLIBC_VERSION}, available: $(echo "${ASSETS}" | tr '\n' ' '))"

# Format glibc for display (e.g. 235 -> 2.35)
BEST_GLIBC_FMT="${BEST_GLIBC:0:1}.${BEST_GLIBC:1}"
info "Selected: ${BEST_ASSET} (glibc ${BEST_GLIBC_FMT})"

# --- Backup existing binary --------------------------------------------------

TARGET="${INSTALL_DIR}/${BINARY_NAME}"

if [[ -f "${TARGET}" && ! -L "${TARGET}" ]]; then
    BACKUP="${TARGET}.old"
    info "Backing up existing binary to ${BACKUP}"
    mv "${TARGET}" "${BACKUP}"
fi

# --- Download ----------------------------------------------------------------

DOWNLOAD_URL="${GITHUB_DL}/${VERSION}/${BEST_ASSET}"
info "Downloading ${DOWNLOAD_URL} ..."
curl -fsSL -o "${TARGET}" "${DOWNLOAD_URL}" || die "Download failed"

chmod +x "${TARGET}"

# --- SHA256 output -----------------------------------------------------------

SHA256=$(sha256sum "${TARGET}" | awk '{print $1}')
info "SHA256: ${SHA256}"

# --- Symlink -----------------------------------------------------------------

LINK="${INSTALL_DIR}/${SYMLINK_NAME}"

if [[ -L "${LINK}" ]]; then
    rm "${LINK}"
elif [[ -e "${LINK}" ]]; then
    die "${LINK} exists and is not a symlink, not overwriting"
fi

ln -s "${BINARY_NAME}" "${LINK}"
info "Symlink: ${LINK} -> ${BINARY_NAME}"

# --- Verify ------------------------------------------------------------------

INSTALLED_VERSION=$("${TARGET}" -V 2>&1 || true)
info "Installed: ${INSTALLED_VERSION}"
info "Done."
