#!/bin/sh
# Installs the 0sql CLI.
#
#   curl -fsSL https://0sql.io/install.sh | sh
#
# Works out which build this machine needs, checks it against the
# published checksum, and puts it somewhere on PATH. Nothing else: the
# CLI is one static binary with no dependencies.
#
#   ZSQL_VERSION=0.1.1       a particular version instead of the newest
#   ZSQL_INSTALL_DIR=~/bin   somewhere other than the usual places
#   ZSQL_DOWNLOADS=...       another base URL, for testing
set -eu

repo=${ZSQL_REPO:-stratasite/0sql-cli}
version=${ZSQL_VERSION:-latest}

# GitHub keeps a permanent redirect at releases/latest/download, so the
# newest build needs no version lookup. A pinned version is the same
# shape with the tag spelled out.
if [ -n "${ZSQL_DOWNLOADS:-}" ]; then
  base=$ZSQL_DOWNLOADS
elif [ "$version" = latest ]; then
  base="https://github.com/$repo/releases/latest/download"
else
  case $version in v*) tag=$version ;; *) tag=v$version ;; esac
  base="https://github.com/$repo/releases/download/$tag"
fi

say() { printf '%s\n' "$*"; }
die() { printf 'install: %s\n' "$*" >&2; exit 1; }

# ------------------------------------------------- which build is this
os=$(uname -s)
arch=$(uname -m)
case $os in
  Linux) os=linux ;;
  Darwin) os=macos ;;
  *) die "no build for $os yet. Builds exist for Linux and macOS; ask about $os." ;;
esac
case $arch in
  x86_64 | amd64) arch=x86_64 ;;
  aarch64 | arm64) arch=aarch64 ;;
  *) die "no build for $arch yet. Builds exist for x86_64 and aarch64." ;;
esac
asset="zsql-$arch-$os"

# ----------------------------------------------------- how to fetch it
if command -v curl >/dev/null 2>&1; then
  fetch() { curl -fsSL "$1" -o "$2"; }
elif command -v wget >/dev/null 2>&1; then
  fetch() { wget -qO "$2" "$1"; }
else
  die "needs curl or wget"
fi

if command -v sha256sum >/dev/null 2>&1; then
  sum() { sha256sum "$1" | cut -d' ' -f1; }
elif command -v shasum >/dev/null 2>&1; then
  sum() { shasum -a 256 "$1" | cut -d' ' -f1; }
else
  die "needs sha256sum or shasum to check the download"
fi

# ------------------------------------------------------- where it goes
if [ -n "${ZSQL_INSTALL_DIR:-}" ]; then
  dir=$ZSQL_INSTALL_DIR
elif [ -w /usr/local/bin ] 2>/dev/null; then
  dir=/usr/local/bin
else
  dir=$HOME/.local/bin
fi
mkdir -p "$dir" || die "cannot make $dir"
[ -w "$dir" ] || die "cannot write to $dir. Set ZSQL_INSTALL_DIR to somewhere you can, or re-run with sudo."

# ------------------------------------------------------------- get it
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT INT TERM

say "0sql: fetching $asset ($version)"
fetch "$base/$asset" "$tmp/$asset" || die "could not download $base/$asset"

# A binary that is not the one that was published is not worth running,
# so this is checked before anything is installed.
if fetch "$base/SHA256SUMS" "$tmp/SHA256SUMS" 2>/dev/null; then
  want=$(grep "  $asset\$" "$tmp/SHA256SUMS" | cut -d' ' -f1)
  [ -n "$want" ] || die "$asset is not listed in SHA256SUMS"
  got=$(sum "$tmp/$asset")
  [ "$want" = "$got" ] || die "checksum mismatch for $asset: expected $want, got $got"
  say "0sql: checksum ok"
else
  die "could not download the checksums; refusing to install something unverified"
fi

chmod +x "$tmp/$asset"
mv -f "$tmp/$asset" "$dir/zsql"

# ------------------------------------------------------------ say so
installed=$("$dir/zsql" --version 2>/dev/null || true)
[ -n "$installed" ] || die "installed $dir/zsql but it will not run on this machine"
say "0sql: installed $installed to $dir/zsql"

case ":$PATH:" in
  *":$dir:"*) say "0sql: run 'zsql' to start, or 'zsql init' in a new project" ;;
  *) say ""
     say "$dir is not on your PATH. Add it:"
     say "    export PATH=\"$dir:\$PATH\"" ;;
esac
