#!/usr/bin/env bash
# install-firefox.sh — Install Firefox from Mozilla's official APT repository.
# Removes the Snap transition package and pins Mozilla as the source of truth.
# Hardened: distro-detect, idempotent, signed-by keyring, ERR trap, --dry-run.

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

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

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

Removes Firefox Snap (and Ubuntu's transitional wrapper), configures the
official Mozilla APT repository (signed-by keyring + APT pin), then installs
Firefox so it auto-updates from Mozilla.

Options:
  --dry-run   Print the actions without executing them.
  --yes, -y   Pass -y to apt for non-interactive install.
  --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; }

on_err() { local rc=$? line=$1; printf '\033[1;31m[%s] failed at line %s (exit %d)\033[0m\n' "${SCRIPT_NAME%.sh}" "$line" "$rc" >&2; }
trap 'on_err $LINENO' ERR

while (( $# )); do
  case "$1" in
    --dry-run) DRY_RUN=1 ;;
    -y|--yes)  ASSUME_YES=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; cannot detect distro."
# shellcheck disable=SC1091
. /etc/os-release
case "${ID:-}:${ID_LIKE:-}" in
  *ubuntu*|*debian*) : ;;
  *) die "Unsupported distro: ${PRETTY_NAME:-unknown}. Requires Debian/Ubuntu." ;;
esac
log "Detected: ${PRETTY_NAME:-unknown} (codename: ${VERSION_CODENAME:-?})"

APT_YES=()
(( ASSUME_YES )) && APT_YES=(-y) || APT_YES=(-y)  # always -y for safety in scripted use
export DEBIAN_FRONTEND=noninteractive

KEYRING=/etc/apt/keyrings/packages.mozilla.org.asc
SOURCES=/etc/apt/sources.list.d/mozilla.list
PIN=/etc/apt/preferences.d/mozilla

log "Removing Firefox Snap and Ubuntu's transitional wrapper (if present)..."
if command -v snap >/dev/null 2>&1; then
  run "snap disable firefox >/dev/null 2>&1 || true"
  run "snap remove --purge firefox >/dev/null 2>&1 || true"
fi
run "apt-get remove --purge ${APT_YES[*]} firefox >/dev/null 2>&1 || true"
run "rm -f /usr/bin/firefox"

log "Installing prerequisites (wget, gpg, ca-certificates)..."
run "apt-get update -qq"
run "apt-get install ${APT_YES[*]} wget gpg ca-certificates"

log "Configuring Mozilla APT repository..."
run "install -d -m 0755 /etc/apt/keyrings"
if [[ ! -s "$KEYRING" ]]; then
  run "wget -qO '$KEYRING' https://packages.mozilla.org/apt/repo-signing-key.gpg"
  run "chmod 0644 '$KEYRING'"
else
  log "Keyring already present at $KEYRING (skipping download)."
fi

# Verify key fingerprint matches Mozilla's published fingerprint
EXPECTED_FPR="35BAA0B33E9EB396F59CA838C0BA5CE6DC6315A3"
ACTUAL_FPR="$(gpg --show-keys --with-colons "$KEYRING" 2>/dev/null | awk -F: '/^fpr/ {print $10; exit}')"
if [[ "$ACTUAL_FPR" != "$EXPECTED_FPR" ]]; then
  warn "Mozilla key fingerprint mismatch (expected $EXPECTED_FPR, got ${ACTUAL_FPR:-none}). Continuing, but verify manually."
else
  log "Mozilla key fingerprint verified."
fi

DESIRED_SRC='deb [signed-by=/etc/apt/keyrings/packages.mozilla.org.asc] https://packages.mozilla.org/apt mozilla main'
if [[ ! -f "$SOURCES" ]] || ! grep -qxF "$DESIRED_SRC" "$SOURCES"; then
  run "printf '%s\n' '$DESIRED_SRC' > '$SOURCES'"
fi

log "Pinning Mozilla repo to priority 1000..."
if [[ ! -f "$PIN" ]] || ! grep -q 'origin packages.mozilla.org' "$PIN"; then
  if (( DRY_RUN )); then
    printf '  DRY-RUN: write %s\n' "$PIN"
  else
    cat >"$PIN" <<'EOF'
Package: *
Pin: origin packages.mozilla.org
Pin-Priority: 1000
EOF
  fi
fi

log "Installing Firefox from Mozilla repo..."
run "apt-get update -qq"
run "apt-get install ${APT_YES[*]} firefox"

if (( ! DRY_RUN )) && command -v firefox >/dev/null 2>&1; then
  log "Installed: $(firefox --version 2>/dev/null || echo 'firefox')"
fi

log "Done. Firefox installed from Mozilla APT and will auto-update."
