#!/usr/bin/env bash
# install-qbittorrent.sh — Install qBittorrent from the latest official GitHub release.
# Hardened: arch-aware, GitHub API token support, SHA-256 verification from the
# release asset digest, idempotent, --dry-run.

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

readonly SCRIPT_NAME="${0##*/}"
DRY_RUN=0
REPO="qbittorrent/qBittorrent"

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

Resolves the latest release of qbittorrent/qBittorrent, downloads the official
Linux x86_64 AppImage, verifies its SHA-256 against the GitHub release asset
digest when available, and installs it system-wide.

If \$GITHUB_TOKEN is set in the environment, it is used to authenticate the
GitHub API request (avoids rate limits).

Options:
  --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 ;;
    -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}." ;;
esac

ARCH="$(dpkg --print-architecture)"
[[ "$ARCH" == "amd64" ]] || die "qBittorrent publishes official Linux AppImages for x86_64/amd64 only (detected: $ARCH)."
log "Detected: ${PRETTY_NAME:-unknown}, arch: $ARCH"

export DEBIAN_FRONTEND=noninteractive
log "Installing prerequisites..."
run "apt-get update -qq"
run "apt-get install -y curl jq ca-certificates desktop-file-utils shared-mime-info hicolor-icon-theme"

GH_HDRS=(-H "Accept: application/vnd.github+json")
[[ -n "${GITHUB_TOKEN:-}" ]] && GH_HDRS+=(-H "Authorization: Bearer ${GITHUB_TOKEN}")

log "Querying GitHub API for latest release of $REPO..."
RELEASE_JSON="$(curl -fsSL "${GH_HDRS[@]}" "https://api.github.com/repos/${REPO}/releases/latest")"
TAG="$(jq -r '.tag_name // empty' <<<"$RELEASE_JSON")"
[[ -n "$TAG" ]] || die "Could not parse latest release tag (rate limited? set GITHUB_TOKEN)."
VERSION="${TAG#release-}"
log "Latest release: $TAG"

ASSET_REGEX='^qbittorrent-[0-9][^/]*_x86_64\.AppImage$'
DOWNLOAD_URL="$(jq -r --arg re "$ASSET_REGEX" '.assets[] | select(.name | test($re)) | select(.name | test("_lt20_") | not) | .browser_download_url' <<<"$RELEASE_JSON" | head -n1)"
ASSET_NAME="$(jq -r --arg re "$ASSET_REGEX" '.assets[] | select(.name | test($re)) | select(.name | test("_lt20_") | not) | .name' <<<"$RELEASE_JSON" | head -n1)"
EXPECTED_SHA="$(jq -r --arg re "$ASSET_REGEX" '.assets[] | select(.name | test($re)) | select(.name | test("_lt20_") | not) | (.digest // "") | sub("^sha256:"; "")' <<<"$RELEASE_JSON" | head -n1)"
[[ "$DOWNLOAD_URL" =~ ^https:// ]] || die "No standard x86_64 AppImage asset found in latest qBittorrent release."

STAGE="$(mktemp -d -t qbittorrent.XXXXXX)"
trap 'rm -rf "$STAGE"' EXIT
APPIMAGE="$STAGE/$ASSET_NAME"

log "Downloading $ASSET_NAME..."
run "curl -fL -o '$APPIMAGE' '$DOWNLOAD_URL'"

if (( DRY_RUN )); then
  [[ -n "$EXPECTED_SHA" && "$EXPECTED_SHA" != "null" ]] \
    && printf '  DRY-RUN: verify SHA-256 %s\n' "$EXPECTED_SHA" \
    || printf '  DRY-RUN: skip SHA-256 verification; no GitHub asset digest found\n'
  printf '  DRY-RUN: install AppImage to /opt/qbittorrent/qbittorrent\n'
  printf '  DRY-RUN: create /usr/local/bin/qbittorrent symlink\n'
  printf '  DRY-RUN: install desktop launcher, icons, and MIME handlers\n'
  log "Done."
  exit 0
fi

if [[ -n "$EXPECTED_SHA" && "$EXPECTED_SHA" != "null" ]]; then
  log "Verifying SHA-256..."
  ACTUAL_SHA="$(sha256sum "$APPIMAGE" | awk '{print $1}')"
  [[ "$EXPECTED_SHA" == "$ACTUAL_SHA" ]] || die "SHA-256 mismatch: expected=$EXPECTED_SHA actual=$ACTUAL_SHA"
  log "SHA-256 ok."
else
  warn "No SHA-256 asset digest in GitHub release metadata; skipping verification."
fi

log "Installing qBittorrent AppImage..."
run "install -d -m 0755 /opt/qbittorrent"
run "install -m 0755 '$APPIMAGE' /opt/qbittorrent/qbittorrent"
run "ln -sfn /opt/qbittorrent/qbittorrent /usr/local/bin/qbittorrent"

log "Extracting desktop metadata and icons..."
EXTRACT_DIR="$STAGE/extract"
run "install -d -m 0755 '$EXTRACT_DIR'"
(
  cd "$EXTRACT_DIR"
  /opt/qbittorrent/qbittorrent --appimage-extract >/dev/null
)

run "install -d -m 0755 /usr/share/icons/hicolor/scalable/apps"
run "install -m 0644 '$EXTRACT_DIR/squashfs-root/usr/share/icons/hicolor/scalable/apps/qbittorrent.svg' /usr/share/icons/hicolor/scalable/apps/qbittorrent.svg"
for size in 16 22 24 32 36 48 64 72 96 128 192; do
  src="$EXTRACT_DIR/squashfs-root/usr/share/icons/hicolor/${size}x${size}/apps/qbittorrent.png"
  [[ -f "$src" ]] || continue
  run "install -d -m 0755 '/usr/share/icons/hicolor/${size}x${size}/apps'"
  run "install -m 0644 '$src' '/usr/share/icons/hicolor/${size}x${size}/apps/qbittorrent.png'"
done

log "Installing desktop launcher..."
cat >/usr/share/applications/org.qbittorrent.qBittorrent.desktop <<EOF
[Desktop Entry]
Type=Application
Name=qBittorrent
GenericName=BitTorrent client
Comment=Download and share files over BitTorrent
Exec=/opt/qbittorrent/qbittorrent %U
Icon=qbittorrent
Terminal=false
Categories=Network;FileTransfer;P2P;Qt;
MimeType=application/x-bittorrent;x-scheme-handler/magnet;
StartupNotify=false
StartupWMClass=qbittorrent
Keywords=bittorrent;torrent;magnet;download;p2p;
SingleMainWindow=true
EOF

run "desktop-file-validate /usr/share/applications/org.qbittorrent.qBittorrent.desktop"
run "update-desktop-database /usr/share/applications"
run "update-mime-database /usr/share/mime"
run "gtk-update-icon-cache -f -t /usr/share/icons/hicolor >/dev/null 2>&1 || true"

if command -v xdg-mime >/dev/null 2>&1; then
  run "xdg-mime default org.qbittorrent.qBittorrent.desktop application/x-bittorrent || true"
  run "xdg-mime default org.qbittorrent.qBittorrent.desktop x-scheme-handler/magnet || true"
fi

if command -v qbittorrent >/dev/null 2>&1; then
  log "Installed: $(qbittorrent --version 2>/dev/null || echo "$VERSION")"
fi
log "Done."
