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

UI_HOST=""; WEBMAIL_HOST=""; MAIL_HOST=""; SSL_AUTO=0
while [[ $# -gt 0 ]]; do
  case "$1" in
    --ui-host)      UI_HOST="$2";      shift 2 ;;
    --webmail-host) WEBMAIL_HOST="$2"; shift 2 ;;
    --mail-host)    MAIL_HOST="$2";    shift 2 ;;
    --ssl-auto)     SSL_AUTO="$2";     shift 2 ;;
    *) shift ;;
  esac
done

PHPV=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
PHP_FPM_SOCK="/run/php/php${PHPV}-fpm.sock"
[ -S "$PHP_FPM_SOCK" ] || PHP_FPM_SOCK="/run/php/php-fpm.sock"

APP_DIR="/var/www/mailwolt"
NGINX_SITE="/etc/nginx/sites-available/mailwolt.conf"
ACME_ROOT="/var/www/letsencrypt"
mkdir -p "${ACME_ROOT}/.well-known/acme-challenge"

# --- Phase 1: HTTP-only Vhosts mit ACME-Challenge ---
cat > "${NGINX_SITE}" <<CONF
server {
  listen 80;
  listen [::]:80;
  server_name ${UI_HOST} ${WEBMAIL_HOST} ${MAIL_HOST};

  root ${APP_DIR}/public;
  index index.php index.html;

  location /.well-known/acme-challenge/ {
    root ${ACME_ROOT};
    try_files \$uri =404;
  }
  location / {
    try_files \$uri \$uri/ /index.php?\$query_string;
  }
  location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:${PHP_FPM_SOCK};
  }
  location ^~ /livewire/ {
    try_files \$uri /index.php?\$query_string;
  }
}
CONF

nginx -t && systemctl reload nginx

# --- Phase 2: Let's Encrypt Zertifikate holen ---
# Prüfen ob Server globales IPv6 hat (nötig wenn AAAA-Records existieren)
has_global_ipv6() {
  ip -6 addr show scope global 2>/dev/null | grep -q 'inet6'
}

cert_needs_action() {
  local domain="$1"
  local cert="/etc/letsencrypt/live/${domain}/fullchain.pem"
  [ ! -f "${cert}" ] && return 0
  # 0 = gültig für >10 Tage → überspringen; 1 = läuft ab → erneuern
  openssl x509 -checkend 864000 -noout -in "${cert}" 2>/dev/null && return 1
  return 0
}

certbot_safe() {
  local domain="$1"
  local has_aaaa=""
  # dig ist nicht immer installiert — Fallback auf getent
  if command -v dig >/dev/null 2>&1; then
    has_aaaa=$(dig +short AAAA "${domain}" 2>/dev/null | head -1) || has_aaaa=""
  else
    has_aaaa=$(getent ahostsv6 "${domain}" 2>/dev/null | awk '{print $1}' | head -1) || has_aaaa=""
  fi
  if [ -n "${has_aaaa}" ] && ! has_global_ipv6; then
    echo "[!] ${domain}: AAAA-Record vorhanden aber kein IPv6 auf diesem Server — Let's Encrypt würde fehlschlagen. Self-signed wird verwendet."
    return 1
  fi
  certbot certonly --webroot \
    -w "${ACME_ROOT}" \
    -d "${domain}" \
    --non-interactive --agree-tos \
    --email "webmaster@${domain}" \
    --no-eff-email
}

if [ "${SSL_AUTO}" = "1" ]; then
  for DOMAIN in "${UI_HOST}" "${WEBMAIL_HOST}" "${MAIL_HOST}"; do
    [ -z "${DOMAIN}" ] && continue
    if cert_needs_action "${DOMAIN}"; then
      certbot_safe "${DOMAIN}" || true
    fi
  done
fi

# --- Phase 3: Finale Vhosts ---
# Nur HTTPS wenn LE-Cert tatsächlich vorhanden, sonst HTTP-only (kein self-signed Fallback)
UI_HAS_CERT=0
WM_HAS_CERT=0
MAIL_HAS_CERT=0
[ -f "/etc/letsencrypt/live/${UI_HOST}/fullchain.pem" ]      && UI_HAS_CERT=1
[ -f "/etc/letsencrypt/live/${WEBMAIL_HOST}/fullchain.pem" ] && WM_HAS_CERT=1
[ -f "/etc/letsencrypt/live/${MAIL_HOST}/fullchain.pem" ]    && MAIL_HAS_CERT=1
(

if [ "${UI_HAS_CERT}" = "1" ] || [ "${WM_HAS_CERT}" = "1" ]; then
  # Mindestens ein Web-Cert vorhanden → HTTP-Redirect Block (inkl. MAIL_HOST für ACME-Renewal)
  cat <<CONF
server {
  listen 80;
  listen [::]:80;
  server_name ${UI_HOST} ${WEBMAIL_HOST} ${MAIL_HOST};

  location /.well-known/acme-challenge/ {
    root ${ACME_ROOT};
    try_files \$uri =404;
  }
  location / { return 301 https://\$host\$request_uri; }
}
CONF
else
  # Kein Cert → HTTP-only, App läuft auf Port 80 weiter
  cat <<CONF
server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name _;

  root ${APP_DIR}/public;
  index index.php index.html;

  location /.well-known/acme-challenge/ {
    root ${ACME_ROOT};
    try_files \$uri =404;
  }
  location / { try_files \$uri \$uri/ /index.php?\$query_string; }
  location ~ \.php\$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:${PHP_FPM_SOCK};
  }
  location ^~ /livewire/ { try_files \$uri /index.php?\$query_string; }
  location ~* \.(jpg|jpeg|png|gif|css|js|ico|svg)\$ { expires 30d; access_log off; }
}
CONF
fi

if [ -n "${UI_HOST}" ] && [ "${UI_HAS_CERT}" = "1" ]; then
  cat <<CONF

server {
  listen 443 ssl;
  listen [::]:443 ssl;
  http2 on;
  server_name ${UI_HOST};

  ssl_certificate     /etc/letsencrypt/live/${UI_HOST}/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/${UI_HOST}/privkey.pem;
  ssl_protocols       TLSv1.2 TLSv1.3;

  root ${APP_DIR}/public;
  index index.php index.html;

  location / { try_files \$uri \$uri/ /index.php?\$query_string; }
  location ~ \.php\$ {
    include snippets/fastcgi-php.conf;
    fastcgi_param HTTPS on;
    fastcgi_pass unix:${PHP_FPM_SOCK};
  }
  location ^~ /livewire/ { try_files \$uri /index.php?\$query_string; }
  location ~* \.(jpg|jpeg|png|gif|css|js|ico|svg)\$ { expires 30d; access_log off; }
}
CONF
fi

if [ -n "${WEBMAIL_HOST}" ] && [ "${WM_HAS_CERT}" = "1" ]; then
  cat <<CONF

server {
  listen 443 ssl;
  listen [::]:443 ssl;
  http2 on;
  server_name ${WEBMAIL_HOST};

  ssl_certificate     /etc/letsencrypt/live/${WEBMAIL_HOST}/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/${WEBMAIL_HOST}/privkey.pem;
  ssl_protocols       TLSv1.2 TLSv1.3;

  root ${APP_DIR}/public;
  index index.php index.html;

  location / { try_files \$uri \$uri/ /index.php?\$query_string; }
  location ~ \.php\$ {
    include snippets/fastcgi-php.conf;
    fastcgi_param HTTPS on;
    fastcgi_pass unix:${PHP_FPM_SOCK};
  }
  location ^~ /livewire/ { try_files \$uri /index.php?\$query_string; }
  location ~* \.(jpg|jpeg|png|gif|css|js|ico|svg)\$ { expires 30d; access_log off; }
}
CONF
fi
) > "${NGINX_SITE}"

# State-Dateien schreiben — korrekt pro Domain, nicht pauschal "done"
STATE_DIR="/var/lib/mailwolt/wizard"
if [ -d "${STATE_DIR}" ]; then
  # UI: done nur wenn LE-Cert tatsächlich vorhanden, sonst error
  if [ -f "${STATE_DIR}/ui" ]; then
    if [ "${UI_HAS_CERT}" = "1" ]; then
      printf "done" > "${STATE_DIR}/ui"
    else
      printf "error" > "${STATE_DIR}/ui"
    fi
  fi
  # Webmail: done nur wenn LE-Cert tatsächlich vorhanden, sonst error
  if [ -f "${STATE_DIR}/webmail" ]; then
    if [ "${WM_HAS_CERT}" = "1" ]; then
      printf "done" > "${STATE_DIR}/webmail"
    else
      printf "error" > "${STATE_DIR}/webmail"
    fi
  fi
  # Mail-Domain: LE-Cert für Postfix/Dovecot
  if [ -f "${STATE_DIR}/mail" ]; then
    if [ "${MAIL_HAS_CERT}" = "1" ]; then
      printf "done" > "${STATE_DIR}/mail"
    else
      printf "error" > "${STATE_DIR}/mail"
    fi
  fi

  # done-Signal: immer schreiben damit der 2s-Poll stoppt
  if [ "${UI_HAS_CERT}" = "1" ] || [ "${WM_HAS_CERT}" = "1" ]; then
    # Erst done schreiben, dann 6s warten bevor nginx auf HTTPS wechselt —
    # so hat der Browser Zeit den "Zum Login"-Button zu rendern bevor der Switch passiert
    printf "1" > "${STATE_DIR}/done"
    sleep 6
  else
    printf "0" > "${STATE_DIR}/done"
  fi
fi

# --- Phase 4: Postfix + Dovecot mit Mail-Domain-Zertifikat konfigurieren ---
if [ -n "${MAIL_HOST}" ] && [ "${MAIL_HAS_CERT}" = "1" ]; then
  MAIL_CERT="/etc/letsencrypt/live/${MAIL_HOST}/fullchain.pem"
  MAIL_KEY="/etc/letsencrypt/live/${MAIL_HOST}/privkey.pem"

  # Postfix
  if command -v postconf >/dev/null 2>&1; then
    postconf -e "smtpd_tls_cert_file = ${MAIL_CERT}"
    postconf -e "smtpd_tls_key_file  = ${MAIL_KEY}"
    postconf -e "smtp_tls_cert_file  = ${MAIL_CERT}"
    postconf -e "smtp_tls_key_file   = ${MAIL_KEY}"
    systemctl reload postfix 2>/dev/null || true
  fi

  # Dovecot
  if [ -d /etc/dovecot/conf.d ]; then
    cat > /etc/dovecot/conf.d/10-ssl.conf <<DCONF
ssl = yes
ssl_cert = <${MAIL_CERT}
ssl_key  = <${MAIL_KEY}
ssl_min_protocol = TLSv1.2
DCONF
    systemctl reload dovecot 2>/dev/null || true
  fi
fi

nginx -t && systemctl reload nginx
echo "mailwolt-apply-domains fertig"
