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

# A4W Auftrag4Works - Linux/Plesk Installer
# Ziel: ASP.NET-Core/Kestrel-App als systemd-Dienst lokal starten und per Plesk/Nginx reverse-proxien.
# Getesteter Praxisfall: Ubuntu 20.04/Plesk, Domainpfad /var/www/vhosts/auftrag4works.de/demo.auftrag4works.de

APP_NAME="A4W Auftrag4Works"
SERVICE_NAME="a4w"
DLL_NAME="A4W Auftrag4Works.Web.dll"
FALLBACK_DLL_NAME="AuftragoBusiness.dll"
DEFAULT_PORT="5080"
SCRIPT_VERSION="2026-06-13-1"
ROOT_UPDATE_HELPER="/usr/local/sbin/a4w-update"
SUDOERS_UPDATE_FILE="/etc/sudoers.d/a4w-update"

# Bekannter Testpfad. Wird nur als Default genutzt, wenn das Verzeichnis existiert.
KNOWN_TEST_DIR="/var/www/vhosts/auftrag4works.de/demo.auftrag4works.de"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CURRENT_DIR="$(pwd)"
LOG_FILE="/tmp/a4w-install-$(date +%Y%m%d-%H%M%S).log"

log() { echo -e "\033[1;32m[OK]\033[0m $*" | tee -a "$LOG_FILE"; }
info() { echo -e "\033[1;34m[INFO]\033[0m $*" | tee -a "$LOG_FILE"; }
warn() { echo -e "\033[1;33m[WARN]\033[0m $*" | tee -a "$LOG_FILE"; }
err() { echo -e "\033[1;31m[FEHLER]\033[0m $*" | tee -a "$LOG_FILE" >&2; }

need_root() {
  if [[ "${EUID}" -ne 0 ]]; then
    err "Bitte als root oder mit sudo ausfuehren."
    exit 1
  fi
}

ask() {
  local prompt="$1"
  local default="$2"
  local value
  if [[ ! -t 0 ]]; then
    echo "$default"
    return
  fi
  read -r -p "$prompt [$default]: " value
  echo "${value:-$default}"
}

ask_yes_no() {
  local prompt="$1"
  local default="$2"
  local value
  if [[ ! -t 0 ]]; then
    value="$default"
  else
    read -r -p "$prompt [$default]: " value
  fi
  value="${value:-$default}"
  case "${value,,}" in
    j|ja|y|yes) return 0 ;;
    *) return 1 ;;
  esac
}

command_exists() {
  command -v "$1" >/dev/null 2>&1
}

require_command() {
  local name="$1"
  local hint="$2"
  if ! command_exists "$name"; then
    err "Benötigtes Kommando fehlt: $name. $hint"
    exit 1
  fi
}

safe_apt_install() {
  local installable=()
  local pkg
  for pkg in "$@"; do
    if apt-cache show "$pkg" >/dev/null 2>&1; then
      installable+=("$pkg")
    else
      warn "Paket nicht in den aktiven Paketquellen gefunden: $pkg"
    fi
  done
  if [[ "${#installable[@]}" -gt 0 ]]; then
    DEBIAN_FRONTEND=noninteractive apt-get install -y "${installable[@]}"
  fi
}

preflight_system() {
  require_command systemctl "Bitte systemd/systemctl bereitstellen."
  require_command find "Bitte findutils installieren."
  require_command stat "Bitte coreutils installieren."

  if [[ ! -f /etc/os-release ]]; then
    err "/etc/os-release nicht gefunden. Ubuntu-Version kann nicht erkannt werden."
    exit 1
  fi

  # shellcheck disable=SC1091
  . /etc/os-release
  if [[ "${ID:-}" != "ubuntu" ]]; then
    err "Automatische Erstinstallation ist aktuell nur fuer Ubuntu vorbereitet. Erkannt: ${PRETTY_NAME:-unbekannt}"
    exit 1
  fi
  info "Ubuntu erkannt: ${PRETTY_NAME:-Ubuntu}"

  if command_exists plesk || [[ -x /usr/local/psa/bin/domain ]]; then
    info "Plesk-Installation wurde erkannt."
  elif [[ "$SCRIPT_DIR" == /var/www/vhosts/* || "$CURRENT_DIR" == /var/www/vhosts/* ]]; then
    warn "Plesk-Pfad erkannt, aber Plesk-CLI nicht gefunden. Plesk/Nginx wird als manueller Schritt ausgegeben."
  else
    warn "Keine Plesk-Installation erkannt. systemd/Kestrel wird eingerichtet; Reverse Proxy bitte passend zum Webserver konfigurieren."
  fi
}

find_default_app_dir() {
  if [[ -d "$KNOWN_TEST_DIR" ]]; then
    echo "$KNOWN_TEST_DIR"
    return
  fi

  # Wenn das Skript direkt in einem Plesk-Domainverzeichnis liegt, dieses als Vorschlag verwenden.
  if [[ "$SCRIPT_DIR" == /var/www/vhosts/* ]]; then
    echo "$SCRIPT_DIR"
    return
  fi

  if [[ "$CURRENT_DIR" == /var/www/vhosts/* ]]; then
    echo "$CURRENT_DIR"
    return
  fi

  echo "/var/www/a4w"
}

find_plesk_owner_for_dir() {
  local dir="$1"
  local probe="$dir"

  # Falls Ziel noch nicht existiert, nach oben laufen, bis ein existierender Ordner gefunden wird.
  while [[ ! -e "$probe" && "$probe" != "/" ]]; do
    probe="$(dirname "$probe")"
  done

  if [[ -e "$probe" ]]; then
    stat -c '%U' "$probe" 2>/dev/null || echo "www-data"
  else
    echo "www-data"
  fi
}

validate_user_and_group() {
  local user="$1"
  if ! id "$user" >/dev/null 2>&1; then
    err "Linux-Benutzer '$user' existiert nicht. Bitte vorhandenen Plesk-Systembenutzer oder www-data verwenden."
    exit 1
  fi
  id -gn "$user"
}

install_dotnet_runtime_if_missing() {
  if command -v dotnet >/dev/null 2>&1 && dotnet --list-runtimes 2>/dev/null | grep -q 'Microsoft.AspNetCore.App 8\.'; then
    log ".NET / ASP.NET Core Runtime 8 ist vorhanden."
    dotnet --list-runtimes | grep -E 'Microsoft\.AspNetCore\.App 8\.|Microsoft\.NETCore\.App 8\.' || true
    return
  fi

  warn ".NET / ASP.NET Core Runtime 8 wurde nicht gefunden."

  if ! ask_yes_no "Soll der Installer versuchen, die ASP.NET Core Runtime 8 jetzt zu installieren?" "ja"; then
    err "Runtime fehlt. Installation abgebrochen. Installiere z.B. aspnetcore-runtime-8.0 und starte danach erneut."
    exit 1
  fi

  if [[ ! -f /etc/os-release ]]; then
    err "/etc/os-release nicht gefunden. Runtime bitte manuell installieren."
    exit 1
  fi

  # shellcheck disable=SC1091
  . /etc/os-release
  if [[ "${ID:-}" != "ubuntu" ]]; then
    err "Automatische Runtime-Installation ist aktuell nur fuer Ubuntu vorbereitet. Erkannt: ${PRETTY_NAME:-unbekannt}"
    exit 1
  fi

  local version_id="${VERSION_ID:-}"
  if [[ -z "$version_id" ]]; then
    err "Ubuntu VERSION_ID konnte nicht erkannt werden."
    exit 1
  fi

  log "Ubuntu erkannt: ${PRETTY_NAME:-Ubuntu $version_id}"
  log "Linux-Basispakete und .NET-Abhaengigkeiten werden geprueft."

  apt-get update
  safe_apt_install wget curl ca-certificates apt-transport-https gnupg unzip libicu72 libicu74 libssl3 zlib1g libstdc++6 libgcc-s1 libgssapi-krb5-2

  log "Microsoft Paketquelle fuer Ubuntu $version_id wird eingerichtet, falls noch nicht vorhanden."

  local tmpdeb="/tmp/packages-microsoft-prod.deb"
  wget "https://packages.microsoft.com/config/ubuntu/${version_id}/packages-microsoft-prod.deb" -O "$tmpdeb"
  dpkg -i "$tmpdeb"
  rm -f "$tmpdeb"

  apt-get update
  safe_apt_install aspnetcore-runtime-8.0

  if ! command -v dotnet >/dev/null 2>&1 || ! dotnet --list-runtimes 2>/dev/null | grep -q 'Microsoft.AspNetCore.App 8\.'; then
    err "Runtime-Installation wurde versucht, aber ASP.NET Core Runtime 8 ist weiterhin nicht sichtbar."
    exit 1
  fi

  log "ASP.NET Core Runtime 8 erfolgreich installiert."
}

check_runtime_dependencies() {
  if ! command_exists apt-get; then
    warn "apt-get nicht gefunden; native .NET-Abhaengigkeiten koennen nicht automatisch nachinstalliert werden."
    return
  fi

  info "Pruefe haeufig benoetigte native .NET-Bibliotheken."
  apt-get update
  safe_apt_install curl ca-certificates unzip libicu72 libicu74 libssl3 zlib1g libstdc++6 libgcc-s1 libgssapi-krb5-2
}

find_pdf_browser() {
  local candidates=(
    "/usr/bin/chromium"
    "/usr/bin/chromium-browser"
    "/usr/bin/google-chrome"
    "/usr/bin/google-chrome-stable"
    "/usr/bin/microsoft-edge"
    "/snap/bin/chromium"
    "/opt/google/chrome/chrome"
    "/opt/microsoft/msedge/msedge"
  )
  local candidate
  for candidate in "${candidates[@]}"; do
    if [[ -x "$candidate" ]]; then
      echo "$candidate"
      return
    fi
  done
  for candidate in chromium chromium-browser google-chrome google-chrome-stable microsoft-edge msedge chrome; do
    if command_exists "$candidate"; then
      command -v "$candidate"
      return
    fi
  done
  echo ""
}

install_pdf_browser_if_missing() {
  local browser
  browser="$(find_pdf_browser)"
  if [[ -n "$browser" ]]; then
    log "HTML-PDF-Browser gefunden: $browser"
    return
  fi

  warn "Kein Chromium/Chrome/Edge fuer HTML-PDF-Erzeugung gefunden. Abschluss-PDFs und Beleg-PDFs benoetigen einen headless Browser."
  if ! command_exists apt-get; then
    warn "apt-get nicht gefunden; PDF-Browser bitte manuell installieren und optional A4W_PDF_BROWSER setzen."
    return
  fi
  if ask_yes_no "Soll der Installer Chromium fuer HTML-PDFs installieren?" "ja"; then
    apt-get update
    safe_apt_install chromium chromium-browser
  fi

  browser="$(find_pdf_browser)"
  if [[ -n "$browser" ]]; then
    log "HTML-PDF-Browser nach Installation gefunden: $browser"
  else
    warn "Weiterhin kein PDF-Browser gefunden. Installiere Chromium/Chrome manuell oder setze A4W_PDF_BROWSER=/voller/pfad/zum/browser."
  fi
}

find_app_dll() {
  local app_dir="$1"
  if [[ -f "$app_dir/$DLL_NAME" ]]; then
    echo "$DLL_NAME"
    return
  fi
  if [[ -f "$app_dir/$FALLBACK_DLL_NAME" ]]; then
    echo "$FALLBACK_DLL_NAME"
    return
  fi

  local found
  found="$(find "$app_dir" -maxdepth 1 -type f -name '*.dll' | sed -n '1p' || true)"
  if [[ -n "$found" ]]; then
    basename "$found"
    return
  fi

  err "Keine startbare DLL im Installationsverzeichnis gefunden. Erwartet z.B. '$DLL_NAME'."
  exit 1
}

write_appsettings() {
  local app_dir="$1"
  local data_dir="$2"
  local log_dir="$3"
  local port="$4"

  if [[ -f "$app_dir/appsettings.json" ]]; then
    cp -a "$app_dir/appsettings.json" "$app_dir/appsettings.json.before-a4w-install.$(date +%Y%m%d-%H%M%S)"
    warn "Vorhandene appsettings.json wurde gesichert."
  fi

  cat > "$app_dir/appsettings.json" <<JSON
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Storage": {
    "Mode": "Installed",
    "DataRoot": "$data_dir",
    "LogsRoot": "$log_dir"
  },
  "Urls": "http://127.0.0.1:$port",
  "AllowedHosts": "*"
}
JSON
}

write_systemd_service() {
  local app_dir="$1"
  local data_dir="$2"
  local log_dir="$3"
  local port="$4"
  local service_user="$5"
  local service_group="$6"
  local dll="$7"
  local pdf_browser="$8"

  cat > "/etc/systemd/system/${SERVICE_NAME}.service" <<SERVICE
[Unit]
Description=A4W Auftrag4Works ASP.NET Core Server
After=network.target

[Service]
WorkingDirectory=$app_dir
ExecStart=/usr/bin/dotnet "$app_dir/$dll"
Restart=always
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=$SERVICE_NAME
User=$service_user
Group=$service_group
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=ASPNETCORE_URLS=http://127.0.0.1:$port
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=A4W_DATA_ROOT=$data_dir
Environment=A4W_LOGS_ROOT=$log_dir
${pdf_browser:+Environment=A4W_PDF_BROWSER=$pdf_browser}

[Install]
WantedBy=multi-user.target
SERVICE
}

write_nginx_hint() {
  local app_dir="$1"
  local port="$2"
  cat > "$app_dir/nginx-a4w-plesk-directives.conf" <<NGINX
# A4W Auftrag4Works - Plesk/Nginx Zusatzanweisungen
# In Plesk: Domain/Subdomain > Apache & nginx-Einstellungen > Zusätzliche nginx-Anweisungen

location / {
    proxy_pass http://127.0.0.1:$port;
    proxy_http_version 1.1;
    proxy_set_header Upgrade \$http_upgrade;
    proxy_set_header Connection keep-alive;
    proxy_set_header Host \$host;
    proxy_cache_bypass \$http_upgrade;
    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto \$scheme;
    proxy_read_timeout 300;
    proxy_connect_timeout 300;
    proxy_send_timeout 300;
}
NGINX
}

validate_port() {
  local port="$1"
  if ! [[ "$port" =~ ^[0-9]+$ ]] || [[ "$port" -lt 1024 || "$port" -gt 65535 ]]; then
    err "Ungueltiger Port '$port'. Bitte einen lokalen Port zwischen 1024 und 65535 verwenden."
    exit 1
  fi

  if command_exists ss && ss -ltn "( sport = :$port )" | tail -n +2 | grep -q .; then
    warn "Port $port ist bereits belegt."
    if ! ask_yes_no "Trotzdem fortfahren? Nur sinnvoll, wenn dies bereits der bestehende A4W-Dienst ist." "nein"; then
      exit 1
    fi
  fi
}

extract_plesk_domain_from_path() {
  local path="$1"
  if [[ "$path" =~ ^/var/www/vhosts/([^/]+)/([^/]+) ]]; then
    echo "${BASH_REMATCH[2]}"
    return
  fi
  if [[ "$path" =~ ^/var/www/vhosts/([^/]+) ]]; then
    echo "${BASH_REMATCH[1]}"
    return
  fi
  echo ""
}

write_install_summary() {
  local app_dir="$1"
  local port="$2"
  local service_user="$3"
  local service_group="$4"
  local domain="$5"
  local pdf_browser="$6"
  local summary="$app_dir/A4W_INSTALLATION_HINWEISE.txt"
  cat > "$summary" <<SUMMARY
A4W Auftrag4Works Installation
================================

Dienst:
  systemctl status $SERVICE_NAME --no-pager
  journalctl -u $SERVICE_NAME -n 100 --no-pager
  sudo /bin/bash $app_dir/a4w-maintenance.sh

App:
  Pfad:      $app_dir
  Benutzer:  $service_user
  Gruppe:    $service_group
  Port:      http://127.0.0.1:$port
  PDF:       ${pdf_browser:-Kein Chromium/Chrome gefunden - HTML bleibt vorhanden, PDF bitte nach Browserinstallation erneut erzeugen}

Web-Update:
  Helper:    $ROOT_UPDATE_HELPER
  Sudoers:   $SUDOERS_UPDATE_FILE
  Aufruf:    sudo $ROOT_UPDATE_HELPER --yes '$app_dir/a4w-data/Updates/A4W-Auftrag4Works-Linux-Server-<version>.zip'

Lokaler Test:
  curl -I http://127.0.0.1:$port/

Plesk:
  1. Domain/Subdomain oeffnen${domain:+: $domain}
  2. Apache & nginx-Einstellungen
  3. Proxy-Modus deaktivieren, wenn ein eigener location / Block verwendet wird
  4. Inhalt aus $app_dir/nginx-a4w-plesk-directives.conf in "Zusaetzliche nginx-Anweisungen" eintragen
  5. SSL/Let's Encrypt aktivieren

Wenn Plesk "duplicate location /" meldet, ist der Proxy-Modus meist noch aktiv.

PDF-Erzeugung:
  Monats-/Jahresabschluss-PDFs und Beleg-PDFs werden aus HTML ueber Chromium/Chrome/Edge erstellt.
  Falls PDF fehlt: apt install chromium oder A4W_PDF_BROWSER=/voller/pfad/zum/browser in der systemd-Unit setzen.

Installationslog:
  $LOG_FILE
SUMMARY
  chown "$service_user:$service_group" "$summary" || true
  chmod 640 "$summary" || true
}

install_web_update_helper() {
  local app_dir="$1"
  local service_user="$2"
  local update_script="$app_dir/update-a4w-linux.sh"

  if [[ ! -f "$update_script" ]]; then
    warn "update-a4w-linux.sh wurde im App-Verzeichnis nicht gefunden. Web-Update-Helper wird nicht eingerichtet."
    return
  fi

  if ! ask_yes_no "Soll ein abgesicherter sudoers-Helper fuer automatische Updates aus der Web-App eingerichtet werden?" "nein"; then
    info "Web-Update-Helper wurde uebersprungen. Updates koennen weiter per SSH/root ausgefuehrt werden."
    return
  fi

  if ! command_exists visudo; then
    warn "visudo wurde nicht gefunden. Sudoers-Eintrag wird nicht automatisch geschrieben."
    return
  fi

  cp -a "$update_script" "$ROOT_UPDATE_HELPER"
  chown root:root "$ROOT_UPDATE_HELPER"
  chmod 750 "$ROOT_UPDATE_HELPER"

  cat > "$SUDOERS_UPDATE_FILE" <<SUDOERS
# A4W Auftrag4Works Web-Update-Helper
# Erlaubt dem Dienstbenutzer nur den root-eigenen Update-Helper mit --yes.
$service_user ALL=(root) NOPASSWD: $ROOT_UPDATE_HELPER --yes *
SUDOERS
  chown root:root "$SUDOERS_UPDATE_FILE"
  chmod 440 "$SUDOERS_UPDATE_FILE"

  if visudo -cf "$SUDOERS_UPDATE_FILE" >/dev/null; then
    log "Web-Update-Helper eingerichtet: $ROOT_UPDATE_HELPER"
    log "Sudoers-Freigabe eingerichtet: $SUDOERS_UPDATE_FILE"
  else
    rm -f "$SUDOERS_UPDATE_FILE"
    err "Sudoers-Pruefung fehlgeschlagen. Eintrag wurde entfernt."
    exit 1
  fi
}

test_local_http() {
  local port="$1"
  if command_exists curl; then
    if curl -fsS -I "http://127.0.0.1:$port/" >/dev/null 2>&1; then
      log "Lokaler HTTP-Test erfolgreich: http://127.0.0.1:$port/"
    else
      warn "Lokaler HTTP-Test war nicht erfolgreich. Bitte journalctl und systemctl pruefen."
    fi
  else
    warn "curl nicht gefunden; lokaler HTTP-Test wurde uebersprungen."
  fi
}

main() {
  need_root
  preflight_system

  echo "============================================================"
  echo " $APP_NAME - Linux/Plesk Installer $SCRIPT_VERSION"
  echo "============================================================"
  echo " Installationslog: $LOG_FILE"
  echo ""

  local default_app_dir
  default_app_dir="$(find_default_app_dir)"

  local app_dir
  app_dir="$(ask "Installationsverzeichnis" "$default_app_dir")"
  app_dir="${app_dir%/}"

  local default_data_dir="$app_dir/a4w-data"
  local default_log_dir="$app_dir/a4w-logs"
  local data_dir log_dir port
  data_dir="$(ask "Datenverzeichnis" "$default_data_dir")"
  log_dir="$(ask "Logverzeichnis" "$default_log_dir")"
  port="$(ask "Lokaler Kestrel-Port" "$DEFAULT_PORT")"
  validate_port "$port"

  local detected_user
  detected_user="$(find_plesk_owner_for_dir "$app_dir")"
  if [[ "$detected_user" == "root" ]]; then
    # In Plesk-Verzeichnissen ist root als Owner manchmal durch Entpacken entstanden.
    # Dann lieber bekannten Plesk-User aus dem Pfad nicht raten, sondern www-data vorschlagen.
    detected_user="www-data"
  fi

  local service_user service_group
  service_user="$(ask "Linux-Benutzer fuer den Dienst" "$detected_user")"
  service_group="$(validate_user_and_group "$service_user")"

  echo ""
  echo "Ermittelte Rechte:"
  echo "  Benutzer: $service_user"
  echo "  Gruppe:   $service_group"
  echo ""

  check_runtime_dependencies
  install_dotnet_runtime_if_missing
  install_pdf_browser_if_missing
  local pdf_browser
  pdf_browser="$(find_pdf_browser)"

  mkdir -p "$app_dir" "$data_dir" "$log_dir"

  local dll
  dll="$(find_app_dll "$app_dir")"
  log "Start-DLL: $dll"

  write_appsettings "$app_dir" "$data_dir" "$log_dir" "$port"
  write_systemd_service "$app_dir" "$data_dir" "$log_dir" "$port" "$service_user" "$service_group" "$dll" "$pdf_browser"
  write_nginx_hint "$app_dir" "$port"
  local plesk_domain
  plesk_domain="$(extract_plesk_domain_from_path "$app_dir")"
  write_install_summary "$app_dir" "$port" "$service_user" "$service_group" "$plesk_domain" "$pdf_browser"
  install_web_update_helper "$app_dir" "$service_user"

  # Rechte bewusst konservativ: Programm/Daten/Logs gehoeren dem Dienstnutzer und dessen echter primärer Gruppe.
  chown -R "$service_user:$service_group" "$app_dir" "$data_dir" "$log_dir"
  find "$app_dir" -type d -exec chmod 750 {} \; || true
  find "$app_dir" -type f -exec chmod 640 {} \; || true
  chmod 750 "$app_dir" "$data_dir" "$log_dir"

  # Shell-Skripte im Ordner ausführbar lassen, falls vorhanden.
  find "$app_dir" -maxdepth 1 -type f -name '*.sh' -exec chmod 750 {} \; || true

  systemctl daemon-reload
  systemctl enable "$SERVICE_NAME"
  systemctl restart "$SERVICE_NAME"

  echo ""
  systemctl status "$SERVICE_NAME" --no-pager || true
  test_local_http "$port"

  echo ""
  echo "============================================================"
  log "Installation abgeschlossen."
  echo ""
  echo "Dienst pruefen:"
  echo "  systemctl status $SERVICE_NAME --no-pager"
  echo "  journalctl -u $SERVICE_NAME -n 100 --no-pager"
  echo "  sudo /bin/bash $app_dir/a4w-maintenance.sh"
  echo ""
  echo "Lokaler Test auf dem Server:"
  echo "  curl -I http://127.0.0.1:$port/"
  echo ""
  echo "Plesk/Nginx Zusatzanweisungen wurden hier abgelegt:"
  echo "  $app_dir/nginx-a4w-plesk-directives.conf"
  echo "Installationshinweise:"
  echo "  $app_dir/A4W_INSTALLATION_HINWEISE.txt"
  echo "Installationslog:"
  echo "  $LOG_FILE"
  echo ""
  echo "Diese Anweisungen in Plesk bei der Subdomain eintragen:"
  echo "  Domain/Subdomain > Apache & nginx-Einstellungen > Zusätzliche nginx-Anweisungen"
  echo "  Wichtig: Proxy-Modus deaktivieren, wenn Plesk sonst 'duplicate location /' meldet."
  echo "============================================================"
}

main "$@"
