#!/bin/sh
#
# Zuild installer.
#
#   curl -fsSL https://zuild.dev/install.sh | sh
#
# Detects your platform, downloads the matching binary from GitHub Releases,
# verifies its SHA-256 checksum against the release manifest (served over
# HTTPS), and installs it.

set -eu

REPO="zuilddev/zuild"
INSTALL_DIR="${ZUILD_INSTALL_DIR:-/usr/local/bin}"
# Override to install from a mirror or air-gapped release host. Defaults to
# GitHub Releases. The host must expose the same /download/<ver>/ layout.
BASE_URL="${ZUILD_BASE_URL:-https://github.com/${REPO}/releases}"

# ── Optional version arg (defaults to latest) ────────────────────────────────
VERSION="${1:-latest}"

err() { printf '\033[31merror:\033[0m %s\n' "$1" >&2; exit 1; }
info() { printf '\033[36m%s\033[0m\n' "$1"; }

# ── Pick a downloader ────────────────────────────────────────────────────────
if command -v curl >/dev/null 2>&1; then
  DL="curl -fsSL"
  DL_O="curl -fsSL -o"
elif command -v wget >/dev/null 2>&1; then
  DL="wget -qO-"
  DL_O="wget -qO"
else
  err "curl or wget is required but neither is installed"
fi

download() { # url [output]
  if [ -n "${2:-}" ]; then
    if [ "${DL_O%% *}" = "curl" ]; then curl -fsSL -o "$2" "$1"; else wget -qO "$2" "$1"; fi
  else
    $DL "$1"
  fi
}

# ── Detect OS ────────────────────────────────────────────────────────────────
case "$(uname -s)" in
  Darwin) OS="darwin" ;;
  Linux)  OS="linux" ;;
  MINGW*|MSYS*|CYGWIN*) err "Windows is not supported by this installer. See https://zuild.dev for options." ;;
  *) err "Unsupported OS: $(uname -s)" ;;
esac

# ── Detect architecture ──────────────────────────────────────────────────────
case "$(uname -m)" in
  x86_64|amd64) ARCH="x64" ;;
  arm64|aarch64) ARCH="arm64" ;;
  *) err "Unsupported architecture: $(uname -m)" ;;
esac

# ── Rosetta 2: native arm64 binary on Apple Silicon running an x64 shell ──────
if [ "$OS" = "darwin" ] && [ "$ARCH" = "x64" ]; then
  if [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)" = "1" ]; then
    ARCH="arm64"
  fi
fi

# ── musl detection on Linux (Alpine etc.) ────────────────────────────────────
PLATFORM="${OS}-${ARCH}"
if [ "$OS" = "linux" ] && [ "$ARCH" = "x64" ]; then
  if [ -f /lib/libc.musl-x86_64.so.1 ] || (ldd /bin/ls 2>&1 | grep -qi musl); then
    PLATFORM="linux-x64-musl"
  fi
fi

info "Detected platform: ${PLATFORM}"

# ── Resolve version + manifest URL ───────────────────────────────────────────
if [ "$VERSION" = "latest" ]; then
  MANIFEST_URL="${BASE_URL}/latest/download/manifest.json"
  BIN_URL="${BASE_URL}/latest/download/zuild-${PLATFORM}"
else
  case "$VERSION" in v*) ;; *) VERSION="v${VERSION}" ;; esac
  MANIFEST_URL="${BASE_URL}/download/${VERSION}/manifest.json"
  BIN_URL="${BASE_URL}/download/${VERSION}/zuild-${PLATFORM}"
fi

# ── Fetch manifest and extract the checksum for this platform ────────────────
info "Fetching manifest..."
MANIFEST="$(download "$MANIFEST_URL")" || err "could not download manifest (release may not exist yet)"

# Pull "<platform>": { "checksum": "<64 hex>" } out of the JSON without jq
CHECKSUM="$(printf '%s' "$MANIFEST" | tr -d '\n\r\t ' \
  | sed -n "s/.*\"${PLATFORM}\":{\"checksum\":\"\([a-f0-9]\{64\}\)\".*/\1/p")"

[ -n "$CHECKSUM" ] || err "platform ${PLATFORM} not found in manifest"

# ── Download the binary ──────────────────────────────────────────────────────
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
BIN="${TMP}/zuild"

info "Downloading zuild (${PLATFORM})..."
download "$BIN_URL" "$BIN" || err "download failed"

# ── Verify checksum ──────────────────────────────────────────────────────────
if command -v sha256sum >/dev/null 2>&1; then
  ACTUAL="$(sha256sum "$BIN" | cut -d' ' -f1)"
elif command -v shasum >/dev/null 2>&1; then
  ACTUAL="$(shasum -a 256 "$BIN" | cut -d' ' -f1)"
else
  err "no SHA-256 tool found (need sha256sum or shasum)"
fi

if [ "$ACTUAL" != "$CHECKSUM" ]; then
  err "checksum mismatch — refusing to install (expected ${CHECKSUM}, got ${ACTUAL})"
fi

chmod +x "$BIN"

# ── Install ──────────────────────────────────────────────────────────────────
if [ -w "$INSTALL_DIR" ]; then
  mv "$BIN" "${INSTALL_DIR}/zuild"
else
  info "Elevating with sudo to write to ${INSTALL_DIR}..."
  sudo mv "$BIN" "${INSTALL_DIR}/zuild"
fi

printf '\n\033[32m✅ Zuild installed to %s/zuild\033[0m\n\n' "$INSTALL_DIR"
"${INSTALL_DIR}/zuild" --version || true
printf '\nGet started:  \033[36mzuild -f Dockerfile .\033[0m\n'
