#!/usr/bin/env bash
# install-libreoffice.sh — Install the latest stable LibreOffice from documentfoundation.org.
# Hardened: arch detection, version JSON when available with HTML fallback, MD5 verification,
# uninstalls bundled distro libreoffice* first to avoid conflicts, --dry-run.

set -euo pipefail
IFS=$'\n\t'

readonly SCRIPT_NAME="${0##*/}"
DRY_RUN=0
SKIP_REMOVE_DISTRO=0

usage() {
  cat <<EOF
Usage: sudo $SCRIPT_NAME [--dry-run] [--keep-distro-libreoffice] [--help]

Detects the latest stable LibreOffice version on download.documentfoundation.org,
downloads the matching DEB tarball for your architecture, verifies the MD5 sum
published alongside it, and installs the .deb packages.

Options:
  --keep-distro-libreoffice  Don't purge any pre-installed distro libreoffice*
                             (default: purge to avoid library conflicts).
  --dry-run                  Print actions without executing.
  --help, -h                 Show this help.
EOF
}

log()  { printf '\033[1;34m[%s]\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*"; }
warn() { printf '\033[1;33m[%s] WARN:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; }
die()  { printf '\033[1;31m[%s] ERROR:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; exit 1; }
run()  { if (( DRY_RUN )); then printf '  DRY-RUN: %s\n' "$*"; else eval "$@"; fi; }
trap 'rc=$?; (( rc )) && printf "\033[1;31m[%s] failed at line %s (exit %d)\033[0m\n" "${SCRIPT_NAME%.sh}" "$LINENO" "$rc" >&2' ERR

while (( $# )); do
  case "$1" in
    --dry-run)                  DRY_RUN=1 ;;
    --keep-distro-libreoffice)  SKIP_REMOVE_DISTRO=1 ;;
    -h|--help)                  usage; exit 0 ;;
    *) die "Unknown argument: $1 (try --help)" ;;
  esac
  shift
done

(( EUID == 0 )) || die "Must run as root. Try: sudo $SCRIPT_NAME"

[[ -r /etc/os-release ]] || die "/etc/os-release not found."
# shellcheck disable=SC1091
. /etc/os-release
case "${ID:-}:${ID_LIKE:-}" in
  *ubuntu*|*debian*) : ;;
  *) die "Unsupported distro: ${PRETTY_NAME:-unknown} (this script installs .deb packages)." ;;
esac

ARCH_RAW="$(uname -m)"
case "$ARCH_RAW" in
  x86_64)  LO_ARCH=x86_64; LO_SUFFIX=Linux_x86-64 ;;
  aarch64) LO_ARCH=aarch64; LO_SUFFIX=Linux_aarch64 ;;
  *) die "Unsupported architecture: $ARCH_RAW (LibreOffice ships x86_64 and aarch64)." ;;
esac
log "Detected: ${PRETTY_NAME:-unknown}, arch: $ARCH_RAW"

export DEBIAN_FRONTEND=noninteractive

log "Installing prerequisites..."
run "apt-get update -qq"
run "apt-get install -y curl wget tar coreutils ca-certificates"

log "Resolving latest stable LibreOffice version..."
INDEX="$(curl -fsSL https://download.documentfoundation.org/libreoffice/stable/)"
LATEST_VERSION="$(printf '%s\n' "$INDEX" \
  | grep -oP '(?<=href=")[0-9]+\.[0-9]+\.[0-9]+(?=/")' \
  | sort -V | tail -1 || true)"
[[ -n "$LATEST_VERSION" ]] || die "Could not detect latest version from index page."
log "Latest stable: $LATEST_VERSION"

BASE="https://download.documentfoundation.org/libreoffice/stable/${LATEST_VERSION}/deb/${LO_ARCH}"
ARCHIVE_NAME="LibreOffice_${LATEST_VERSION}_${LO_SUFFIX}_deb.tar.gz"
URL="${BASE}/${ARCHIVE_NAME}"
SUM_URL="${URL}.md5"

STAGE="$(mktemp -d -t lo.XXXXXX)"
trap 'rm -rf "$STAGE"' EXIT
ARCHIVE="$STAGE/$ARCHIVE_NAME"

log "Downloading $ARCHIVE_NAME..."
run "wget -q --show-progress -O '$ARCHIVE' '$URL'"

log "Verifying MD5..."
if EXPECTED_MD5="$(curl -fsSL "$SUM_URL" 2>/dev/null | awk '{print $1}')" && [[ -n "$EXPECTED_MD5" ]]; then
  ACTUAL_MD5="$(md5sum "$ARCHIVE" | awk '{print $1}')"
  [[ "$EXPECTED_MD5" == "$ACTUAL_MD5" ]] || die "MD5 mismatch: expected=$EXPECTED_MD5 actual=$ACTUAL_MD5"
  log "MD5 ok."
else
  warn "No MD5 published for $SUM_URL; skipping checksum."
fi

log "Extracting..."
run "tar -xzf '$ARCHIVE' -C '$STAGE'"
DEBS_DIR="$(find "$STAGE" -maxdepth 3 -type d -name DEBS | head -n1 || true)"
[[ -n "$DEBS_DIR" || $DRY_RUN -eq 1 ]] || die "DEBS/ directory not found in archive."

if (( ! SKIP_REMOVE_DISTRO )); then
  if dpkg -l 'libreoffice*' 2>/dev/null | awk '/^ii/ {print $2}' | grep -q .; then
    log "Removing distro-supplied libreoffice* packages to avoid conflicts..."
    run "apt-get remove --purge -y 'libreoffice*'"
  fi
fi

log "Installing .deb packages..."
run "dpkg -i -R '$DEBS_DIR'"
log "Resolving any missing dependencies..."
run "apt-get install -f -y"

log "Done. LibreOffice $LATEST_VERSION installed."
