#!/bin/sh
#
# Agentarivm installer.
#
#   curl -fsSL https://agentarivm.com/install.sh | sh
#
# Installs the Agentarivm manager for the current user:
#
#   ~/.local/share/agentarivm/versions/<version>/   the release (own Node
#                                                   runtime included — no
#                                                   system Node required)
#   ~/.local/bin/agentarivm                         symlink to it
#
# No sudo, ever. Safe to re-run: downloads are verified against their
# published sha256, the version directory is replaced atomically, and the
# symlink swap is atomic. Old versions are kept; upgrading is just running
# this installer again.
#
# Environment:
#   AGENTARIVM_VERSION   pin a version (e.g. 0.1.0) instead of the latest.
#
# POSIX sh — works under sh, bash and zsh.

set -eu

# AGENTARIVM_DOWNLOAD_BASE is an escape hatch for testing mirrors; users
# never need it.
DOWNLOAD_BASE="${AGENTARIVM_DOWNLOAD_BASE:-https://dl.agentarivm.com}"
SHARE_DIR="${HOME}/.local/share/agentarivm"
BIN_DIR="${HOME}/.local/bin"

say()  { printf '%s\n' "$*"; }
warn() { printf 'warning: %s\n' "$*" >&2; }
die()  { printf 'error: %s\n' "$*" >&2; exit 1; }

# ---------------------------------------------------------------------------
# Platform detection
# ---------------------------------------------------------------------------

os=$(uname -s)
case "$os" in
  Darwin) platform=darwin ;;
  Linux)  platform=linux ;;
  *)
    say "Agentarivm supports macOS and Linux."
    say "On Windows, install it inside WSL2 (it uses the Linux build):"
    say "  https://learn.microsoft.com/windows/wsl/install"
    exit 1
    ;;
esac

machine=$(uname -m)
case "$machine" in
  arm64 | aarch64) arch=arm64 ;;
  x86_64 | amd64)  arch=x64 ;;
  *) die "unsupported architecture: $machine (supported: arm64, x86_64)" ;;
esac
target="${platform}-${arch}"

command -v curl >/dev/null 2>&1 || die "curl is required to download Agentarivm"
command -v tar  >/dev/null 2>&1 || die "tar is required to extract Agentarivm"

# sha256 tooling differs by OS: shasum ships with macOS, sha256sum with linux.
if command -v sha256sum >/dev/null 2>&1; then
  checksum() { sha256sum "$1" | cut -d' ' -f1; }
elif command -v shasum >/dev/null 2>&1; then
  checksum() { shasum -a 256 "$1" | cut -d' ' -f1; }
else
  die "neither sha256sum nor shasum found; cannot verify the download"
fi

# ---------------------------------------------------------------------------
# Resolve version, url and expected sha256
# ---------------------------------------------------------------------------

tmp=$(mktemp -d "${TMPDIR:-/tmp}/agentarivm-install.XXXXXX")
trap 'rm -rf "$tmp"' EXIT INT TERM

if [ -n "${AGENTARIVM_VERSION:-}" ]; then
  # Pinned install: the URL scheme is stable, and every tarball has a .sha256
  # sibling, so the manifest is not needed.
  version=${AGENTARIVM_VERSION#v}
  tarball="agentarivm-v${version}-${target}.tar.gz"
  url="${DOWNLOAD_BASE}/releases/v${version}/${tarball}"
  say "Installing pinned Agentarivm v${version} (${target})"
  curl -fsSL "${url}.sha256" -o "$tmp/expected.sha256" ||
    die "could not fetch ${url}.sha256 — is v${version} a published release?"
  sha=$(cut -d' ' -f1 <"$tmp/expected.sha256")
else
  # Latest: one small manifest names the newest version and, per target, the
  # asset url and its sha256. Parsed with sed so the installer needs no jq;
  # the manifest is machine-generated by our release workflow, so its shape
  # is dependable. Whitespace is stripped first to be indentation-proof.
  say "Looking up the latest Agentarivm release..."
  curl -fsSL "${DOWNLOAD_BASE}/latest.json" -o "$tmp/latest.json" ||
    die "could not fetch ${DOWNLOAD_BASE}/latest.json"
  flat=$(tr -d ' \t\r\n' <"$tmp/latest.json")

  version=$(printf '%s' "$flat" | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')
  url=$(printf '%s' "$flat" |
    sed -n 's/.*"'"$target"'":{"url":"\([^"]*\)".*/\1/p')
  sha=$(printf '%s' "$flat" |
    sed -n 's/.*"'"$target"'":{"url":"[^"]*","sha256":"\([^"]*\)".*/\1/p')

  [ -n "$version" ] || die "could not read a version from latest.json"
  [ -n "$url" ] && [ -n "$sha" ] || die "latest.json has no asset for ${target}"
  tarball=$(basename "$url")
  say "Installing Agentarivm v${version} (${target})"
fi

case "$sha" in
  [0-9a-f][0-9a-f][0-9a-f][0-9a-f]*) : ;;
  *) die "published sha256 looks malformed: '$sha'" ;;
esac

# ---------------------------------------------------------------------------
# Download and verify
# ---------------------------------------------------------------------------

say "Downloading ${url}"
curl -fSL --progress-bar "$url" -o "$tmp/$tarball" || die "download failed"

actual=$(checksum "$tmp/$tarball")
if [ "$actual" != "$sha" ]; then
  die "sha256 mismatch for ${tarball}
  expected: ${sha}
  actual:   ${actual}
The download may be corrupt or tampered with. Nothing was installed."
fi
say "Checksum verified."

# ---------------------------------------------------------------------------
# Install: versions/<version>/ then an atomic symlink swap
# ---------------------------------------------------------------------------

version_dir="${SHARE_DIR}/versions/${version}"
mkdir -p "${SHARE_DIR}/versions" "$BIN_DIR"

# Extract in the temp dir first, so a half-extracted tree can never sit at the
# real path; the tarball's top-level agentarivm/ directory becomes versions/<v>.
tar -xzf "$tmp/$tarball" -C "$tmp"
[ -x "$tmp/agentarivm/bin/agentarivm" ] ||
  die "tarball did not contain agentarivm/bin/agentarivm"

# Re-running for an installed version replaces it (the symlink is re-pointed
# atomically below, so a concurrent `agentarivm` still resolves somewhere sane).
if [ -e "$version_dir" ]; then
  say "v${version} is already installed; replacing it."
  mv "$version_dir" "$tmp/replaced.$$"
fi
mv "$tmp/agentarivm" "$version_dir"

# An atomic swap: symlink to a scratch name, then rename over the real one.
# `ln -sf` alone deletes-then-creates, leaving a window with no binary at all.
ln -s "${version_dir}/bin/agentarivm" "$tmp/agentarivm-link"
mv -f "$tmp/agentarivm-link" "${BIN_DIR}/agentarivm"

say ""
say "Installed: ${version_dir}"
say "Command:   ${BIN_DIR}/agentarivm"

# Older versions stay on disk under versions/ so a broken upgrade can be
# undone by re-pointing the symlink; delete them whenever you like.

# ---------------------------------------------------------------------------
# PATH check + next steps
# ---------------------------------------------------------------------------

case ":${PATH}:" in
  *":${BIN_DIR}:"*) : ;;
  *)
    warn "${BIN_DIR} is not on your PATH."
    say  "Add it to your shell profile (~/.zshrc, ~/.bashrc, ...):"
    # The unexpanded $HOME is the point: it is the exact line the user
    # should paste into their profile.
    # shellcheck disable=SC2016
    say  '  export PATH="$HOME/.local/bin:$PATH"'
    ;;
esac

say ""
say "Next steps:"
say "  1. Run:  agentarivm init            # write a starter config, then edit it"
say "  2. Make sure the tools Agentarivm drives are installed:"
say "     git, gh (GitHub CLI), claude (Claude Code)"
say "  3. Run:  agentarivm doctor          # checks this machine end to end"
say "  4. Run:  agentarivm service install # start the manager as a service"
say ""
say "To upgrade later, just run this installer again."
