#!/bin/sh
# zima installer - https://cli.zimaos.com
#
# Usage:
#   curl -fsSL https://cli.zimaos.com/install.sh | sh
#
# Environment overrides:
#   ZIMA_VERSION      install a specific version, e.g. v0.1.3
#                        (default: the portal's dl/latest.txt)
#   ZIMA_BASE         primary download base (default: https://cli.zimaos.com)
#   ZIMA_MIRROR       fallback base for the release archive, tried when the
#                        primary fails (default: the OSS Shanghai mirror, so
#                        downloads stay fast inside mainland China where the
#                        Cloudflare-fronted primary can be slow)
#   ZIMA_INSTALL_DIR  target directory (default: first writable of
#                        /usr/local/bin, /DATA/local/bin, ~/.local/bin -
#                        ZimaOS has a read-only rootfs, /DATA persists)
#
# The script detects OS/arch, downloads the release archive (primary first,
# then mirror), verifies its sha256 against checksums.txt, and installs the
# zima binary.

set -eu

BASE="${ZIMA_BASE:-https://cli.zimaos.com}"
# The version pointer is tiny, so it always comes from the primary; only the
# large archive falls back to the mirror. The mirror's path layout differs
# (GitHub-release style), so it is templated separately below.
MIRROR="${ZIMA_MIRROR:-https://casaos.oss-cn-shanghai.aliyuncs.com/IceWhaleTech/ZimaOS-CLI/releases/download}"

say() { printf '%s\n' "$*"; }
fail() {
  printf 'install.sh: %s\n' "$*" >&2
  exit 1
}

command -v curl >/dev/null 2>&1 || fail "curl is required"
command -v tar >/dev/null 2>&1 || fail "tar is required"

# ── detect platform ──────────────────────────────────────────────────
case "$(uname -s)" in
Linux) os="linux" ;;
Darwin) os="darwin" ;;
*) fail "unsupported OS: $(uname -s) (linux and macOS only)" ;;
esac

case "$(uname -m)" in
x86_64 | amd64) arch="amd64" ;;
aarch64 | arm64) arch="arm64" ;;
*) fail "unsupported architecture: $(uname -m) (amd64 and arm64 only)" ;;
esac

# ── resolve version ──────────────────────────────────────────────────
version="${ZIMA_VERSION:-}"
if [ -z "$version" ]; then
  version="$(curl -fsSL "$BASE/dl/latest.txt" 2>/dev/null | tr -d '[:space:]')" ||
    fail "cannot resolve the latest version from $BASE/dl/latest.txt"
fi
case "$version" in
v*) ;;
*) version="v$version" ;;
esac

archive="${os}-${arch}-zima-${version}.tar.gz"

say "Installing zima $version ($os/$arch)"
say "  from $BASE (mirror: $MIRROR)"

# fetch <primary_url> <mirror_url> <out>: download from the primary, and on
# any failure retry from the mirror. An empty mirror URL disables fallback.
fetch() {
  if curl -fSL --progress-bar "$1" -o "$3"; then
    return 0
  fi
  [ -n "$2" ] || return 1
  say "  primary source failed, retrying from mirror"
  curl -fSL --progress-bar "$2" -o "$3"
}

# ── download and verify ──────────────────────────────────────────────
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT INT TERM

fetch "$BASE/dl/$version/$archive" "$MIRROR/$version/$archive" "$tmp/$archive" ||
  fail "download failed: $archive"
fetch "$BASE/dl/$version/checksums.txt" "$MIRROR/$version/checksums.txt" "$tmp/checksums.txt" ||
  fail "download failed: checksums.txt"

expected="$(awk -v f="$archive" '$2 == f { print $1 }' "$tmp/checksums.txt")"
[ -n "$expected" ] || fail "no checksum entry for $archive"

if command -v sha256sum >/dev/null 2>&1; then
  actual="$(sha256sum "$tmp/$archive" | awk '{print $1}')"
else
  actual="$(shasum -a 256 "$tmp/$archive" | awk '{print $1}')"
fi
[ "$actual" = "$expected" ] ||
  fail "sha256 mismatch for $archive
  expected: $expected
  actual:   $actual"
say "  sha256 OK"

# ── install ──────────────────────────────────────────────────────────
tar -xzf "$tmp/$archive" -C "$tmp"
binary="$tmp/build/sysroot/usr/bin/zima"
[ -x "$binary" ] || fail "archive layout unexpected: zima binary not found"

# try_install <dir> [sudo] - best-effort: a read-only filesystem (ZimaOS
# squashfs rootfs) fails mkdir/install even as root, so failures fall
# through to the next candidate instead of aborting.
try_install() {
  dir="$1" use_sudo="${2:-}"
  $use_sudo mkdir -p "$dir" 2>/dev/null || return 1
  $use_sudo install -m 0755 "$binary" "$dir/zima" 2>/dev/null || return 1
  INSTALL_DIR="$dir"
  return 0
}

installed=""
if [ -n "${ZIMA_INSTALL_DIR:-}" ]; then
  if [ -w "$ZIMA_INSTALL_DIR" ] || [ ! -e "$ZIMA_INSTALL_DIR" ]; then
    try_install "$ZIMA_INSTALL_DIR" && installed=1
  fi
  if [ -z "$installed" ] && command -v sudo >/dev/null 2>&1; then
    try_install "$ZIMA_INSTALL_DIR" sudo && installed=1
  fi
  [ -n "$installed" ] || fail "cannot install to $ZIMA_INSTALL_DIR"
else
  sudo=""
  command -v sudo >/dev/null 2>&1 && sudo="sudo"
  # /usr/local/bin: the conventional prefix on stock linux/macOS.
  # /DATA/local/bin: ZimaOS - rootfs is read-only squashfs, /DATA persists.
  # ~/.local/bin: last resort, never needs privileges.
  for candidate in /usr/local/bin /DATA/local/bin "$HOME/.local/bin"; do
    case "$candidate" in
    /DATA/*) [ -d /DATA ] || continue ;;
    esac
    if try_install "$candidate"; then
      installed=1
      break
    fi
    if [ -n "$sudo" ] && [ "$candidate" != "$HOME/.local/bin" ]; then
      if try_install "$candidate" "$sudo"; then
        installed=1
        break
      fi
    fi
  done
  [ -n "$installed" ] || fail "no writable install directory found
  re-run with ZIMA_INSTALL_DIR=<dir>"
fi

say ""
say "Installed: $INSTALL_DIR/zima"
"$INSTALL_DIR/zima" -v || true

case ":$PATH:" in
*:"$INSTALL_DIR":*) ;;
*)
  # Best-effort PATH wiring for shells that source /etc/profile.d (the
  # fanctl prototype used the same trick on ZimaOS); otherwise just hint.
  profiled_written=""
  if [ -d /etc/profile.d ] && [ -w /etc/profile.d ]; then
    printf 'export PATH="$PATH:%s"\n' "$INSTALL_DIR" \
      >/etc/profile.d/zima-path.sh 2>/dev/null && profiled_written=1
  fi
  say ""
  if [ -n "$profiled_written" ]; then
    say "PATH updated via /etc/profile.d/zima-path.sh - re-login, or run:"
  else
    say "$INSTALL_DIR is not on PATH - add it, or run:"
  fi
  say "  export PATH=\"\$PATH:$INSTALL_DIR\""
  ;;
esac

say ""
say "Next: on a ZimaOS machine just run \"zima device ls\";"
say "      for a remote device run \"zima auth login <address>\" first."
