#!/bin/sh
# mvirt installer — https://cli.mvirt.io
#
#   curl -fsSL https://cli.mvirt.io | sh
#
# The binaries live in the Forgejo generic package registry on git.malte.io; this script is the only
# thing cli.mvirt.io serves for the install path. That split is deliberate: the download origin is the
# git host, which is external to the mvirt cluster and therefore still reachable during exactly the
# outage where someone wants to install the CLI to go look at the cluster.
#
# Env knobs:
#   MVIRT_VERSION    version to install (default: latest)
#   MVIRT_INSTALL    install dir        (default: $HOME/.local/bin)
#   MVIRT_PKG_BASE   package registry   (default: the git.malte.io generic registry)
#   MVIRT_SKILL      install the Claude Code skill (default: 1; set 0 to skip)
#   MVIRT_SKILL_DIR  skill dir          (default: $HOME/.claude/skills/mvirt)
set -eu

PKG_BASE="${MVIRT_PKG_BASE:-https://git.malte.io/api/packages/mvirt/generic/mvirt-cli}"
VER="${MVIRT_VERSION:-latest}"
DEST="${MVIRT_INSTALL:-$HOME/.local/bin}"

err() { echo "mvirt-install: $*" >&2; exit 1; }

# ---- detect platform -> Rust target triple -------------------------------
OS="$(uname -s)"
ARCH="$(uname -m)"
case "$OS" in
  Linux)  case "$ARCH" in
            x86_64|amd64)          TRIPLE=x86_64-unknown-linux-musl ;;
            aarch64|arm64)         TRIPLE=aarch64-unknown-linux-musl ;;
            *) err "unsupported Linux arch: $ARCH" ;;
          esac ;;
  Darwin) case "$ARCH" in
            x86_64)                TRIPLE=x86_64-apple-darwin ;;
            arm64)                 TRIPLE=aarch64-apple-darwin ;;
            *) err "unsupported macOS arch: $ARCH" ;;
          esac ;;
  *) err "unsupported OS: $OS (Windows? use: irm https://cli.mvirt.io/install.ps1 | iex)" ;;
esac

# ---- download + checksum plumbing ----------------------------------------
have() { command -v "$1" >/dev/null 2>&1; }
have curl || have wget || err "need curl or wget"

TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
fetch() { # url dest
  if have curl; then curl -fsSL "$1" -o "$2"
  else wget -qO "$2" "$1"; fi
}
sha256_of() { # file
  if have sha256sum;  then sha256sum "$1" | awk '{print $1}'
  elif have shasum;   then shasum -a 256 "$1" | awk '{print $1}'
  else err "need sha256sum or shasum to verify"; fi
}

URL="$PKG_BASE/$VER/mvirt-$TRIPLE"
echo "mvirt-install: downloading $TRIPLE ($VER) ..."
fetch "$URL"        "$TMP/mvirt"        || err "download failed: $URL"
fetch "$URL.sha256" "$TMP/mvirt.sha256" || err "checksum download failed: $URL.sha256"
want="$(awk '{print $1}' "$TMP/mvirt.sha256")"
[ -n "$want" ] || err "empty checksum"
got="$(sha256_of "$TMP/mvirt")"
[ "$want" = "$got" ] || err "checksum mismatch (want $want, got $got)"

mkdir -p "$DEST"
chmod 0755 "$TMP/mvirt"
mv -f "$TMP/mvirt" "$DEST/mvirt"
echo "mvirt-install: installed -> $DEST/mvirt"
"$DEST/mvirt" --version 2>/dev/null || true

# ---- credential helper --------------------------------------------------
# Docker AND Podman exec `docker-credential-mvirt` from PATH for registry auth. It is the SAME
# binary — mvirt switches into credential-helper mode when invoked under that name (argv[0]).
# Expose it as a sibling symlink so both runtimes find it right after install.
ln -sf mvirt "$DEST/docker-credential-mvirt" 2>/dev/null \
  && echo "mvirt-install: linked docker-credential-mvirt -> mvirt" \
  || cp -f "$DEST/mvirt" "$DEST/docker-credential-mvirt"   # fallback if symlinks are unavailable

# ---- install the Claude Code skill (best-effort; opt out with MVIRT_SKILL=0) ----
# The skill is embedded in the binary, so it is always version-matched — we just ask
# the freshly installed mvirt to write it into ~/.claude/skills/mvirt/SKILL.md.
# Only done when Claude Code is actually present (a ~/.claude dir), unless the target
# dir is set explicitly (MVIRT_SKILL_DIR = opt-in regardless).
if [ "${MVIRT_SKILL:-1}" != "0" ]; then
  if [ -n "${MVIRT_SKILL_DIR:-}" ]; then
    "$DEST/mvirt" skill --install --dir "$MVIRT_SKILL_DIR" >/dev/null 2>&1 \
      && echo "mvirt-install: installed Claude Code skill -> $MVIRT_SKILL_DIR/SKILL.md" || true
  elif [ -d "$HOME/.claude" ]; then
    "$DEST/mvirt" skill --install >/dev/null 2>&1 \
      && echo "mvirt-install: installed Claude Code skill -> $HOME/.claude/skills/mvirt/SKILL.md" || true
  fi
fi

# ---- add to PATH (idempotent; picks the right rc for the user's shell) ----
add_to_path() {
  dir="$1"
  case ":$PATH:" in *":$dir:"*) return 0 ;; esac   # already effective

  line="export PATH=\"$dir:\$PATH\""
  case "$(basename "${SHELL:-sh}")" in
    zsh)  rc="${ZDOTDIR:-$HOME}/.zshrc" ;;
    bash) [ "$(uname -s)" = Darwin ] && rc="$HOME/.bash_profile" || rc="$HOME/.bashrc" ;;
    fish) rc="$HOME/.config/fish/config.fish"; line="fish_add_path \"$dir\"" ;;
    *)    rc="$HOME/.profile" ;;
  esac

  if [ -f "$rc" ] && grep -qF "$line" "$rc" 2>/dev/null; then
    return 0   # already added on a previous run
  fi
  mkdir -p "$(dirname "$rc")"
  printf '\n# added by mvirt-install (https://cli.mvirt.io)\n%s\n' "$line" >> "$rc"
  echo "mvirt-install: added $dir to PATH in $rc"
  echo "mvirt-install: restart your shell (or: exec \$SHELL) to use 'mvirt'"
}
add_to_path "$DEST"

echo "mvirt-install: done — next: mvirt login"
