#!/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 ---
# Default values
UPLOAD=true
TAG=true
OUTPUT_DIR=""
VERSION_ARG=""

usage() {
  echo "Usage: $(basename "$0") [options] [VERSION]"
  echo "Builds and deploys the admin repository."
  echo
  echo "Options:"
  echo "  -l, --local           Build locally, do not upload. Artifacts are saved to './build/<version>' by default."
  echo "      --no-tag          Do not create a new git tag for the build (used for local builds)."
  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
      ;;
    --no-tag)
      TAG=false
      shift
      ;;
    -o | --output-dir)
      OUTPUT_DIR="$2"
      shift 2
      ;;
    -h | --help) usage ;;
    -*)
      err "Unknown option: $1"
      usage
      exit 1
      ;;
    *)
      VERSION_ARG="$1"
      shift
      ;;
  esac
done

set -e

# Check git status
say "Confirming git status"
run git fetch
if [ "$UPLOAD" = true ] && git status -sb | grep -q 'behind'; then
  say "Pulling changes from upstream..."
  run git pull
fi

# Check dependencies
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

# Confirm SSH access
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

# Versioning
VERSION="$VERSION_ARG"
if [ -z "$VERSION" ]; then
  if [ "$TAG" = true ]; then
    say "No tag provided, auto-tagging..."
    LATEST_TAG=$(git tag -l | sort -V | tail -n1)
    if [ -z "$LATEST_TAG" ]; then
      VERSION="0.1.0"
    else
      VERSION=$(echo "$LATEST_TAG" | awk -F. '''{$NF = $NF + 1;} 1''' | sed '''s/ /./g''')
    fi
    say "New version: $VERSION"
    run git tag "$VERSION" -m "Release $VERSION"
    if [ "$UPLOAD" = true ]; then
      say "Pushing new tag to origin"
      run git push
      run git push --tags
    fi
  else
    VERSION="dev-$(git rev-parse --short HEAD)"
    say "Using dev version: $VERSION"
    LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
  fi
else
  say "Using provided tag: $VERSION"
  if ! git rev-parse "$VERSION" >/dev/null 2>&1; then
    err "Tag $VERSION not found locally. Make sure to fetch tags."
  fi
  LATEST_TAG=$(git tag -l | sort -V | grep -B1 "$VERSION" | head -n1)
fi

# Create tarball in a temporary directory
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")

# --- Artifact Handling ---
if [ "$UPLOAD" = true ]; then
  say "Uploading release to bastion.techlitafrica.org"
  run rsync -avz "$ARCHIVE_FILE" "$CHECKSUM_FILE" "admin@bastion.techlitafrica.org:/srv/admin/"
  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
