#!/bin/sh
# Uno CLI installer.
#
#   curl -fsSL https://console.uno4.dev/install.sh | sh
#
# Puts the `uno` binary in /usr/local/bin, or in ~/.local/bin when that is not
# writable. English on purpose: this URL is public and agents read it too.
#
# Every expansion is braced. An unbraced "$arch" followed by a non-ASCII byte
# is parsed as part of the variable NAME in 8-bit locales, and with `set -u`
# the script died on line 37 with "arch<?>: unbound variable", reported from
# macOS 15. For the same reason there is no non-ASCII character anywhere here.
set -eu

BASE="${UNO_CLI_BASE:-https://console.uno4.dev/cli}"

if ! command -v curl >/dev/null 2>&1; then
  echo "uno: curl is required to install" >&2
  exit 1
fi

os=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m)
case "${arch}" in
  x86_64|amd64) arch=amd64 ;;
  aarch64|arm64) arch=arm64 ;;
  *) echo "uno: unsupported architecture ${arch}" >&2; exit 1 ;;
esac
case "${os}" in
  linux|darwin) ;;
  *) echo "uno: unsupported OS ${os} (linux and macOS are available)" >&2; exit 1 ;;
esac

dest=/usr/local/bin
if [ ! -w "${dest}" ]; then
  if command -v sudo >/dev/null 2>&1 && [ -t 0 ]; then
    SUDO=sudo
  else
    dest="${HOME}/.local/bin"
    mkdir -p "${dest}"
    SUDO=""
  fi
else
  SUDO=""
fi

tmp=$(mktemp)
sums=$(mktemp)
trap 'rm -f "${tmp}" "${sums}"' EXIT

echo "uno: downloading ${os}/${arch}..."
curl -fsSL "${BASE}/uno-${os}-${arch}" -o "${tmp}"

# Magic-byte check, before anything is installed and before the checksum.
#
# This exists because the console is a SPA served with a fallback to
# index.html: a missing /cli/uno-linux-amd64 came back as HTTP 200 with an
# HTML body, curl -f saw success, and we happily chmod +x'd a web page into
# /usr/local/bin. A checksum would also catch that, but only with a confusing
# "checksum mismatch" -- and the checksum file lives behind the same broken
# fallback, so it cannot be the only guard. The magic check is therefore
# mandatory and never skipped.
#
# od is POSIX; xxd is not (and is missing on stock macOS shells).
magic=$(od -A n -t x1 -N 4 "${tmp}" 2>/dev/null | tr -d ' \n' || true)
case "${os}" in
  # 7f 45 4c 46 = "\x7fELF".
  linux) want_magic="7f454c46" ;;
  # cffaedfe = Mach-O 64-bit, little-endian (MH_MAGIC_64 on disk).
  # cafebabe = universal ("fat") binary wrapping several architectures.
  darwin) want_magic="cffaedfe cafebabe" ;;
esac

magic_ok=no
for want in ${want_magic}; do
  if [ "${magic}" = "${want}" ]; then
    magic_ok=yes
  fi
done

if [ "${magic_ok}" != "yes" ]; then
  case "${magic}" in
    3c*)
      echo "uno: downloaded file is not a binary (got HTML?) - the download endpoint may be misconfigured, report to hello@uno4.dev" >&2
      ;;
    *)
      echo "uno: downloaded file is not a binary (unexpected header ${magic}) - the download endpoint may be misconfigured, report to hello@uno4.dev" >&2
      ;;
  esac
  exit 1
fi

# Checksum, for integrity rather than for the HTML case above. A missing
# SHA256SUMS must not be fatal: older release directories predate it, and
# failing shut there would leave users unable to install at all.
if command -v sha256sum >/dev/null 2>&1; then
  sha_cmd="sha256sum"
elif command -v shasum >/dev/null 2>&1; then
  sha_cmd="shasum -a 256"
else
  sha_cmd=""
fi

if [ -z "${sha_cmd}" ]; then
  echo "uno: warning: no sha256sum/shasum available, skipping checksum verification" >&2
elif ! curl -fsSL "${BASE}/SHA256SUMS" -o "${sums}" 2>/dev/null; then
  echo "uno: warning: SHA256SUMS not available, skipping checksum verification" >&2
else
  expected=$(awk -v f="uno-${os}-${arch}" '$2 == f || $2 == "*"f {print $1; exit}' "${sums}" || true)
  actual=$(${sha_cmd} "${tmp}" | awk '{print $1}' || true)
  if [ -z "${expected}" ]; then
    echo "uno: warning: no checksum listed for uno-${os}-${arch}, skipping verification" >&2
  elif [ "${expected}" != "${actual}" ]; then
    echo "uno: checksum mismatch for uno-${os}-${arch}" >&2
    echo "uno:   expected ${expected}" >&2
    echo "uno:   actual   ${actual}" >&2
    echo "uno: refusing to install, report to hello@uno4.dev" >&2
    exit 1
  fi
fi

chmod +x "${tmp}"
${SUDO} mv "${tmp}" "${dest}/uno"

echo "uno: installed at ${dest}/uno"
case ":${PATH}:" in
  *":${dest}:"*) ;;
  *) echo "uno: add it to PATH:  export PATH=\"${dest}:\$PATH\"" ;;
esac

cat <<'EOF'

Next:
  export UNO_API_URL=https://console.uno4.dev
  export UNO_TOKEN=<your api_key from the console>
  uno whoami

Full instructions for an agent: https://console.uno4.dev/llms.txt
EOF
