#!/bin/sh
# Rokkhe CLI installer.
#
#   curl --proto '=https' --tlsv1.2 -fsSL https://rokkhe.com/install.sh | sh
#
# Piping a script from the internet into a shell is a real risk, so this one is
# written to reduce it rather than pretend it away:
#
#   * Every line lives inside a function invoked on the very last line. A
#     truncated download therefore defines functions and does nothing, instead of
#     executing half an install.
#   * The wheel's SHA-256 is verified before anything is installed, and the
#     checksum is fetched over a separate request so a single tampered response
#     cannot supply both artifact and hash.
#   * TLS is pinned to https and >=1.2. No plaintext fallback, no redirect to
#     another scheme.
#   * Nothing runs as root. The CLI installs into the user's own tool directory.
#
# You are encouraged not to pipe it at all:
#
#   curl --proto '=https' --tlsv1.2 -fsSLO https://rokkhe.com/install.sh
#   less install.sh          # read it
#   sh install.sh            # then run it
#
# POSIX sh on purpose: this runs on hardened servers and minimal containers where
# bash is not installed.

set -eu

BASE_URL="${ROKKHE_INSTALL_BASE:-https://rokkhe.com/dist}"
VERSION="${ROKKHE_VERSION:-latest}"
CURL_OPTS="--proto =https --tlsv1.2 -fsSL"

say() { printf '%s\n' "$*"; }
err() { printf 'error: %s\n' "$*" >&2; }

die() {
    err "$*"
    exit 1
}

need() {
    command -v "$1" >/dev/null 2>&1
}

fetch() {
    # $1 url, $2 destination
    # shellcheck disable=SC2086 # CURL_OPTS is a deliberate word list
    curl $CURL_OPTS -o "$2" "$1" || die "could not download $1"
}

sha256_of() {
    if need sha256sum; then
        sha256sum "$1" | cut -d' ' -f1
    elif need shasum; then
        shasum -a 256 "$1" | cut -d' ' -f1
    else
        die "need sha256sum or shasum to verify the download; refusing to install unverified"
    fi
}

check_prerequisites() {
    need curl || die "curl is required"

    if ! need python3; then
        die "python3 3.12 or newer is required"
    fi

    python3 - <<'PY' || die "python3 3.12 or newer is required (found $(python3 -V 2>&1))"
import sys
raise SystemExit(0 if sys.version_info >= (3, 12) else 1)
PY
}

resolve_version() {
    if [ "$VERSION" = "latest" ]; then
        tmp_version="$(mktemp)"
        fetch "$BASE_URL/latest.txt" "$tmp_version"
        VERSION="$(tr -d ' \t\r\n' < "$tmp_version")"
        rm -f "$tmp_version"
        [ -n "$VERSION" ] || die "could not resolve the latest version"
    fi
    say "Installing rokkhe $VERSION"
}

download_and_verify() {
    wheel_name="rokkhe_agent-${VERSION}-py3-none-any.whl"
    workdir="$(mktemp -d)"
    # Clean up even when a later step fails.
    trap 'rm -rf "$workdir"' EXIT INT TERM

    wheel_path="$workdir/$wheel_name"
    sums_path="$workdir/SHA256SUMS"

    say "Downloading $wheel_name"
    fetch "$BASE_URL/$wheel_name" "$wheel_path"

    # Fetched separately so one tampered response cannot supply both the
    # artifact and the hash that vouches for it.
    fetch "$BASE_URL/SHA256SUMS" "$sums_path"

    expected="$(grep " $wheel_name\$" "$sums_path" | cut -d' ' -f1 || true)"
    [ -n "$expected" ] || die "no checksum published for $wheel_name"

    actual="$(sha256_of "$wheel_path")"
    if [ "$expected" != "$actual" ]; then
        err "checksum mismatch for $wheel_name"
        err "  expected $expected"
        err "  actual   $actual"
        die "refusing to install a file that does not match its published hash"
    fi
    say "Checksum verified"
}

install_wheel() {
    # uv and pipx both install into an isolated environment on the user's PATH.
    # Plain pip --user is the last resort because it can collide with system
    # packages. None of these need root.
    if need uv; then
        say "Installing with uv"
        uv tool install --force "$wheel_path"
    elif need pipx; then
        say "Installing with pipx"
        pipx install --force "$wheel_path"
    else
        say "Installing with pip --user"
        say "  (install uv or pipx for an isolated environment)"
        python3 -m pip install --user --upgrade "$wheel_path"
    fi
}

report() {
    if need rokkhe; then
        say ""
        say "Installed: $(command -v rokkhe)"
        say ""
        say "  rokkhe login          sign in to a Rokkhe platform"
        say "  rokkhe doctor         check this machine"
        say "  rokkhe --help         everything else"
    else
        say ""
        say "Installed, but 'rokkhe' is not on your PATH yet."
        if need uv; then
            say "  Run: uv tool update-shell   (then reopen your shell)"
        elif need pipx; then
            say "  Run: pipx ensurepath        (then reopen your shell)"
        else
            say "  Add your Python user bin directory to PATH:"
            say "    $(python3 -m site --user-base)/bin"
        fi
    fi
}

main() {
    check_prerequisites
    resolve_version
    download_and_verify
    install_wheel
    report
}

# Everything above only defines functions. A download truncated at any point
# before this line therefore installs nothing at all.
main "$@"
