#!/bin/bash

# SSL/TLS Setup Script für YourPart Daemon
# Erstellt oder verwaltet SSL-Zertifikate für WebSocket Secure (WSS)
# Unterstützt Self-Signed Certificates und Let's Encrypt

set -e

# Farben für Logging
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

CERT_DIR="/etc/yourpart"
CERT_FILE="$CERT_DIR/server.crt"
KEY_FILE="$CERT_DIR/server.key"
CSR_FILE="$CERT_DIR/server.csr"

# Let's Encrypt Verzeichnisse
LETSENCRYPT_DIR="/etc/letsencrypt/live"
LETSENCRYPT_CERT="$LETSENCRYPT_DIR/your-part.de/fullchain.pem"
LETSENCRYPT_KEY="$LETSENCRYPT_DIR/your-part.de/privkey.pem"

# Apache2 Zertifikate (Ubuntu/Debian)
APACHE2_CERT="/etc/ssl/certs/ssl-cert-snakeoil.pem"
APACHE2_KEY="/etc/ssl/private/ssl-cert-snakeoil.key"

# Apache2 Let's Encrypt Zertifikate
APACHE2_LE_CERT="/etc/letsencrypt/live/your-part.de/fullchain.pem"
APACHE2_LE_KEY="/etc/letsencrypt/live/your-part.de/privkey.pem"

# Prüfe ob OpenSSL installiert ist
if ! command -v openssl &> /dev/null; then
    log_error "OpenSSL ist nicht installiert!"
    exit 1
fi

# Prüfe ob wir sudo-Rechte haben
if ! sudo -n true 2>/dev/null; then
    log_info "Einige Operationen benötigen sudo-Rechte für SSL-Verzeichnisse..."
fi

# Funktionen
setup_letsencrypt() {
    log_info "Let's Encrypt Setup für your-part.de"
    
    # Prüfe ob certbot installiert ist
    if ! command -v certbot &> /dev/null; then
        log_error "Certbot ist nicht installiert!"
        log_info "Installiere Certbot..."
        if command -v apt &> /dev/null; then
            sudo apt update
            sudo apt install -y certbot
        elif command -v zypper &> /dev/null; then
            sudo zypper install -y certbot
        else
            log_error "Paketmanager nicht unterstützt. Installiere Certbot manuell."
            exit 1
        fi
    fi
    
    # Prüfe ob Let's Encrypt Zertifikate bereits existieren
    if [ -f "$LETSENCRYPT_CERT" ] && [ -f "$LETSENCRYPT_KEY" ]; then
        log_info "Let's Encrypt Zertifikate existieren bereits"
        
        # Prüfe Gültigkeit
        if openssl x509 -in "$LETSENCRYPT_CERT" -text -noout &> /dev/null; then
            log_success "Let's Encrypt Zertifikat ist gültig"
            
            # Zeige Zertifikats-Informationen
            log_info "Let's Encrypt Zertifikats-Informationen:"
            openssl x509 -in "$LETSENCRYPT_CERT" -text -noout | grep -E "(Subject:|Not Before|Not After|DNS:)"
            
            read -p "Möchten Sie die Zertifikate erneuern? (y/N): " -n 1 -r
            echo
            if [[ ! $REPLY =~ ^[Yy]$ ]]; then
                log_info "Zertifikate bleiben unverändert"
                return 0
            fi
        else
            log_warning "Let's Encrypt Zertifikat ist ungültig, erstelle neue..."
        fi
    fi
    
    # Erstelle oder erneuere Let's Encrypt Zertifikat
    log_info "Erstelle/erneuere Let's Encrypt Zertifikat für your-part.de..."
    
    # Prüfe ob Port 80 verfügbar ist (für HTTP-01 Challenge)
    if ! sudo netstat -tlnp | grep -q ":80 "; then
        log_warning "Port 80 ist nicht verfügbar. Stelle sicher, dass kein anderer Service läuft."
        log_info "Oder verwende DNS-01 Challenge mit --dns-cloudflare oder ähnlich"
    fi
    
    # Erstelle Zertifikat mit HTTP-01 Challenge
    sudo certbot certonly --standalone -d your-part.de --non-interactive --agree-tos --email admin@your-part.de
    
    if [ $? -eq 0 ]; then
        log_success "Let's Encrypt Zertifikat erfolgreich erstellt!"
        
        # Erstelle Symlinks zu den Zertifikaten
        sudo ln -sf "$LETSENCRYPT_CERT" "$CERT_FILE"
        sudo ln -sf "$LETSENCRYPT_KEY" "$KEY_FILE"
        
        # Setze korrekte Berechtigungen
        sudo chown yourpart:yourpart "$CERT_FILE" "$KEY_FILE"
        sudo chmod 644 "$CERT_FILE"
        sudo chmod 600 "$KEY_FILE"
        
        # Zeige Zertifikats-Informationen
        log_info "Let's Encrypt Zertifikats-Informationen:"
        openssl x509 -in "$CERT_FILE" -text -noout | grep -E "(Subject:|Not Before|Not After|DNS:)"
        
        # Erstelle Auto-Renewal Cron Job
        setup_auto_renewal
        
    else
        log_error "Let's Encrypt Zertifikat konnte nicht erstellt werden!"
        exit 1
    fi
}

setup_apache2_certificates() {
    log_info "Apache2 Zertifikate Setup"
    
    # Prüfe ob Apache2 installiert ist
    if ! command -v apache2 &> /dev/null && ! command -v httpd &> /dev/null; then
        log_warning "Apache2 ist nicht installiert, aber wir können trotzdem die Zertifikate verwenden"
    fi
    
    # Prüfe verschiedene Apache2 Zertifikats-Pfade (priorisiert nach Qualität)
    APACHE2_CERT_PATHS=(
        "/etc/letsencrypt/live/your-part.de/fullchain.pem"
        "/etc/letsencrypt/live/$(hostname)/fullchain.pem"
        "/etc/apache2/ssl/apache.crt"
        "/etc/httpd/ssl/apache.crt"
        "/etc/ssl/certs/apache-selfsigned.crt"
        "/etc/ssl/certs/ssl-cert-snakeoil.pem"
    )
    
    APACHE2_KEY_PATHS=(
        "/etc/letsencrypt/live/your-part.de/privkey.pem"
        "/etc/letsencrypt/live/$(hostname)/privkey.pem"
        "/etc/apache2/ssl/apache.key"
        "/etc/httpd/ssl/apache.key"
        "/etc/ssl/private/apache-selfsigned.key"
        "/etc/ssl/private/ssl-cert-snakeoil.key"
    )
    
    # Finde verfügbare Zertifikate
    FOUND_CERT=""
    FOUND_KEY=""
    
    for cert_path in "${APACHE2_CERT_PATHS[@]}"; do
        if sudo test -f "$cert_path"; then
            FOUND_CERT="$cert_path"
            log_info "Gefundenes Zertifikat: $cert_path"
            break
        fi
    done
    
    for key_path in "${APACHE2_KEY_PATHS[@]}"; do
        if sudo test -f "$key_path"; then
            FOUND_KEY="$key_path"
            log_info "Gefundener Private Key: $key_path"
            break
        fi
    done
    
    if [ -z "$FOUND_CERT" ] || [ -z "$FOUND_KEY" ]; then
        log_error "Keine Apache2-Zertifikate gefunden!"
        log_info "Verfügbare Pfade:"
        for path in "${APACHE2_CERT_PATHS[@]}" "${APACHE2_KEY_PATHS[@]}"; do
            if sudo test -f "$path"; then
                log_info "  ✓ $path"
            else
                log_info "  ✗ $path"
            fi
        done
        exit 1
    fi
    
    # Warnung für Snakeoil-Zertifikate
    if [[ "$FOUND_CERT" == *"snakeoil"* ]]; then
        log_warning "ACHTUNG: Snakeoil-Zertifikat erkannt!"
        log_warning "Dieses Zertifikat ist nur für localhost gültig, nicht für your-part.de"
        log_warning "Für Produktionsumgebungen sollten Sie Let's Encrypt verwenden"
        echo ""
        read -p "Möchten Sie trotzdem fortfahren? (y/N): " -n 1 -r
        echo ""
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Setup abgebrochen. Verwenden Sie Option 2 für Let's Encrypt."
            exit 0
        fi
    fi
    
    # Erstelle Symlinks zu den Apache2-Zertifikaten
    log_info "Erstelle Symlinks zu Apache2-Zertifikaten..."
    sudo ln -sf "$FOUND_CERT" "$CERT_FILE"
    sudo ln -sf "$FOUND_KEY" "$KEY_FILE"
    
    # Setze korrekte Berechtigungen
    sudo chown yourpart:yourpart "$CERT_FILE" "$KEY_FILE"
    sudo chmod 644 "$CERT_FILE"
    sudo chmod 600 "$KEY_FILE"
    
    log_success "Apache2-Zertifikate erfolgreich verlinkt!"
    
    # Zeige Zertifikats-Informationen
    log_info "Apache2-Zertifikats-Informationen:"
    openssl x509 -in "$CERT_FILE" -text -noout | grep -E "(Subject:|Not Before|Not After|DNS:)"
    
    # Prüfe ob es sich um Let's Encrypt-Zertifikate handelt
    if [[ "$FOUND_CERT" == *"letsencrypt"* ]]; then
        log_info "Let's Encrypt-Zertifikate erkannt, richte Auto-Renewal ein..."
        setup_auto_renewal
    else
        log_warning "Self-Signed oder andere Zertifikate erkannt - kein Auto-Renewal eingerichtet"
    fi
}

setup_auto_renewal() {
    log_info "Richte automatische Zertifikats-Erneuerung ein..."
    
    # Erstelle Renewal Script
    sudo tee /etc/yourpart/renew-ssl.sh > /dev/null << 'EOF'
#!/bin/bash
# Automatische SSL-Zertifikats-Erneuerung für YourPart Daemon

CERT_DIR="/etc/yourpart"
LETSENCRYPT_CERT="/etc/letsencrypt/live/your-part.de/fullchain.pem"
LETSENCRYPT_KEY="/etc/letsencrypt/live/your-part.de/privkey.pem"

# Erneuere Zertifikat
certbot renew --quiet

if [ $? -eq 0 ]; then
    # Aktualisiere Symlinks
    ln -sf "$LETSENCRYPT_CERT" "$CERT_DIR/server.crt"
    ln -sf "$LETSENCRYPT_KEY" "$CERT_DIR/server.key"
    
    # Setze Berechtigungen
    chown yourpart:yourpart "$CERT_DIR/server.crt" "$CERT_DIR/server.key"
    chmod 644 "$CERT_DIR/server.crt"
    chmod 600 "$CERT_DIR/server.key"
    
    # Starte Daemon neu
    systemctl reload yourpart-daemon
    
    echo "$(date): SSL-Zertifikat erfolgreich erneuert" >> /var/log/yourpart/ssl-renewal.log
fi
EOF
    
    sudo chmod +x /etc/yourpart/renew-ssl.sh
    
    # Füge Cron Job hinzu (täglich um 2:30 Uhr)
    (sudo crontab -l 2>/dev/null; echo "30 2 * * * /etc/yourpart/renew-ssl.sh") | sudo crontab -
    
    log_success "Automatische Erneuerung eingerichtet (täglich um 2:30 Uhr)"
}

log_info "SSL/TLS Setup für YourPart Daemon"

# Benutzerauswahl
echo ""
log_info "Wählen Sie den Zertifikatstyp:"
echo "1) Self-Signed Certificate (für Entwicklung/Testing)"
echo "2) Let's Encrypt Certificate (für Produktion)"
echo "3) Bestehende Let's Encrypt Zertifikate verwenden"
echo "4) Apache2-Zertifikate verwenden (empfohlen für Ubuntu)"
echo ""
read -p "Ihre Wahl (1-4): " -n 1 -r
echo ""

case $REPLY in
    1)
        log_info "Self-Signed Certificate wird erstellt..."
        CERT_TYPE="self-signed"
        ;;
    2)
        log_info "Let's Encrypt Certificate wird erstellt..."
        CERT_TYPE="letsencrypt"
        ;;
    3)
        log_info "Bestehende Let's Encrypt Zertifikate werden verwendet..."
        CERT_TYPE="existing-letsencrypt"
        ;;
    4)
        log_info "Apache2-Zertifikate werden verwendet..."
        CERT_TYPE="apache2"
        ;;
    *)
        log_error "Ungültige Auswahl!"
        exit 1
        ;;
esac

# Erstelle Zertifikats-Verzeichnis falls nicht vorhanden
if [ ! -d "$CERT_DIR" ]; then
    log_info "Erstelle Zertifikats-Verzeichnis: $CERT_DIR"
    sudo mkdir -p "$CERT_DIR"
fi

# Führe entsprechenden Setup-Typ aus
case $CERT_TYPE in
    "self-signed")
        # Prüfe ob bereits Zertifikate existieren
        if [ -f "$CERT_FILE" ] && [ -f "$KEY_FILE" ]; then
            log_info "Zertifikate existieren bereits"
            
            # Prüfe Gültigkeit der Zertifikate
            if openssl x509 -in "$CERT_FILE" -text -noout &> /dev/null; then
                log_success "Zertifikat ist gültig"
                
                # Zeige Zertifikats-Informationen
                log_info "Zertifikats-Informationen:"
                openssl x509 -in "$CERT_FILE" -text -noout | grep -E "(Subject:|Not Before|Not After|DNS:)"
                
                read -p "Möchten Sie neue Zertifikate erstellen? (y/N): " -n 1 -r
                echo
                if [[ ! $REPLY =~ ^[Yy]$ ]]; then
                    log_info "Zertifikate bleiben unverändert"
                    exit 0
                fi
            else
                log_warning "Zertifikat ist ungültig, erstelle neue..."
            fi
        fi

        log_info "Erstelle neue Self-Signed SSL-Zertifikate..."

        # Erstelle Private Key
        log_info "Erstelle Private Key..."
        sudo openssl genrsa -out "$KEY_FILE" 2048
        sudo chmod 600 "$KEY_FILE"
        sudo chown yourpart:yourpart "$KEY_FILE"

        # Erstelle Certificate Signing Request (CSR)
        log_info "Erstelle Certificate Signing Request..."
        sudo openssl req -new -key "$KEY_FILE" -out "$CSR_FILE" -subj "/C=DE/ST=Germany/L=Berlin/O=YourPart/OU=IT/CN=your-part.de"

        # Erstelle Self-Signed Certificate
        log_info "Erstelle Self-Signed Certificate..."
        sudo openssl x509 -req -days 365 -in "$CSR_FILE" -signkey "$KEY_FILE" -out "$CERT_FILE"

        # Setze korrekte Berechtigungen
        sudo chmod 644 "$CERT_FILE"
        sudo chown yourpart:yourpart "$CERT_FILE"

        # Lösche CSR-Datei (nicht mehr benötigt)
        sudo rm -f "$CSR_FILE"

        log_success "Self-Signed SSL-Zertifikate erfolgreich erstellt!"
        ;;
        
    "letsencrypt")
        setup_letsencrypt
        ;;
        
    "existing-letsencrypt")
        if [ -f "$LETSENCRYPT_CERT" ] && [ -f "$LETSENCRYPT_KEY" ]; then
            log_info "Verwende bestehende Let's Encrypt Zertifikate..."
            
            # Erstelle Symlinks zu den Zertifikaten
            sudo ln -sf "$LETSENCRYPT_CERT" "$CERT_FILE"
            sudo ln -sf "$LETSENCRYPT_KEY" "$KEY_FILE"
            
            # Setze korrekte Berechtigungen
            sudo chown yourpart:yourpart "$CERT_FILE" "$KEY_FILE"
            sudo chmod 644 "$CERT_FILE"
            sudo chmod 600 "$KEY_FILE"
            
            log_success "Let's Encrypt Zertifikate erfolgreich verlinkt!"
            
            # Richte Auto-Renewal ein
            setup_auto_renewal
        else
            log_error "Let's Encrypt Zertifikate nicht gefunden in $LETSENCRYPT_DIR"
            log_info "Führen Sie zuerst 'certbot certonly' aus oder wählen Sie Option 2"
            exit 1
        fi
        ;;
        
    "apache2")
        setup_apache2_certificates
        ;;
esac

# Zeige Zertifikats-Informationen
log_info "Zertifikats-Informationen:"
openssl x509 -in "$CERT_FILE" -text -noout | grep -E "(Subject:|Not Before|Not After|DNS:)"

log_info ""
log_info "Nächste Schritte:"
log_info "1. Aktiviere SSL in der Konfiguration:"
log_info "   WEBSOCKET_SSL_ENABLED=true"
log_info "2. Starte den Daemon neu:"
log_info "   sudo systemctl restart yourpart-daemon"
log_info "3. Verbinde dich mit:"
log_info "   wss://your-part.de:4551"
log_info ""

case $CERT_TYPE in
    "self-signed")
        log_warning "Hinweis: Dies ist ein Self-Signed Certificate!"
        log_warning "Für Produktionsumgebungen verwenden Sie Let's Encrypt oder Apache2-Zertifikate."
        ;;
    "apache2")
        log_success "Apache2-Zertifikate erfolgreich konfiguriert!"
        log_info "Diese Zertifikate werden automatisch von Apache2 verwaltet."
        ;;
    *)
        log_success "Let's Encrypt Zertifikat ist produktionsbereit!"
        ;;
esac
