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

DOMAIN="${DOMAIN:-data.cpav.net}"
HOST_SHORT="${DOMAIN%%.*}"
REPORT="${REPORT:-./missing-data.cpav.net.txt}"
INSTALL_CPANEL=0
SKIP_SSL=0

usage() {
  cat <<USAGE
Usage: sudo bash pre.sh [options]

Configures a legitimate cPanel/WHM VPS for ${DOMAIN}.

Options:
  --domain FQDN          Hostname to configure. Default: data.cpav.net
  --install-cpanel      Install cPanel/WHM if it is not already installed.
                        cPanel recommends this only on a fresh OS.
  --skip-ssl            Skip cPanel service SSL certificate check/install.
  --help                Show this help.

Environment:
  DOMAIN=host.example.com REPORT=/path/to/report.txt bash pre.sh
USAGE
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    --domain)
      DOMAIN="${2:-}"
      HOST_SHORT="${DOMAIN%%.*}"
      shift 2
      ;;
    --install-cpanel)
      INSTALL_CPANEL=1
      shift
      ;;
    --skip-ssl)
      SKIP_SSL=1
      shift
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      echo "Unknown option: $1" >&2
      usage
      exit 2
      ;;
  esac
done

: > "$REPORT"

log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
ok() { printf '\033[1;32mOK\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33mWARN\033[0m %s\n' "$*"; }
fail_item() { printf -- '- %s\n' "$*" >> "$REPORT"; warn "$*"; }
need_cmd() { command -v "$1" >/dev/null 2>&1 || fail_item "Missing command: $1"; }

require_root() {
  if [ "${EUID:-$(id -u)}" -ne 0 ]; then
    echo "Run as root: sudo bash pre.sh" >&2
    exit 1
  fi
}

validate_domain() {
  if ! printf '%s' "$DOMAIN" | grep -Eq '^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)+$'; then
    echo "Invalid FQDN: $DOMAIN" >&2
    exit 1
  fi
  case "$DOMAIN" in
    www.*|[0-9]*|*-)
      fail_item "Hostname should be a valid unique FQDN that does not begin with www, begin with a number, or end with a hyphen: $DOMAIN"
      ;;
  esac
}

read_os() {
  OS_ID="unknown"
  OS_VERSION_ID="unknown"
  if [ -r /etc/os-release ]; then
    # shellcheck disable=SC1091
    . /etc/os-release
    OS_ID="${ID:-unknown}"
    OS_VERSION_ID="${VERSION_ID:-unknown}"
  fi
}

install_base_tools() {
  log "Checking base tools"
  local missing=""
  for cmd in curl perl hostnamectl awk sed grep; do
    command -v "$cmd" >/dev/null 2>&1 || missing="$missing $cmd"
  done

  if [ -z "$missing" ]; then
    ok "Base tools are present"
    return
  fi

  if command -v dnf >/dev/null 2>&1; then
    dnf install -y $missing
  elif command -v yum >/dev/null 2>&1; then
    yum install -y $missing
  elif command -v apt-get >/dev/null 2>&1; then
    apt-get update
    apt-get install -y $missing
  else
    fail_item "No supported package manager found to install:$missing"
  fi
}

public_ipv4() {
  local ip=""
  ip="$(curl -4fsS --max-time 10 https://cpanel.net/myip 2>/dev/null || true)"
  if ! printf '%s' "$ip" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
    ip="$(curl -4fsS --max-time 10 https://ifconfig.me 2>/dev/null || true)"
  fi
  printf '%s' "$ip"
}

dns_ipv4() {
  if command -v dig >/dev/null 2>&1; then
    dig +short A "$DOMAIN" | tail -n 1
  elif command -v getent >/dev/null 2>&1; then
    getent ahostsv4 "$DOMAIN" | awk 'NR==1 {print $1}'
  elif command -v nslookup >/dev/null 2>&1; then
    nslookup "$DOMAIN" | awk '/^Address: / {print $2}' | tail -n 1
  else
    printf ''
  fi
}

check_system_requirements() {
  log "Checking server requirements"
  read_os
  ARCH="$(uname -m)"
  MEM_MB="$(awk '/MemTotal/ {printf "%d", $2/1024}' /proc/meminfo 2>/dev/null || echo 0)"
  DISK_AVAIL_MB="$(df -Pm /usr/local 2>/dev/null | awk 'NR==2 {print $4}' || echo 0)"

  [ "$ARCH" = "x86_64" ] || fail_item "Unsupported architecture for cPanel: $ARCH. Use x86_64."
  [ "$MEM_MB" -ge 2048 ] || fail_item "RAM is below cPanel minimum: ${MEM_MB}MB detected, 2048MB minimum. 4096MB+ recommended."
  [ "$DISK_AVAIL_MB" -ge 20480 ] || fail_item "Disk space under /usr/local is low: ${DISK_AVAIL_MB}MB available, 20480MB minimum. 40960MB+ recommended."

  case "$OS_ID" in
    almalinux|rocky|cloudlinux|ubuntu)
      ok "Detected supported OS family candidate: $OS_ID $OS_VERSION_ID"
      ;;
    *)
      fail_item "OS may not be supported by cPanel/WHM: $OS_ID $OS_VERSION_ID. Use AlmaLinux, Rocky Linux, CloudLinux, or supported Ubuntu."
      ;;
  esac
}

check_dns() {
  log "Checking DNS for $DOMAIN"
  SERVER_IP="$(public_ipv4)"
  DNS_IP="$(dns_ipv4)"

  if [ -z "$SERVER_IP" ]; then
    fail_item "Could not detect this server public IPv4 address. Ensure outbound HTTPS works."
  else
    ok "Server public IPv4: $SERVER_IP"
  fi

  if [ -z "$DNS_IP" ]; then
    fail_item "No A record found for $DOMAIN. Create: $DOMAIN A ${SERVER_IP:-YOUR_SERVER_IP}"
  elif [ -n "$SERVER_IP" ] && [ "$DNS_IP" != "$SERVER_IP" ]; then
    fail_item "DNS mismatch for $DOMAIN. Current A record: $DNS_IP. Expected: $SERVER_IP"
  else
    ok "$DOMAIN resolves to this server"
  fi
}

set_hostname_local() {
  log "Configuring hostname: $DOMAIN"
  hostnamectl set-hostname "$DOMAIN"

  if [ -n "${SERVER_IP:-}" ]; then
    cp /etc/hosts /etc/hosts.cpanel-setup.bak.$(date +%Y%m%d%H%M%S)
    sed -i "/[[:space:]]$DOMAIN\([[:space:]]\|$\)/d" /etc/hosts
    printf '%s\t%s %s\n' "$SERVER_IP" "$DOMAIN" "$HOST_SHORT" >> /etc/hosts
  fi

  if [ -x /usr/local/cpanel/bin/set_hostname ]; then
    /usr/local/cpanel/bin/set_hostname "$DOMAIN"
  fi

  ok "Hostname is now $(hostname -f 2>/dev/null || hostname)"
}

install_or_update_cpanel() {
  if [ -x /usr/local/cpanel/cpanel ] || [ -d /usr/local/cpanel ]; then
    log "cPanel appears installed; running update/license refresh"
    /scripts/upcp --force || fail_item "cPanel update failed: /scripts/upcp --force"
    if [ -x /usr/local/cpanel/cpkeyclt ]; then
      /usr/local/cpanel/cpkeyclt || fail_item "cPanel license refresh failed. Confirm your server IP has a valid cPanel license."
    else
      fail_item "Missing official cPanel license tool: /usr/local/cpanel/cpkeyclt"
    fi
    return
  fi

  if [ "$INSTALL_CPANEL" -ne 1 ]; then
    fail_item "cPanel is not installed. Re-run with --install-cpanel on a fresh supported OS to install it."
    return
  fi

  log "Installing cPanel/WHM from the official cPanel installer"
  cd /home
  curl -o latest -L https://securedownloads.cpanel.net/latest
  sh latest
}

configure_ssl() {
  [ "$SKIP_SSL" -eq 0 ] || return
  log "Requesting/refreshing cPanel service SSL certificates"

  if [ -x /usr/local/cpanel/bin/checkallsslcerts ]; then
    /usr/local/cpanel/bin/checkallsslcerts --verbose || fail_item "Service SSL certificate check failed. Verify DNS points to this server and ports 80/443 are reachable."
  else
    fail_item "cPanel SSL utility not found: /usr/local/cpanel/bin/checkallsslcerts"
  fi

  if [ -x /scripts/restartsrv_cpsrvd ]; then
    /scripts/restartsrv_cpsrvd || fail_item "Could not restart cPanel cpsrvd service."
  fi
}

print_summary() {
  echo
  if [ -s "$REPORT" ]; then
    warn "Setup finished with missing items. See: $REPORT"
    cat "$REPORT"
    exit 3
  fi

  ok "Setup completed for $DOMAIN"
  echo "WHM URL: https://$DOMAIN:2087"
  echo "cPanel service hostname: $DOMAIN"
}

main() {
  require_root
  validate_domain
  install_base_tools
  need_cmd curl
  need_cmd perl
  need_cmd hostnamectl
  check_system_requirements
  check_dns
  set_hostname_local
  install_or_update_cpanel
  configure_ssl
  print_summary
}

main "$@"