#!/bin/sh
# imprecise CLI installer.
#
#   curl -fsSL https://get.imprecise.dev | sh
#
# Downloads the `imprecise` binary for your platform, verifies its SHA-256
# checksum against the release, and installs it onto your PATH. POSIX sh.
#
# The binary needs a one-time `imprecise login` before it can do anything, so
# installing it grants no access on its own.
#
# Environment overrides (all optional):
#
#   IMPRECISE_CHANNEL       stable | dev              (default: stable)
#   IMPRECISE_INSTALL_BASE  download base URL         (default: https://get.imprecise.dev)
#   IMPRECISE_VERSION       vX.Y.Z | latest           (default: latest)
#   IMPRECISE_INSTALL_DIR   target dir                (default: ~/.local/bin, else /usr/local/bin)
#   IMPRECISE_TOKEN         token for authenticated downloads (default: unset)
#   IMPRECISE_COMPONENT     release component id      (default: imprecise-cli)
#   IMPRECISE_BINARY        installed binary name     (default: imprecise)
#
set -eu

# ── configuration ──────────────────────────────────────────────────────────
CHANNEL="${IMPRECISE_CHANNEL:-stable}"
BASE="${IMPRECISE_INSTALL_BASE:-https://get.imprecise.dev}"
VERSION="${IMPRECISE_VERSION:-latest}"
COMPONENT="${IMPRECISE_COMPONENT:-imprecise-cli}"
BINARY="${IMPRECISE_BINARY:-imprecise}"
TOKEN="${IMPRECISE_TOKEN:-}"

BASE="${BASE%/}" # strip trailing slash

# ── helpers ────────────────────────────────────────────────────────────────
info()  { printf '\033[0;34m::\033[0m %s\n' "$*" >&2; }
warn()  { printf '\033[0;33m!!\033[0m %s\n' "$*" >&2; }
die()   { printf '\033[0;31mxx\033[0m %s\n' "$*" >&2; exit 1; }

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

# http_get <url> -> body on stdout. Follows redirects. Adds bearer if TOKEN set.
http_get() {
	_url="$1"
	if have curl; then
		if [ -n "$TOKEN" ]; then
			curl -fsSL -H "Authorization: Bearer $TOKEN" "$_url"
		else
			curl -fsSL "$_url"
		fi
	elif have wget; then
		if [ -n "$TOKEN" ]; then
			wget -qO- --header="Authorization: Bearer $TOKEN" "$_url"
		else
			wget -qO- "$_url"
		fi
	else
		die "need curl or wget"
	fi
}

# http_download <url> <dest>. Follows redirects (the 302 to the signed URL).
http_download() {
	_url="$1"; _dest="$2"
	if have curl; then
		if [ -n "$TOKEN" ]; then
			curl -fsSL -H "Authorization: Bearer $TOKEN" -o "$_dest" "$_url"
		else
			curl -fsSL -o "$_dest" "$_url"
		fi
	elif have wget; then
		if [ -n "$TOKEN" ]; then
			wget -qO "$_dest" --header="Authorization: Bearer $TOKEN" "$_url"
		else
			wget -qO "$_dest" "$_url"
		fi
	else
		die "need curl or wget"
	fi
}

# sha256_of <file> -> hex digest on stdout
sha256_of() {
	if have sha256sum; then
		sha256sum "$1" | awk '{print $1}'
	elif have shasum; then
		shasum -a 256 "$1" | awk '{print $1}'
	else
		die "need sha256sum or shasum to verify the download"
	fi
}

# ── platform detection ─────────────────────────────────────────────────────
detect_platform() {
	_os="$(uname -s)"
	_arch="$(uname -m)"

	case "$_os" in
		Linux)  OS="linux" ;;
		Darwin) OS="darwin" ;;
		MINGW*|MSYS*|CYGWIN*|Windows_NT)
			die "Windows is not supported by this script. Download the .zip from the docs: https://imprecise.dev/docs/cli/install-and-login" ;;
		*) die "unsupported OS: $_os" ;;
	esac

	case "$_arch" in
		x86_64|amd64)  ARCH="amd64" ;;
		aarch64|arm64) ARCH="arm64" ;;
		*) die "unsupported architecture: $_arch" ;;
	esac
}

# ── install dir ────────────────────────────────────────────────────────────
pick_install_dir() {
	if [ -n "${IMPRECISE_INSTALL_DIR:-}" ]; then
		INSTALL_DIR="$IMPRECISE_INSTALL_DIR"
		NEED_SUDO=0
		return
	fi
	# Prefer a no-sudo user dir.
	INSTALL_DIR="$HOME/.local/bin"
	NEED_SUDO=0
	# If ~/.local/bin isn't on PATH but /usr/local/bin is, prefer the latter.
	case ":$PATH:" in
		*":$HOME/.local/bin:"*) : ;;
		*)
			if [ -d /usr/local/bin ] && [ -w /usr/local/bin ]; then
				INSTALL_DIR="/usr/local/bin"
			elif [ -d /usr/local/bin ]; then
				INSTALL_DIR="/usr/local/bin"
				NEED_SUDO=1
			fi
			;;
	esac
}

# ── channel → version resolution ───────────────────────────────────────────
# GET {BASE}/v1/releases returns a per-component catalog carrying both the
# stable head ("latest") and the newest pre-release ("latest_dev"). We read the
# field for the chosen channel. An explicit IMPRECISE_VERSION wins.
resolve_version() {
	if [ "$VERSION" != "latest" ]; then
		info "Using pinned version $VERSION"
		return
	fi

	# The catalog carries both "latest" (stable head) and "latest_dev" (highest
	# incl. prereleases). Pick the field for our channel.
	_field="latest"
	[ "$CHANNEL" = "dev" ] && _field="latest_dev"

	info "Resolving latest ($CHANNEL channel) …"
	_catalog="$(http_get "$BASE/v1/releases")" \
		|| die "could not reach the release catalog at $BASE"

	# Pull the channel's version field for our component out of the JSON without
	# a JSON parser. Catalog shape:
	#   {"components":[{"id":"imprecise-cli","latest":"v0.1.0","latest_dev":"v0.2.0-rc1",...}]}
	# tr splits at each '{': a component's "id" and its version fields sit in the
	# same segment (before the first nested asset object).
	VERSION="$(
		printf '%s' "$_catalog" \
		| tr '{' '\n' \
		| grep "\"id\"[[:space:]]*:[[:space:]]*\"$COMPONENT\"" \
		| grep -o "\"$_field\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" \
		| head -n1 \
		| sed "s/.*\"$_field\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/"
	)"

	[ -n "$VERSION" ] || die "no published $CHANNEL release found for $COMPONENT"
	info "Latest is $VERSION"
}

# ── download + verify + install ────────────────────────────────────────────
main() {
	detect_platform
	pick_install_dir
	resolve_version

	# $VERSION is already a concrete tag (resolved above), so the download and
	# checksums routes need no ?channel= param — that only affects "latest".
	ASSET="$COMPONENT-$VERSION-$OS-$ARCH.tar.gz"
	DL_URL="$BASE/v1/releases/$COMPONENT/$VERSION/$OS/$ARCH?format=tar.gz"
	SUMS_URL="$BASE/v1/releases/$COMPONENT/$VERSION/SHA256SUMS.txt"

	TMP="$(mktemp -d "${TMPDIR:-/tmp}/imprecise-install.XXXXXX")"
	# shellcheck disable=SC2064
	trap "rm -rf \"$TMP\"" EXIT INT TERM

	info "Downloading $ASSET …"
	http_download "$DL_URL" "$TMP/$ASSET" \
		|| die "download failed ($DL_URL)"

	# Verify against SHA256SUMS.txt from the same release. A missing sums file
	# is a hard failure, not a silent skip — an unverified binary is worse than
	# no binary.
	info "Verifying checksum …"
	if http_download "$SUMS_URL" "$TMP/SHA256SUMS.txt" 2>/dev/null; then
		_want="$(grep " $ASSET\$" "$TMP/SHA256SUMS.txt" 2>/dev/null | awk '{print $1}' | head -n1)"
		[ -n "$_want" ] || _want="$(grep "$ASSET" "$TMP/SHA256SUMS.txt" 2>/dev/null | awk '{print $1}' | head -n1)"
		[ -n "$_want" ] || die "no checksum for $ASSET in SHA256SUMS.txt"
		_got="$(sha256_of "$TMP/$ASSET")"
		[ "$_want" = "$_got" ] || die "checksum mismatch! expected $_want, got $_got"
		info "Checksum OK"
	else
		die "could not fetch SHA256SUMS.txt — refusing to install an unverified binary"
	fi

	info "Extracting …"
	tar -xzf "$TMP/$ASSET" -C "$TMP" || die "extract failed"

	# The archive may contain the binary at the top level or under a dir. Find
	# the executable by name; fall back to the single-most-likely candidate.
	_bin="$(find "$TMP" -type f -name "$BINARY" 2>/dev/null | head -n1)"
	if [ -z "$_bin" ]; then
		_bin="$(find "$TMP" -type f -name "$BINARY.exe" 2>/dev/null | head -n1)"
	fi
	[ -n "$_bin" ] || die "could not find '$BINARY' inside the archive"

	# Install.
	mkdir -p "$INSTALL_DIR" 2>/dev/null || true
	_dest="$INSTALL_DIR/$BINARY"
	if [ "${NEED_SUDO:-0}" = "1" ]; then
		info "Installing to $_dest (needs sudo)"
		sudo install -m 0755 "$_bin" "$_dest" || die "install to $_dest failed"
	else
		install -m 0755 "$_bin" "$_dest" 2>/dev/null \
			|| { mkdir -p "$INSTALL_DIR" && cp "$_bin" "$_dest" && chmod 0755 "$_dest"; } \
			|| die "install to $_dest failed (set IMPRECISE_INSTALL_DIR to a writable path)"
	fi

	info "Installed $BINARY $VERSION → $_dest"

	# PATH hint.
	case ":$PATH:" in
		*":$INSTALL_DIR:"*) : ;;
		*)
			warn "$INSTALL_DIR is not on your PATH. Add it, e.g.:"
			warn "    export PATH=\"$INSTALL_DIR:\$PATH\""
			;;
	esac

	# Verify it runs (best-effort; PATH may not be updated in this shell).
	if "$_dest" --version >/dev/null 2>&1; then
		info "$("$_dest" --version 2>&1 | head -n1)"
	fi

	printf '\n'
	info "Next: run '$BINARY login' to authenticate."
}

main "$@"
