#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# Pyxsoft pxShield Installer
# -----------------------------------------------------------------------------
# 1) Detect the package family (rpm-based vs deb-based)
# 2) Install the Pyxsoft repository:
#       rpm  ->  https://www.pyxsoft.com/extra/repo-latest.rpm
#       deb  ->  https://www.pyxsoft.com/extra/repo-latest.deb
# 3) Install pxShield:
#       cPanel     ->  pxshield-cpanel  (meta-package: pulls the engine, the
#                                        WHM/cPanel UI and mod_remoteip; managed from WHM)
#       no cPanel  ->  pxshield         (managed from centralhost.sh)
#
# Includes retry logic for transient package-manager DB locks.
# Usage: curl -s https://www.pyxsoft.com/extra/install-pxshield | bash
# -----------------------------------------------------------------------------

set -euo pipefail

REPO_RPM_URL="https://www.pyxsoft.com/extra/repo-latest.rpm"
REPO_DEB_URL="https://www.pyxsoft.com/extra/repo-latest.deb"

# Package family: "rpm" or "deb". Resolved by detect_pkg_family().
PKG_FAMILY=""

# --- Helpers -----------------------------------------------------------------

require_root() {
  # Ensure the script is executed with root privileges. This installer is meant
  # to be piped straight into bash (curl … | bash), so the script arrives on
  # stdin with no file path — re-exec'ing via sudo cannot work here (there is no
  # "$0" to re-run and stdin is already consumed). Fail with a clear message.
  if [[ $EUID -ne 0 ]]; then
    echo "[-] This installer must be run as root."
    echo "    Re-run it as root, for example:"
    echo "        curl -s https://www.pyxsoft.com/extra/install-pxshield | sudo bash"
    exit 1
  fi
}

detect_pkg_family() {
  # Decide whether this is an rpm-based or deb-based distribution.
  if command -v dnf >/dev/null 2>&1 || command -v yum >/dev/null 2>&1 || command -v rpm >/dev/null 2>&1; then
    PKG_FAMILY="rpm"
  elif command -v apt-get >/dev/null 2>&1 || command -v dpkg >/dev/null 2>&1; then
    PKG_FAMILY="deb"
  else
    echo "[!] Could not detect a supported package manager (yum/dnf or apt)."
    echo "    pxShield supports RHEL-family (rpm) and Debian/Ubuntu (deb) systems."
    exit 1
  fi
  echo "[*] Detected ${PKG_FAMILY}-based system."
}

# Prefer dnf, fall back to yum. Used only on rpm systems.
RPM_MGR=""
resolve_rpm_mgr() {
  if command -v dnf >/dev/null 2>&1; then
    RPM_MGR="dnf"
  elif command -v yum >/dev/null 2>&1; then
    RPM_MGR="yum"
  else
    echo "[!] Neither dnf nor yum found on this rpm-based system."
    exit 1
  fi
}

with_lock_retry() {
  # Run a package-manager command with retries on transient lock/metadata errors.
  local max_tries=6
  local delay=3
  local attempt=1

  while true; do
    if "$@"; then
      return 0
    fi
    local rc=$?
    if (( attempt < max_tries )); then
      echo "[!] Command failed (rc=$rc). Attempt ${attempt}/${max_tries}. Retrying in ${delay}s…"
      sleep "${delay}"
      delay=$(( delay * 2 )); (( delay > 20 )) && delay=20
      attempt=$(( attempt + 1 ))
      continue
    fi
    echo "[!] Command failed after ${max_tries} attempts."
    return $rc
  done
}

ensure_curl() {
  # curl is used to fetch the .deb repo package; make sure it exists.
  if command -v curl >/dev/null 2>&1; then
    return 0
  fi
  echo "[*] Installing curl…"
  if [[ "${PKG_FAMILY}" == "rpm" ]]; then
    with_lock_retry "${RPM_MGR}" -y install curl
  else
    with_lock_retry apt-get update
    with_lock_retry apt-get -y install curl
  fi
}

is_cpanel() {
  # cPanel/WHM leaves these markers on the server.
  [[ -d /var/cpanel || -d /usr/local/cpanel ]]
}

# --- Repository install ------------------------------------------------------

install_repo_rpm() {
  echo "[*] Installing Pyxsoft repository (rpm)…"
  with_lock_retry "${RPM_MGR}" -y install "${REPO_RPM_URL}"
  with_lock_retry "${RPM_MGR}" -y clean all || true
  with_lock_retry "${RPM_MGR}" -y makecache || true
}

install_repo_deb() {
  echo "[*] Installing Pyxsoft repository (deb)…"
  local tmp_deb
  tmp_deb="$(mktemp --suffix=.deb)"
  curl -fsSL -o "${tmp_deb}" "${REPO_DEB_URL}"
  # dpkg may report missing deps; apt-get -f fixes them up.
  dpkg -i "${tmp_deb}" || with_lock_retry apt-get -y -f install
  rm -f "${tmp_deb}"
  with_lock_retry apt-get update
}

# --- Package install ---------------------------------------------------------

install_pxshield_rpm() {
  if is_cpanel; then
    echo "[*] cPanel detected — installing pxshield-cpanel…"
    with_lock_retry "${RPM_MGR}" -y install pxshield-cpanel
  else
    echo "[*] Installing pxshield…"
    with_lock_retry "${RPM_MGR}" -y install pxshield
  fi
}

install_pxshield_deb() {
  if is_cpanel; then
    echo "[*] cPanel detected — installing pxshield-cpanel…"
    with_lock_retry apt-get -y install pxshield-cpanel
  else
    echo "[*] Installing pxshield…"
    with_lock_retry apt-get -y install pxshield
  fi
}

# --- Post-install summary ----------------------------------------------------

print_summary() {
  echo
  echo "[✓] pxShield was successfully installed on this server."
  echo
  if is_cpanel; then
    echo "    Manage pxShield from WHM » Plugins » Pyxsoft pxShield."
    echo "    Your end users get the pxShield interface inside cPanel."
  else
    echo "    This server has no cPanel. You can manage pxShield remotely from"
    echo "    Centralhost — a single dashboard for all your servers:"
    echo
    echo "        https://www.centralhost.sh"
    echo
    echo "    Add this server to your Centralhost account to configure rules,"
    echo "    review blocks and manage licensing from one place."
  fi
  echo
}

# --- Main --------------------------------------------------------------------

main() {
  require_root
  detect_pkg_family

  if [[ "${PKG_FAMILY}" == "rpm" ]]; then
    resolve_rpm_mgr
    ensure_curl
    install_repo_rpm
    install_pxshield_rpm
  else
    ensure_curl
    install_repo_deb
    install_pxshield_deb
  fi

  print_summary
}

main "$@"
