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

# =======================
# SSH Server Setup Skript
# =======================
# Dieses Skript richtet einen Linux-Server für SSH-Key-Authentifizierung ein:
# - Lädt SSH-Key von Webseite herunter
# - Richtet SSH-Key für root und normalen User ein
# - Deaktiviert Passwort-Authentifizierung
# - Setzt Hostname
# - Konfiguriert /etc/hosts (IPv4 und IPv6)
# - Führt System-Updates aus
#
# Verwendung:
#   ./setup-ssh-server.sh [--ssh-key-url URL] [--username USER]
#

# =======================
# Helpers
# =======================
WARNINGS_COUNT=0
ERRORS_COUNT=0

log()  { echo -e "\e[1;32m[+]\e[0m $*"; }
warn() { 
  ((WARNINGS_COUNT++))
  echo -e "\e[1;33m[!]\e[0m $*" >&2
}
err()  { 
  ((ERRORS_COUNT++))
  echo -e "\e[1;31m[-]\e[0m $*" >&2
}

# =======================
# Konfiguration
# =======================
# SSH-Key URL (kann via CLI-Parameter überschrieben werden)
DEFAULT_SSH_KEY_URL="http://fastdl.linuxy95.at/ssh/neubaumi.pub"
SSH_KEY_URL="${SSH_KEY_URL:-${DEFAULT_SSH_KEY_URL}}"

# Username für normalen User (kann via CLI-Parameter überschrieben werden)
DEFAULT_USERNAME=""
USERNAME="${USERNAME:-${DEFAULT_USERNAME}}"

# Parse CLI-Parameter
while [[ $# -gt 0 ]]; do
  case $1 in
    --ssh-key-url)
      SSH_KEY_URL="$2"
      shift 2
      ;;
    --username)
      USERNAME="$2"
      shift 2
      ;;
    --help|-h)
      echo "Verwendung: $0 [OPTIONEN]"
      echo ""
      echo "Optionen:"
      echo "  --ssh-key-url URL    URL zum Herunterladen des SSH-Keys (Standard: ${DEFAULT_SSH_KEY_URL})"
      echo "  --username USER      Benutzername für normalen User (Standard: wird abgefragt)"
      echo "  --help, -h           Zeige diese Hilfe"
      echo ""
      echo "Umgebungsvariablen:"
      echo "  SSH_KEY_URL          URL zum Herunterladen des SSH-Keys"
      echo "  USERNAME             Benutzername für normalen User"
      exit 0
      ;;
    *)
      err "Unbekannte Option: $1"
      err "Verwende --help für Hilfe"
      exit 1
      ;;
  esac
done

# =======================
# Weitere Helpers
# =======================
need_root(){ [[ $EUID -eq 0 ]] || { err "Bitte als root ausführen."; exit 1; }; }
cmd_exists(){ command -v "$1" >/dev/null 2>&1; }
backup_file(){ local f="$1"; [[ -f "$f" ]] && cp -a "$f" "${f}.bak.$(date +%Y%m%d-%H%M%S)"; }
get_ssh_service_name(){
  # Prüfe welcher SSH-Service verfügbar ist
  if systemctl list-unit-files | grep -q "^ssh\.service"; then
    echo "ssh"
  elif systemctl list-unit-files | grep -q "^sshd\.service"; then
    echo "sshd"
  else
    # Fallback: Versuche beide
    if systemctl is-active --quiet ssh 2>/dev/null; then
      echo "ssh"
    elif systemctl is-active --quiet sshd 2>/dev/null; then
      echo "sshd"
    else
      echo "ssh"  # Standard für Debian/Ubuntu
    fi
  fi
}

need_root

# =======================
# Distribution-Prüfung
# =======================
log "Prüfe Distribution…"
if [[ -f /etc/debian_version ]] || [[ -f /etc/os-release ]]; then
  if [[ -f /etc/os-release ]]; then
    . /etc/os-release
    if [[ "${ID:-}" != "debian" && "${ID:-}" != "ubuntu" ]]; then
      err "Dieses Skript unterstützt nur Debian und Ubuntu!"
      err "Gefundene Distribution: ${ID:-unknown}"
      exit 1
    fi
    log "Distribution erkannt: ${ID} ${VERSION_ID:-}"
  else
    log "Distribution erkannt: Debian"
  fi
else
  err "Keine Debian/Ubuntu-Distribution erkannt!"
  exit 1
fi

export DEBIAN_FRONTEND=noninteractive

# =======================
# SSH-Key URL abfragen
# =======================
if [[ -z "${SSH_KEY_URL}" ]]; then
  SSH_KEY_URL="${DEFAULT_SSH_KEY_URL}"
fi

echo
log "SSH-Key wird von folgender URL heruntergeladen: ${SSH_KEY_URL}"
read -p "URL ändern? (Enter für Standard verwenden): " CHANGE_URL
if [[ -n "${CHANGE_URL}" ]]; then
  SSH_KEY_URL="${CHANGE_URL}"
  log "URL geändert auf: ${SSH_KEY_URL}"
fi
echo

# =======================
# Username abfragen
# =======================
if [[ -z "${USERNAME}" ]]; then
  echo
  log "Benutzername für normalen User benötigt"
  read -p "Benutzername (leer lassen, um keinen User zu erstellen): " USERNAME
  echo
fi

# =======================
# Hostname abfragen und setzen
# =======================
echo
log "Hostname-Konfiguration"
CURRENT_HOSTNAME=$(hostname)
read -p "Hostname (aktuell: ${CURRENT_HOSTNAME}): " NEW_HOSTNAME
if [[ -z "${NEW_HOSTNAME}" ]]; then
  NEW_HOSTNAME="${CURRENT_HOSTNAME}"
  log "Hostname bleibt unverändert: ${NEW_HOSTNAME}"
else
  log "Setze Hostname auf: ${NEW_HOSTNAME}"
  hostnamectl set-hostname "${NEW_HOSTNAME}" || {
    err "Hostname konnte nicht gesetzt werden"
    exit 1
  }
  log "Hostname erfolgreich gesetzt"
fi

# FQDN automatisch generieren (kann überschrieben werden)
AUTO_FQDN="${NEW_HOSTNAME}.mnhub.net"
CURRENT_FQDN=$(hostname -f 2>/dev/null || echo "")
log "FQDN wird automatisch generiert: ${AUTO_FQDN}"
read -p "FQDN (Enter für automatisch: ${AUTO_FQDN}): " FQDN
if [[ -z "${FQDN}" ]]; then
  FQDN="${AUTO_FQDN}"
  log "FQDN automatisch gesetzt: ${FQDN}"
else
  log "FQDN manuell gesetzt: ${FQDN}"
fi

# =======================
# IPv4 und IPv6 Adressen ermitteln
# =======================
log "Ermittle Netzwerk-Adressen…"

# IPv4 Adresse
IPV4_ADDR=""
if cmd_exists ip; then
  IPV4_ADDR=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
elif cmd_exists hostname; then
  IPV4_ADDR=$(hostname -I | awk '{print $1}')
fi

# IPv6 Adresse
IPV6_ADDR=""
if cmd_exists ip; then
  IPV6_ADDR=$(ip -6 addr show | grep -oP '(?<=inet6\s)[0-9a-f:]+' | grep -v '::1' | grep -v '^fe80:' | head -1)
fi

if [[ -z "${IPV4_ADDR}" ]]; then
  warn "Keine IPv4-Adresse gefunden"
  read -p "IPv4-Adresse manuell eingeben (leer lassen zum Überspringen): " IPV4_ADDR
fi

if [[ -z "${IPV6_ADDR}" ]]; then
  warn "Keine IPv6-Adresse gefunden"
  read -p "IPv6-Adresse manuell eingeben (leer lassen zum Überspringen): " IPV6_ADDR
fi

log "IPv4-Adresse: ${IPV4_ADDR:-nicht gesetzt}"
log "IPv6-Adresse: ${IPV6_ADDR:-nicht gesetzt}"

# =======================
# /etc/hosts konfigurieren
# =======================
log "Konfiguriere /etc/hosts…"
backup_file /etc/hosts

# Entferne alte Einträge für diesen Hostname und FQDN
sed -i "/[[:space:]]${NEW_HOSTNAME}[[:space:]]/d" /etc/hosts 2>/dev/null || true
sed -i "/[[:space:]]${NEW_HOSTNAME}$/d" /etc/hosts 2>/dev/null || true
sed -i "/[[:space:]]${FQDN}[[:space:]]/d" /etc/hosts 2>/dev/null || true
sed -i "/[[:space:]]${FQDN}$/d" /etc/hosts 2>/dev/null || true

# Füge neue Einträge hinzu (Format: IP    hostname fqdn)
HOSTS_ENTRY=""
if [[ -n "${IPV4_ADDR}" ]]; then
  HOSTS_ENTRY="${IPV4_ADDR}    ${NEW_HOSTNAME} ${FQDN}"
  if [[ -n "${IPV6_ADDR}" ]]; then
    HOSTS_ENTRY="${HOSTS_ENTRY}\n${IPV6_ADDR}    ${NEW_HOSTNAME} ${FQDN}"
  fi
elif [[ -n "${IPV6_ADDR}" ]]; then
  HOSTS_ENTRY="${IPV6_ADDR}    ${NEW_HOSTNAME} ${FQDN}"
fi

if [[ -n "${HOSTS_ENTRY}" ]]; then
  echo -e "${HOSTS_ENTRY}" >> /etc/hosts
  log "/etc/hosts aktualisiert"
  log "Eintrag: ${IPV4_ADDR:-${IPV6_ADDR}}    ${NEW_HOSTNAME} ${FQDN}"
else
  warn "Keine IP-Adressen zum Eintragen in /etc/hosts gefunden"
fi

# =======================
# System-Updates
# =======================
log "Führe System-Updates aus…"
apt-get update -y
apt-get upgrade -y
apt-get autoremove -y
apt-get autoclean -y
log "System-Updates abgeschlossen"

# =======================
# SSH-Key herunterladen
# =======================
log "Lade SSH-Key von ${SSH_KEY_URL} herunter…"
TMP_KEY_FILE=$(mktemp)
if curl -fsSL "${SSH_KEY_URL}" -o "${TMP_KEY_FILE}" 2>/dev/null || wget -q "${SSH_KEY_URL}" -O "${TMP_KEY_FILE}" 2>/dev/null; then
  log "SSH-Key erfolgreich heruntergeladen"
  
  # Validiere SSH-Key Format
  if ! ssh-keygen -l -f "${TMP_KEY_FILE}" >/dev/null 2>&1; then
    err "Heruntergeladene Datei ist kein gültiger SSH-Key!"
    rm -f "${TMP_KEY_FILE}"
    exit 1
  fi
else
  err "SSH-Key konnte nicht heruntergeladen werden!"
  err "Prüfe die URL und die Netzwerkverbindung."
  rm -f "${TMP_KEY_FILE}"
  exit 1
fi

# =======================
# SSH-Key für root einrichten
# =======================
log "Richte SSH-Key für root ein…"
ROOT_SSH_DIR="/root/.ssh"
mkdir -p "${ROOT_SSH_DIR}"
chmod 700 "${ROOT_SSH_DIR}"

AUTHORIZED_KEYS="${ROOT_SSH_DIR}/authorized_keys"
if [[ -f "${AUTHORIZED_KEYS}" ]]; then
  backup_file "${AUTHORIZED_KEYS}"
fi

# Füge Key hinzu (falls noch nicht vorhanden)
KEY_CONTENT=$(cat "${TMP_KEY_FILE}")
if ! grep -Fxq "${KEY_CONTENT}" "${AUTHORIZED_KEYS}" 2>/dev/null; then
  echo "${KEY_CONTENT}" >> "${AUTHORIZED_KEYS}"
  log "SSH-Key zu root authorized_keys hinzugefügt"
else
  log "SSH-Key bereits in root authorized_keys vorhanden"
fi

chmod 600 "${AUTHORIZED_KEYS}"
chown root:root "${AUTHORIZED_KEYS}"

# =======================
# SSH-Key für normalen User einrichten
# =======================
if [[ -n "${USERNAME}" ]]; then
  log "Richte SSH-Key für User ${USERNAME} ein…"
  
  # Prüfe ob User existiert
  if ! id "${USERNAME}" >/dev/null 2>&1; then
    log "User ${USERNAME} existiert nicht - erstelle User…"
    useradd -m -s /bin/bash "${USERNAME}" || {
      err "User konnte nicht erstellt werden"
      rm -f "${TMP_KEY_FILE}"
      exit 1
    }
    log "User ${USERNAME} erfolgreich erstellt"
  fi
  
  USER_HOME=$(getent passwd "${USERNAME}" | cut -d: -f6)
  USER_SSH_DIR="${USER_HOME}/.ssh"
  mkdir -p "${USER_SSH_DIR}"
  chmod 700 "${USER_SSH_DIR}"
  chown "${USERNAME}:${USERNAME}" "${USER_SSH_DIR}"
  
  USER_AUTHORIZED_KEYS="${USER_SSH_DIR}/authorized_keys"
  if [[ -f "${USER_AUTHORIZED_KEYS}" ]]; then
    backup_file "${USER_AUTHORIZED_KEYS}"
  fi
  
  # Füge Key hinzu (falls noch nicht vorhanden)
  if ! grep -Fxq "${KEY_CONTENT}" "${USER_AUTHORIZED_KEYS}" 2>/dev/null; then
    echo "${KEY_CONTENT}" >> "${USER_AUTHORIZED_KEYS}"
    log "SSH-Key zu ${USERNAME} authorized_keys hinzugefügt"
  else
    log "SSH-Key bereits in ${USERNAME} authorized_keys vorhanden"
  fi
  
  chmod 600 "${USER_AUTHORIZED_KEYS}"
  chown "${USERNAME}:${USERNAME}" "${USER_AUTHORIZED_KEYS}"
fi

# Temporäre Key-Datei löschen
rm -f "${TMP_KEY_FILE}"

# =======================
# SSH-Konfiguration anpassen
# =======================
log "Konfiguriere SSH-Server…"
backup_file /etc/ssh/sshd_config

# Entferne alte Einträge und setze neue Werte
# Deaktiviere Passwort-Authentifizierung
sed -i '/^PasswordAuthentication/d' /etc/ssh/sshd_config
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
log "Passwort-Authentifizierung deaktiviert"

# Aktiviere Public-Key-Authentifizierung
sed -i '/^PubkeyAuthentication/d' /etc/ssh/sshd_config
echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config
log "Public-Key-Authentifizierung aktiviert"

# Erlaube Root-Login nur mit Public-Key (kein Passwort)
sed -i '/^PermitRootLogin/d' /etc/ssh/sshd_config
echo "PermitRootLogin prohibit-password" >> /etc/ssh/sshd_config
log "Root-Login mit Public-Key erlaubt (kein Passwort)"

# Teste SSH-Konfiguration
if sshd -t 2>/dev/null; then
  log "SSH-Konfiguration ist gültig"
  
  # Ermittle den SSH-Service-Namen
  SSH_SERVICE=$(get_ssh_service_name)
  log "SSH-Service erkannt: ${SSH_SERVICE}"
  
  log "Starte SSH-Service neu…"
  if systemctl restart "${SSH_SERVICE}" 2>/dev/null; then
    log "SSH-Service erfolgreich neu gestartet"
  else
    warn "SSH-Service konnte nicht neu gestartet werden"
    warn "Versuche alternativen Service-Namen…"
    if [[ "${SSH_SERVICE}" == "ssh" ]]; then
      systemctl restart sshd 2>/dev/null || warn "Auch sshd konnte nicht gestartet werden"
    else
      systemctl restart ssh 2>/dev/null || warn "Auch ssh konnte nicht gestartet werden"
    fi
    warn "Bitte manuell neu starten: systemctl restart ${SSH_SERVICE} oder systemctl restart ssh"
  fi
else
  err "SSH-Konfiguration hat Fehler!"
  err "Bitte prüfe: sshd -t"
  exit 1
fi

# =======================
# Zusammenfassung
# =======================
echo
log "=== Zusammenfassung ==="
echo
log "System-Informationen:"
echo "  - Distribution: ${ID:-unknown} ${VERSION_ID:-}"
echo "  - Hostname: ${NEW_HOSTNAME}"
echo "  - FQDN: ${FQDN}"
echo "  - IPv4: ${IPV4_ADDR:-nicht gesetzt}"
echo "  - IPv6: ${IPV6_ADDR:-nicht gesetzt}"
echo
log "SSH-Konfiguration:"
echo "  ✓ SSH-Key für root eingerichtet"
if [[ -n "${USERNAME}" ]]; then
  echo "  ✓ SSH-Key für User ${USERNAME} eingerichtet"
fi
echo "  ✓ Passwort-Authentifizierung deaktiviert"
echo "  ✓ Public-Key-Authentifizierung aktiviert"
echo
log "Wichtige Hinweise:"
echo "  ⚠ Stelle sicher, dass du mit dem SSH-Key auf den Server zugreifen kannst,"
echo "    bevor du die aktuelle SSH-Session schließt!"
echo "  ⚠ Teste den Zugriff in einer neuen SSH-Session, bevor du die aktuelle beendest."
echo "  ⚠ Falls der Zugriff nicht funktioniert, kannst du die Backup-Dateien verwenden:"
echo "    - /etc/ssh/sshd_config.bak.*"
echo "    - /root/.ssh/authorized_keys.bak.*"
if [[ -n "${USERNAME}" ]]; then
  echo "    - ~${USERNAME}/.ssh/authorized_keys.bak.*"
fi
echo

if [[ $ERRORS_COUNT -gt 0 ]]; then
  err "Skript mit Fehlern beendet (${ERRORS_COUNT} Fehler, ${WARNINGS_COUNT} Warnungen)"
  exit 1
elif [[ $WARNINGS_COUNT -gt 0 ]]; then
  warn "Skript erfolgreich abgeschlossen mit ${WARNINGS_COUNT} Warnung(en)"
  exit 0
else
  log "Skript erfolgreich abgeschlossen ohne Fehler oder Warnungen."
  exit 0
fi

