#!/bin/sh
# install.sh — download and install a prebuilt rdbms-playground binary.
#
# Quick start (Linux / macOS):
#   curl -fsSL https://git.lazyeval.net/oli/rdbms-playground/raw/branch/main/scripts/install.sh | sh
#
# What it does: detects your OS + CPU, downloads the matching release binary
# from the Gitea releases (Linux uses the fully-static musl build), verifies
# its SHA-256 checksum, and installs it to ~/.local/bin.
#
# Environment overrides:
#   RDBMS_VERSION      install a specific tag (e.g. v0.2.0) instead of the latest
#   RDBMS_INSTALL_DIR  install directory (default: $HOME/.local/bin)
#   RDBMS_OS           force the OS (testing): Linux | Darwin
#   RDBMS_ARCH         force the CPU (testing): x86_64 | aarch64
#
# Flags:
#   --print-target   print the resolved target triple and exit (no download)
#   -h, --help       print this help and exit
#
# Notes:
#   * Windows is not installable via this script (the binary is a .exe) —
#     use Scoop/winget (planned) or download the .exe from the releases page.
#   * macOS: a curl download is not quarantined by Gatekeeper, so the binary
#     runs without extra steps. (Developer-ID signing + notarization is a
#     separate, planned improvement for browser downloads.)
#
# POSIX sh — no bashisms, so it runs under the `sh` of `curl | sh`.

set -eu

REPO_BASE="https://git.lazyeval.net/oli/rdbms-playground"
API_BASE="https://git.lazyeval.net/api/v1/repos/oli/rdbms-playground"
BIN_NAME="rdbms-playground"
PRINT_TARGET=0

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

usage() {
	# Lines 2..(first blank) of this file are the human-readable header.
	sed -n '2,/^$/p' "$0" | sed 's/^# \{0,1\}//'
}

# Resolve the Rust target triple for the current (or forced) platform.
# Linux  -> <arch>-unknown-linux-musl   (the fully-static build)
# macOS  -> <arch>-apple-darwin
detect_target() {
	os="${RDBMS_OS:-$(uname -s)}"
	arch="${RDBMS_ARCH:-$(uname -m)}"
	case "$os" in
	Linux | linux) os_part="unknown-linux-musl" ;;
	Darwin | darwin | macos | macOS) os_part="apple-darwin" ;;
	MINGW* | MSYS* | CYGWIN* | *Windows* | *windows*)
		err "Windows is not supported by this installer — use Scoop/winget (planned) or download the .exe from $REPO_BASE/releases" ;;
	*) err "unsupported operating system: $os" ;;
	esac
	case "$arch" in
	x86_64 | amd64) arch_part="x86_64" ;;
	aarch64 | arm64) arch_part="aarch64" ;;
	*) err "unsupported CPU architecture: $arch" ;;
	esac
	printf '%s-%s' "$arch_part" "$os_part"
}

# Download $1 to file $2 (curl or wget).
download() {
	if command -v curl >/dev/null 2>&1; then
		curl -fsSL "$1" -o "$2"
	elif command -v wget >/dev/null 2>&1; then
		wget -qO "$2" "$1"
	else
		err "need either curl or wget on PATH"
	fi
}

# Fetch $1 to stdout (curl or wget).
fetch() {
	if command -v curl >/dev/null 2>&1; then
		curl -fsSL "$1"
	elif command -v wget >/dev/null 2>&1; then
		wget -qO- "$1"
	else
		err "need either curl or wget on PATH"
	fi
}

# The release tag to install: $RDBMS_VERSION if set, else the latest release.
resolve_version() {
	if [ -n "${RDBMS_VERSION:-}" ]; then
		printf '%s' "$RDBMS_VERSION"
		return
	fi
	json=$(fetch "$API_BASE/releases/latest") ||
		err "could not query the latest release from $API_BASE"
	# Portable JSON scrape (no jq): the latest-release object carries exactly
	# one "tag_name": "<tag>" field.
	tag=$(printf '%s' "$json" |
		grep -o '"tag_name"[[:space:]]*:[[:space:]]*"[^"]*"' |
		head -1 | sed 's/.*"\([^"]*\)"$/\1/')
	[ -n "$tag" ] || err "could not parse the latest release tag"
	printf '%s' "$tag"
}

# Verify file $1 against sha256 sidecar $2 (format: "<hash>  <name>").
verify_checksum() {
	expected=$(awk '{print $1; exit}' "$2")
	if command -v sha256sum >/dev/null 2>&1; then
		actual=$(sha256sum "$1" | awk '{print $1}')
	elif command -v shasum >/dev/null 2>&1; then
		actual=$(shasum -a 256 "$1" | awk '{print $1}')
	else
		info "warning: no sha256 tool found — skipping checksum verification"
		return 0
	fi
	[ "$expected" = "$actual" ] ||
		err "checksum mismatch (expected $expected, got $actual) — refusing to install"
}

main() {
	while [ $# -gt 0 ]; do
		case "$1" in
		--print-target) PRINT_TARGET=1 ;;
		-h | --help)
			usage
			exit 0
			;;
		*) err "unknown argument: $1 (try --help)" ;;
		esac
		shift
	done

	target=$(detect_target)
	if [ "$PRINT_TARGET" = "1" ]; then
		printf '%s\n' "$target"
		exit 0
	fi

	version=$(resolve_version)
	asset="$BIN_NAME-$version-$target"
	url="$REPO_BASE/releases/download/$version/$asset"
	dir="${RDBMS_INSTALL_DIR:-$HOME/.local/bin}"

	tmp=$(mktemp -d 2>/dev/null) || err "could not create a temporary directory"
	trap 'rm -rf "$tmp"' EXIT INT TERM

	info "downloading $asset ..."
	download "$url" "$tmp/$BIN_NAME" || err "download failed: $url"
	download "$url.sha256" "$tmp/$BIN_NAME.sha256" || err "checksum download failed: $url.sha256"
	verify_checksum "$tmp/$BIN_NAME" "$tmp/$BIN_NAME.sha256"

	mkdir -p "$dir" || err "could not create install directory: $dir"
	chmod +x "$tmp/$BIN_NAME"
	mv "$tmp/$BIN_NAME" "$dir/$BIN_NAME" || err "could not install to $dir"
	info "installed $BIN_NAME $version -> $dir/$BIN_NAME"

	case ":${PATH:-}:" in
	*":$dir:"*) ;;
	*) info "note: $dir is not on your PATH. Add it, e.g.:  export PATH=\"$dir:\$PATH\"" ;;
	esac
}

main "$@"
