#!/usr/bin/env bash
# vim:et:ts=2:sts=2:sw=2

# Get absolute repository root (especially when symlinked)
ROOT="$(realpath "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")")"

# Load accompanying bash library
source "$ROOT/lib/lib.bash"

# Configuration
UPLOAD=true
OUTPUT_DIR=""
VERSION=""

usage() {
  echo "Usage: $(basename "$0") [options] [VERSION]"
  echo "Builds and deploys a BETA release from the 'beta' branch."
  echo
  echo "Options:"
  echo "  -l, --local           Build locally, do not upload."
  echo "  -o, --output-dir DIR  Save build artifacts to a specific directory."
  echo "  -h, --help            Display this help and exit."
  exit 0
}

while [[ "$#" -gt 0 ]]; do
  case $1 in
    -l | --local)
      UPLOAD=false
      shift
      ;;
    -o | --output-dir)
      OUTPUT_DIR="$2"
      shift 2
      ;;
    -h | --help) usage ;;
    -*)
      err "Unknown option: $1"
      usage
      exit 1
      ;;
    *)
      VERSION="$1"
      shift
      ;;
  esac
done

set -e

CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$CURRENT_BRANCH" != "test" ]; then
  err "This script is only for deploying from the 'beta' branch."
  exit 1
fi

say "Confirming git status on 'beta' branch"
run git fetch

say "Checking dependencies"
for cmd in tar sha256sum rsync git; do
  if ! command -v "$cmd" &>/dev/null; then
    err "$cmd could not be found"
  fi
done

if [ "$UPLOAD" = true ]; then
  say "Checking SSH connection to bastion.techlitafrica.org"
  if ! ssh -q -o BatchMode=yes -o ConnectTimeout=5 admin@bastion.techlitafrica.org exit; then
    err "Cannot connect to admin@bastion.techlitafrica.org"
    exit 1
  fi
fi

LATEST_TAG=""
if [ -z "$VERSION" ]; then
  say "Auto-tagging beta version..."
  LATEST_TAG=$(git tag -l | sort -V | tail -n1)
      if [ -z "$LATEST_TAG" ]; then
        VERSION="0.1.0-beta-1"
      elif [[ "$LATEST_TAG" == *"-beta-"* ]]; then
        VERSION=$(echo "$LATEST_TAG" | awk -F'beta-' '{print $1"beta-"($2+1)}')
      else
        BASE_VERSION=$(echo "$LATEST_TAG" | awk -F. '{$NF = $NF + 1;} 1' | sed 's/ /./g')
        VERSION="$BASE_VERSION-beta-1"
      fi
  say "New beta version: $VERSION"
  run git tag "$VERSION" -m "Release $VERSION"
fi

# If a version was passed as an argument, find the previous tag for changelog generation
if [ -z "$LATEST_TAG" ]; then
  LATEST_TAG=$(git tag -l | sort -V | grep -B1 "$VERSION" | head -n1)
fi

if [ "$UPLOAD" = true ]; then
  say "Pushing new tag and commits to origin"
  run git push
  run git push --tags
fi

# Packaging
TMPDIR=$(mktemp -d)
trap 'rm -rf -- "$TMPDIR"' EXIT

PACKAGE_DIR="$TMPDIR/package"
ARCHIVE_FILE="$TMPDIR/v$VERSION.tar.gz"
CHECKSUM_FILE="$TMPDIR/v$VERSION.sha256"

say "Creating package for version $VERSION in $TMPDIR"
run mkdir -p "$PACKAGE_DIR"

# Archive repo contents directly into the working dir
say "Archiving repository content"
run git archive "$VERSION" | tar -x -C "$PACKAGE_DIR"

# Create changelog and version files
say "Generating changelog and version file"
echo "$VERSION" >"$PACKAGE_DIR/.version"
{
  echo "Version $VERSION"
  if [ -n "$LATEST_TAG" ]; then
    git --no-pager log --pretty=format:'''- %s (%an)''' "$LATEST_TAG..$VERSION"
  else
    git --no-pager log --pretty=format:'''- %s (%an)''' "$VERSION"
  fi
} >"$PACKAGE_DIR/.changelog"

say "Creating tarball and checksum"
run tar -czf "$ARCHIVE_FILE" -C "$PACKAGE_DIR" .

(cd "$TMPDIR" && sha256sum "v$VERSION.tar.gz" >"v$VERSION.sha256")

if [ "$UPLOAD" = true ]; then
  say "Uploading BETA release to bastion.techlitafrica.org"
  run rsync -avz "$ARCHIVE_FILE" "$CHECKSUM_FILE" "admin@bastion.techlitafrica.org:/srv/admin-beta/"
  say "Deployment of $VERSION complete."
else
  # For local builds, copy artifacts to a persistent directory
  if [ -n "$OUTPUT_DIR" ]; then
    DEST_DIR="$OUTPUT_DIR"
  else
    DEST_DIR="$ROOT/build/$VERSION"
  fi
  say "Local build complete. Copying artifacts to $DEST_DIR"
  run mkdir -p "$DEST_DIR"
  run cp "$ARCHIVE_FILE" "$CHECKSUM_FILE" "$DEST_DIR/"
  say "Artifacts are in $DEST_DIR"
fi
