#!/bin/sh
# Altitude installer — https://getaltitude.dev
#
# Detects your platform, downloads the matching binary from dl.getaltitude.dev,
# verifies its SHA-256 against the published manifest, and installs it to
# ~/.local/bin/altitude. POSIX sh; needs only curl-or-wget and a sha256 tool.
#
#   curl -fsSL https://getaltitude.dev/install.sh | sh
#
# Override the install directory with ALTITUDE_INSTALL_DIR.
set -eu

DL_BASE="https://dl.getaltitude.dev/releases/latest"
INSTALL_DIR="${ALTITUDE_INSTALL_DIR:-${HOME}/.local/bin}"
BIN_NAME="altitude"
INSTALL_PAGE="https://getaltitude.dev/install"

work_dir=""
cleanup() {
	if [ -n "${work_dir}" ] && [ -d "${work_dir}" ]; then
		rm -rf "${work_dir}"
	fi
}
trap cleanup EXIT INT TERM

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

info() {
	printf 'altitude install: %s\n' "$1"
}

# ── 1. detect platform ────────────────────────────────────────────────────────
os="$(uname -s 2>/dev/null || echo unknown)"
arch="$(uname -m 2>/dev/null || echo unknown)"

case "${os}" in
	Darwin) os_id="darwin" ;;
	Linux) os_id="linux" ;;
	*) die "unsupported operating system '${os}'. Download manually: ${INSTALL_PAGE}" ;;
esac

case "${arch}" in
	x86_64 | amd64) arch_id="x64" ;;
	arm64 | aarch64) arch_id="arm64" ;;
	*) die "unsupported architecture '${arch}'. Download manually: ${INSTALL_PAGE}" ;;
esac

platform="${os_id}-${arch_id}"
asset="altitude-${platform}"

# ── 2. pick a downloader and a sha256 tool ────────────────────────────────────
if command -v curl >/dev/null 2>&1; then
	http_get() { curl -fsSL "$1"; }
	http_download() { curl -fsSL "$1" -o "$2"; }
elif command -v wget >/dev/null 2>&1; then
	http_get() { wget -qO- "$1"; }
	http_download() { wget -qO "$2" "$1"; }
else
	die "need curl or wget to download. Install one and re-run."
fi

if command -v sha256sum >/dev/null 2>&1; then
	sha256_of() { sha256sum "$1" | awk '{ print $1 }'; }
elif command -v shasum >/dev/null 2>&1; then
	sha256_of() { shasum -a 256 "$1" | awk '{ print $1 }'; }
else
	die "need sha256sum or shasum to verify the download. Install one and re-run."
fi

# ── 3. fetch the manifest ─────────────────────────────────────────────────────
info "Resolving the latest release for ${platform}…"
manifest="$(http_get "${DL_BASE}/latest.json")" || die "could not fetch ${DL_BASE}/latest.json"
[ -n "${manifest}" ] || die "empty release manifest at ${DL_BASE}/latest.json"

# Flatten to one line so the field scrapes below don't depend on JSON formatting.
manifest_flat="$(printf '%s' "${manifest}" | tr -d '\n\r\t')"

version="$(printf '%s' "${manifest_flat}" | sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
[ -n "${version}" ] || die "could not read the version from the manifest"

# Isolate this platform's object — "<platform>": { ... } — then its 64-hex sha256.
platform_obj="$(printf '%s' "${manifest_flat}" | sed -n "s/.*\"${platform}\"[[:space:]]*:[[:space:]]*{\([^}]*\)}.*/\1/p")"
expected_sha="$(printf '%s' "${platform_obj}" | sed -n 's/.*"sha256"[[:space:]]*:[[:space:]]*"\([0-9a-fA-F]\{64\}\)".*/\1/p')"
[ -n "${expected_sha}" ] || die "no ${platform} build in release ${version}. Download manually: ${INSTALL_PAGE}"

# ── 4. download ───────────────────────────────────────────────────────────────
work_dir="$(mktemp -d 2>/dev/null || mktemp -d -t altitude.XXXXXX)" || die "could not create a temp directory"
tmp_bin="${work_dir}/${asset}"

info "Downloading altitude ${version} (${platform})…"
http_download "${DL_BASE}/${asset}" "${tmp_bin}" || die "download failed: ${DL_BASE}/${asset}"
[ -s "${tmp_bin}" ] || die "downloaded file is empty"

# ── 5. verify ─────────────────────────────────────────────────────────────────
info "Verifying checksum…"
actual_sha="$(sha256_of "${tmp_bin}")"
if [ "${actual_sha}" != "${expected_sha}" ]; then
	die "checksum mismatch — refusing to install.
  expected ${expected_sha}
  actual   ${actual_sha}"
fi

# ── 6. install ────────────────────────────────────────────────────────────────
mkdir -p "${INSTALL_DIR}" || die "could not create ${INSTALL_DIR}"
chmod +x "${tmp_bin}" || die "could not mark the binary executable"
# mv is atomic within a filesystem; fall back to cp+rm across filesystem boundaries.
if ! mv "${tmp_bin}" "${INSTALL_DIR}/${BIN_NAME}" 2>/dev/null; then
	cp "${tmp_bin}" "${INSTALL_DIR}/${BIN_NAME}" || die "could not install to ${INSTALL_DIR}/${BIN_NAME}"
	rm -f "${tmp_bin}"
fi

info "Installed altitude ${version} → ${INSTALL_DIR}/${BIN_NAME}"

# ── 7. PATH hint ──────────────────────────────────────────────────────────────
case ":${PATH}:" in
	*":${INSTALL_DIR}:"*)
		info "Run 'altitude --version' to get started."
		;;
	*)
		printf '\n'
		info "${INSTALL_DIR} is not on your PATH. Add it to your shell profile:"
		# The literal $PATH is intentional — it's text for the user to paste, not for us to expand.
		# shellcheck disable=SC2016
		printf '\n  export PATH="%s:$PATH"\n\n' "${INSTALL_DIR}"
		info "Then run 'altitude --version'."
		;;
esac
