#!/usr/bin/env bash
# Download, verify and install Growbud Edge Server (Linux and macOS).
#
#   curl -fsSL https://growbud.io/edge/install.sh | sudo bash
#   curl -fsSL https://growbud.io/edge/install.sh | sudo bash -s -- --admin-email you@example.com
#
# Every argument goes to the bundle's install.sh (README section 3). Run it
# again to upgrade: the bundle is extracted over the install folder, and .env
# and the volumes are kept.
#
# Environment:
#   GROWBUD_EDGE_VERSION   install this version instead of the latest
#   GROWBUD_EDGE_DIR       install folder (default /opt/growbud-edge)
#   GROWBUD_EDGE_BASE_URL  download site (default https://growbud.io/edge)
#
# The bundle must match the SHA-256 the download site lists. When cosign is
# installed, its keyless signature must also come from the Growbud release
# workflow. Nothing is extracted until both checks pass.
set -euo pipefail

BASE_URL="${GROWBUD_EDGE_BASE_URL:-https://growbud.io/edge}"
INSTALL_DIR="${GROWBUD_EDGE_DIR:-/opt/growbud-edge}"
VERSION="${GROWBUD_EDGE_VERSION:-}"
SIGNER='^https://github\.com/growbud-io/edge/\.github/workflows/release\.yml@refs/heads/main$'

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

[ "$(id -u)" = 0 ] || fail "Run as root: curl -fsSL $BASE_URL/install.sh | sudo bash"
command -v curl >/dev/null 2>&1 || fail "curl is not installed."
command -v tar >/dev/null 2>&1 || fail "tar is not installed."
if ! command -v docker >/dev/null 2>&1; then
    fail "Docker is not installed. Install Docker Engine (Linux) or Docker Desktop (macOS): https://docs.docker.com/engine/install/ Then run this again."
fi
docker compose version >/dev/null 2>&1 \
    || fail "Docker Compose v2 is not installed. Install the docker-compose-plugin package."

sha256() {
    if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d' ' -f1
    else shasum -a 256 "$1" | cut -d' ' -f1; fi
}

if [ -z "$VERSION" ]; then
    say "Finding the latest version"
    VERSION="$(curl -fsSL "$BASE_URL/latest.json" | sed -n 's/.*"version" *: *"\([^"]*\)".*/\1/p' | head -n 1)"
    [ -n "$VERSION" ] || fail "Could not read $BASE_URL/latest.json"
fi
case "$VERSION" in
    *[!0-9A-Za-z.-]*|'') fail "Invalid version: $VERSION" ;;
esac

NAME="growbud-edge-$VERSION"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT

say "Downloading Growbud Edge $VERSION"
for file in "$NAME.tar.gz" "$NAME.tar.gz.sha256" "$NAME.tar.gz.cosign.bundle"; do
    curl -fsSL --retry 3 -o "$WORK/$file" "$BASE_URL/download/$VERSION/$file" \
        || fail "Could not download $BASE_URL/download/$VERSION/$file"
done

say "Verifying the download"
want="$(cut -d' ' -f1 < "$WORK/$NAME.tar.gz.sha256")"
got="$(sha256 "$WORK/$NAME.tar.gz")"
[ -n "$want" ] && [ "$want" = "$got" ] || fail "SHA-256 mismatch: expected $want, got $got. Nothing was installed."
echo "SHA-256 OK"
if command -v cosign >/dev/null 2>&1; then
    cosign verify-blob \
        --bundle "$WORK/$NAME.tar.gz.cosign.bundle" \
        --certificate-identity-regexp "$SIGNER" \
        --certificate-oidc-issuer https://token.actions.githubusercontent.com \
        "$WORK/$NAME.tar.gz" >/dev/null 2>&1 \
        || fail "The signature does not come from the Growbud release workflow. Nothing was installed."
    echo "Signature OK"
else
    echo "cosign is not installed: the signature was not checked (README section 3)."
fi

say "Extracting to $INSTALL_DIR"
mkdir -p "$INSTALL_DIR/bundles"
tar -xzf "$WORK/$NAME.tar.gz" -C "$INSTALL_DIR" --strip-components=1
# Keep each bundle: a rollback needs the one you ran before (README section 8).
cp "$WORK/$NAME.tar.gz" "$WORK/$NAME.tar.gz.cosign.bundle" "$INSTALL_DIR/bundles/"
chmod 700 "$INSTALL_DIR/bundles"
# exec below skips the EXIT trap, so clean up now.
rm -rf "$WORK"
trap - EXIT

say "Running the installer"
cd "$INSTALL_DIR"
# Piped through bash, stdin is this script. Give the installer the terminal
# so it can ask for the administrator email.
if [ -t 1 ] && { : < /dev/tty; } 2>/dev/null; then
    exec ./install.sh "$@" < /dev/tty
fi
exec ./install.sh "$@"
