#!/bin/sh
# Download and verify an official MicroDev release. No root privileges required.
set -eu

fail() { printf 'Error: %s\n' "$*" >&2; exit 1; }
usage() {
    printf '%s\n' 'Usage: sh install-microdev.sh [--version VERSION] [--bin-dir ABSOLUTE_PATH]' \
        'Installs microdev to ~/.local/bin. Supports macOS and Linux, Intel and ARM64.'
}
version=latest
bin_dir=${HOME:?HOME must be set}/.local/bin
base_url=${MICRODEV_DOWNLOAD_URL:-https://microdev.dev/downloads}
while [ "$#" -gt 0 ]; do
    case "$1" in
        --version) [ "$#" -ge 2 ] || fail '--version requires a value'; version=$2; shift 2 ;;
        --bin-dir) [ "$#" -ge 2 ] || fail '--bin-dir requires a value'; bin_dir=$2; shift 2 ;;
        --help|-h) usage; exit 0 ;;
        *) fail "Unknown option: $1" ;;
    esac
done
case "$version" in ''|*[!a-zA-Z0-9._-]*|.*) fail 'Invalid release version' ;; esac
case "$bin_dir" in /*) ;; *) fail '--bin-dir must be an absolute path' ;; esac
case "$base_url" in https://*) ;; *) fail 'Download URL must use HTTPS' ;; esac
case "$(uname -s)" in
    Darwin) platform=apple-darwin ;;
    Linux) platform=unknown-linux-musl ;;
    *) fail 'MicroDev supports macOS and Linux. On Windows, install inside WSL2.' ;;
esac
case "$(uname -m)" in
    x86_64|amd64) architecture=x86_64 ;;
    arm64|aarch64) architecture=aarch64 ;;
    *) fail 'MicroDev supports Intel/AMD 64-bit and ARM64 processors.' ;;
esac
for tool in curl tar mktemp awk; do command -v "$tool" >/dev/null 2>&1 || fail "Install $tool and try again"; done
if command -v sha256sum >/dev/null 2>&1; then checksum_tool=sha256sum
elif command -v shasum >/dev/null 2>&1; then checksum_tool=shasum
else fail 'Install sha256sum or shasum to verify the download'; fi
archive=microdev-$architecture-$platform.tar.gz
work=$(mktemp -d "${TMPDIR:-/tmp}/microdev-install.XXXXXX")
staged=
cleanup() { rm -rf "$work"; if [ -n "$staged" ]; then rm -f "$staged"; fi; }
trap cleanup EXIT HUP INT TERM
fetch() { curl --proto '=https' --tlsv1.2 --fail --location --silent --show-error --connect-timeout 10 --max-time 180 "$1" -o "$2"; }
if [ "$version" = latest ]; then
    fetch "$base_url/latest/VERSION" "$work/VERSION" || fail 'Could not find the latest release. Visit https://microdev.dev/downloads'
    version=$(cat "$work/VERSION")
    case "$version" in ''|*[!a-zA-Z0-9._-]*|.*) fail 'Invalid release metadata' ;; esac
fi
printf 'Downloading MicroDev %s for %s…\n' "$version" "$architecture-$platform"
fetch "$base_url/$version/$archive" "$work/archive.tar.gz" || fail 'Download failed; no changes were made to your installation'
fetch "$base_url/$version/$archive.sha256" "$work/checksum" || fail 'Could not fetch the release checksum'
expected=$(awk -v name="$archive" 'NF == 2 && $2 == name { digest=$1; matches++ } END { if (NR == 1 && matches == 1) print digest }' "$work/checksum")
case "$expected" in ''|*[!0-9a-f]*) fail 'Invalid release checksum' ;; esac
[ "${#expected}" -eq 64 ] || fail 'Invalid release checksum'
if [ "$checksum_tool" = sha256sum ]; then actual=$(sha256sum "$work/archive.tar.gz" | awk '{print $1}')
else actual=$(shasum -a 256 "$work/archive.tar.gz" | awk '{print $1}'); fi
[ "$actual" = "$expected" ] || fail 'Checksum mismatch; the download was not installed'
[ "$(tar -tzf "$work/archive.tar.gz")" = microdev ] || fail 'Invalid release archive'
tar -xzf "$work/archive.tar.gz" -C "$work"
[ -f "$work/microdev" ] && [ ! -L "$work/microdev" ] || fail 'Invalid release executable'
mkdir -p "$bin_dir"
[ ! -d "$bin_dir/microdev" ] || fail "Cannot replace a directory at $bin_dir/microdev"
staged=$(mktemp "$bin_dir/.microdev.XXXXXX")
cp "$work/microdev" "$staged"
chmod 0755 "$staged"
mv -f "$staged" "$bin_dir/microdev"
staged=
printf '\nInstalled %s/microdev\n' "$bin_dir"
case ":${PATH:-}:" in
    *:"$bin_dir":*) printf '\nNext: microdev login\nThen: microdev demo\n' ;;
    *) printf '\nAdd %s to your shell PATH, then run:\n  microdev login\n  microdev demo\n' "$bin_dir"
       if [ "$bin_dir" = "$HOME/.local/bin" ]; then printf '\nFor this terminal: export PATH="$HOME/.local/bin:$PATH"\n'; fi ;;
esac
