#!/usr/bin/env sh
set -eu

REPOSITORY="${BOAT_REPOSITORY:-young-kwng/BOAT-annotation-tool}"
CHANNEL="${BOAT_CHANNEL:-stable}"
INSTALL_DIR="${BOAT_INSTALL_DIR:-$HOME/.local/bin}"

fail() { printf 'BOAT installer: %s\n' "$*" >&2; exit 1; }
command -v curl >/dev/null 2>&1 || fail "curl is required"
SYSTEM="$(uname -s)"
MACHINE="$(uname -m)"
case "${SYSTEM}/${MACHINE}" in
  Linux/x86_64)
    command -v sha256sum >/dev/null 2>&1 || fail "sha256sum is required"
    [ -r /etc/os-release ] || fail "cannot identify the Linux distribution"
    . /etc/os-release
    [ "${ID:-}" = "ubuntu" ] || fail "v1 supports Ubuntu only (detected ${ID:-unknown})"
    case "${VERSION_ID:-}" in
      22.04|24.04) ;;
      *) fail "v1 supports Ubuntu 22.04 or 24.04 (detected ${VERSION_ID:-unknown})" ;;
    esac
    PLATFORM="linux_amd64"
    ;;
  Darwin/arm64)
    command -v shasum >/dev/null 2>&1 || fail "shasum is required"
    PLATFORM="darwin_arm64"
    ;;
  *) fail "v1 supports Ubuntu 22.04/24.04 on x86_64 and macOS on Apple silicon (detected ${SYSTEM}/${MACHINE})" ;;
esac

if [ -n "${BOAT_VERSION:-}" ]; then
  VERSION="${BOAT_VERSION#v}"
else
  if [ "$CHANNEL" = "beta" ]; then
    API_URL="https://api.github.com/repos/${REPOSITORY}/releases?per_page=20"
    VERSION="$(curl -fsSL --proto '=https' --tlsv1.2 "$API_URL" | awk -F'"' '/"tag_name":/{tag=$4} /"prerelease": true/{sub(/^v/, "", tag); print tag; exit}')"
  else
    API_URL="https://api.github.com/repos/${REPOSITORY}/releases/latest"
    VERSION="$(curl -fsSL --proto '=https' --tlsv1.2 "$API_URL" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"v\{0,1\}\([^"]*\)".*/\1/p' | head -n 1)"
  fi
  [ -n "$VERSION" ] || fail "could not determine the latest release"
fi

BASE_URL="https://github.com/${REPOSITORY}/releases/download/v${VERSION}"
ASSET="boat_${VERSION}_${PLATFORM}.tar.gz"
TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/boat-install.XXXXXX")"
trap 'rm -rf "$TMP_DIR"' EXIT HUP INT TERM

printf 'Downloading BOAT %s…\n' "$VERSION"
curl -fL --proto '=https' --tlsv1.2 "${BASE_URL}/${ASSET}" -o "$TMP_DIR/$ASSET"
curl -fsSL --proto '=https' --tlsv1.2 "${BASE_URL}/${ASSET}.sha256" -o "$TMP_DIR/$ASSET.sha256"
if [ "$SYSTEM" = "Darwin" ]; then
  (cd "$TMP_DIR" && shasum -a 256 -c "$ASSET.sha256") || fail "checksum verification failed"
else
  (cd "$TMP_DIR" && sha256sum -c "$ASSET.sha256") || fail "checksum verification failed"
fi

MEMBERS="$(tar -tzf "$TMP_DIR/$ASSET")"
[ "$MEMBERS" = "boat
cosign" ] || [ "$MEMBERS" = "cosign
boat" ] || fail "release archive contains unexpected paths"
tar -xzf "$TMP_DIR/$ASSET" -C "$TMP_DIR"
[ -x "$TMP_DIR/boat" ] || fail "release archive does not contain the boat binary"
[ -x "$TMP_DIR/cosign" ] || fail "release archive does not contain the signature verifier"
COSIGN_BIN="$TMP_DIR/cosign"
if command -v cosign >/dev/null 2>&1; then COSIGN_BIN="$(command -v cosign)"; fi
curl -fsSL --proto '=https' --tlsv1.2 "${BASE_URL}/${ASSET}.sigstore.json" -o "$TMP_DIR/$ASSET.sigstore.json"
"$COSIGN_BIN" verify-blob "$TMP_DIR/$ASSET" \
  --bundle "$TMP_DIR/$ASSET.sigstore.json" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  --certificate-identity-regexp "^https://github.com/${REPOSITORY}/.github/workflows/release.yml@refs/(tags/v.*|heads/main)$" >/dev/null || fail "release signature verification failed"
mkdir -p "$INSTALL_DIR"
cp "$TMP_DIR/boat" "$INSTALL_DIR/boat.new"
chmod 755 "$INSTALL_DIR/boat.new"
mv "$INSTALL_DIR/boat.new" "$INSTALL_DIR/boat"
TOOLS_DIR="${BOAT_HOME:-${XDG_DATA_HOME:-$HOME/.local/share}/boat}/tools"
mkdir -p "$TOOLS_DIR"
cp "$TMP_DIR/cosign" "$TOOLS_DIR/cosign.new"
chmod 755 "$TOOLS_DIR/cosign.new"
mv "$TOOLS_DIR/cosign.new" "$TOOLS_DIR/cosign"

printf '\nBOAT CLI installed at %s/boat\n' "$INSTALL_DIR"
case ":$PATH:" in
  *":$INSTALL_DIR:"*) printf 'Run: boat setup  (optional)\n     boat start\n' ;;
  *) printf 'Add it to this shell, then start BOAT:\n  export PATH="%s:$PATH"\n  boat start\n' "$INSTALL_DIR" ;;
esac
