#!/usr/bin/env bash
set -euo pipefail

version=2.4.68-0ubuntu20.04.3
bundle_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
state_dir=/var/lib/apache2-offline-upgrade
timestamp=$(date +%Y%m%d-%H%M%S)
backup_dir="/var/backups/apache2-before-${version}-${timestamp}"
repo_dir="$bundle_dir/repo"
repo_list=/etc/apt/sources.list.d/apache2-offline-upgrade.list
export DEBIAN_FRONTEND=noninteractive

service_stop() {
  [ "${APACHE_OFFLINE_SKIP_SYSTEMD:-0}" = 1 ] || systemctl stop apache2
}
service_start_and_check() {
  if [ "${APACHE_OFFLINE_SKIP_SYSTEMD:-0}" != 1 ]; then
    systemctl start apache2
    systemctl is-active --quiet apache2
  fi
}
apt_local() {
  apt-get \
    -o Dir::Etc::sourcelist="$repo_list" \
    -o Dir::Etc::sourceparts="-" \
    -o APT::Get::List-Cleanup=0 \
    "$@"
}
prepare_repo() {
  case "$repo_dir" in
    *[[:space:]]*) echo "ERROR: move the bundle to a path without spaces" >&2; return 1 ;;
  esac
  printf 'deb [trusted=yes] file:%s ./\n' "$repo_dir" > "$repo_list"
  apt_local update
}
cleanup_repo() {
  rm -f "$repo_list"
}

if [ "$(id -u)" -ne 0 ]; then
  echo "ERROR: run with sudo: sudo ./install.sh" >&2
  exit 1
fi
if [ "$(dpkg --print-architecture)" != amd64 ]; then
  echo "ERROR: this bundle only supports amd64" >&2
  exit 1
fi
if ! grep -q '^VERSION_ID="20.04"' /etc/os-release; then
  echo "ERROR: this bundle only supports Ubuntu 20.04" >&2
  exit 1
fi

cd "$bundle_dir"
sha256sum -c SHA256SUMS
if ! apache2ctl configtest; then
  echo "WARNING: current Apache configuration is already failing; continuing with backup and repair upgrade" >&2
fi

mkdir -p "$backup_dir" "$state_dir"
tar -C / -czpf "$backup_dir/etc-apache2.tar.gz" etc/apache2
dpkg-query -W -f='${binary:Package}\t${Version}\n' 'apache2*' 'libapache2-mod-*' \
  > "$backup_dir/packages.tsv" 2>/dev/null || true
systemctl is-enabled apache2 > "$backup_dir/service-enabled" 2>/dev/null || true
printf '%s\n' "$backup_dir" > "$state_dir/last-backup"

rollback_on_error() {
  rc=$?
  trap - ERR
  echo "ERROR: upgrade failed; restoring Focal packages and saved configuration" >&2
  cleanup_repo
  "$bundle_dir/rollback.sh" "$backup_dir" || true
  exit "$rc"
}
trap rollback_on_error ERR

service_stop
prepare_repo
apt_local \
  -o Dpkg::Options::=--force-confold \
  --allow-downgrades -y install \
  "apache2-bin=$version" \
  "apache2-data=$version" \
  "apache2-utils=$version" \
  "apache2=$version"

test "$(dpkg-query -W -f='${Version}' apache2)" = "$version"
apache2ctl -V 2>&1 | grep -F 'HTTPD_ROOT="/etc/apache2"'
apache2ctl configtest
service_start_and_check
cleanup_repo
trap - ERR

echo "OK: Apache upgraded to $version"
echo "Backup: $backup_dir"
