#!/bin/bash

#
# Production SSL Certificate Setup Script for michaelschiemer.de
# Sets up Let's Encrypt SSL certificates on the production server
#

set -euo pipefail

# Configuration
SERVER_USER="deploy"
SERVER_IP="94.16.110.151"
REMOTE_PATH="/home/deploy/michaelschiemer"
DOMAIN="michaelschiemer.de"
EMAIL="michael@michaelschiemer.de"  # Change this to your email
SSH_OPTS="-i ~/.ssh/production -o StrictHostKeyChecking=no"

# Colors for output
GREEN="\e[32m"
YELLOW="\e[33m"
RED="\e[31m"
BLUE="\e[34m"
RESET="\e[0m"

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

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

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

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

# Check if domain resolves to production server
check_dns() {
    log_info "Checking DNS resolution for $DOMAIN..."
    local resolved_ip=$(dig +short "$DOMAIN" | head -1)
    
    if [[ "$resolved_ip" == "$SERVER_IP" ]]; then
        log_success "Domain $DOMAIN resolves correctly to $SERVER_IP"
    else
        log_warning "Domain $DOMAIN resolves to $resolved_ip (expected: $SERVER_IP)"
        log_warning "SSL certificate might fail if DNS is incorrect"
    fi
}

# Install certbot on production server
install_certbot() {
    log_info "Installing certbot on production server..."
    
    ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" '
        # Update package list
        sudo apt update
        
        # Install snapd if not present
        if ! command -v snap &> /dev/null; then
            sudo apt install -y snapd
        fi
        
        # Install certbot via snap
        if ! command -v certbot &> /dev/null; then
            sudo snap install core; sudo snap refresh core
            sudo snap install --classic certbot
            sudo ln -sf /snap/bin/certbot /usr/bin/certbot
        fi
        
        # Verify certbot installation
        certbot --version
    '
    
    log_success "Certbot installed successfully"
}

# Stop nginx temporarily for certificate generation
prepare_nginx() {
    log_info "Preparing nginx for certificate generation..."
    
    ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
        cd $REMOTE_PATH
        
        # Stop nginx container temporarily
        docker compose down web 2>/dev/null || true
        
        # Create ssl directory
        mkdir -p ssl
        
        # Create temporary nginx config for certbot
        cat > ssl/nginx-temp.conf << 'EOF'
server {
    listen 80;
    server_name $DOMAIN;
    
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    
    location / {
        return 301 https://\$server_name\$request_uri;
    }
}
EOF
        
        # Start temporary nginx for certificate validation
        docker run -d --name nginx-temp \\
            -p 80:80 \\
            -v \$(pwd)/ssl/nginx-temp.conf:/etc/nginx/conf.d/default.conf \\
            -v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
            nginx:alpine
    "
    
    log_success "Nginx prepared for certificate generation"
}

# Generate Let's Encrypt certificate
generate_certificate() {
    log_info "Generating Let's Encrypt certificate for $DOMAIN..."
    
    ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
        cd $REMOTE_PATH
        
        # Create webroot directory
        mkdir -p ssl/certbot-webroot
        
        # Generate certificate
        docker run --rm \\
            -v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
            -v \$(pwd)/ssl:/etc/letsencrypt \\
            certbot/certbot certonly \\
                --webroot \\
                --webroot-path=/var/www/certbot \\
                --email $EMAIL \\
                --agree-tos \\
                --no-eff-email \\
                -d $DOMAIN
        
        # Copy certificates to expected location
        if [ -d \"ssl/live/$DOMAIN\" ]; then
            cp ssl/live/$DOMAIN/fullchain.pem ssl/fullchain.pem
            cp ssl/live/$DOMAIN/privkey.pem ssl/privkey.pem
            chmod 644 ssl/fullchain.pem ssl/privkey.pem
            log_success 'SSL certificates generated and copied'
        else
            log_error 'Certificate generation failed'
            exit 1
        fi
    "
    
    log_success "SSL certificate generated successfully"
}

# Clean up temporary nginx
cleanup_nginx() {
    log_info "Cleaning up temporary nginx..."
    
    ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
        cd $REMOTE_PATH
        
        # Stop and remove temporary nginx
        docker stop nginx-temp 2>/dev/null || true
        docker rm nginx-temp 2>/dev/null || true
        
        # Clean up temporary files
        rm -f ssl/nginx-temp.conf
        rm -rf ssl/certbot-webroot
    "
    
    log_success "Temporary nginx cleaned up"
}

# Start the application with SSL
start_application() {
    log_info "Starting application with SSL certificates..."
    
    ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
        cd $REMOTE_PATH
        
        # Start all services
        docker compose up -d
        
        # Wait for services to start
        sleep 10
        
        # Check container status
        docker compose ps
    "
    
    log_success "Application started with SSL certificates"
}

# Test SSL certificate
test_ssl() {
    log_info "Testing SSL certificate..."
    
    # Test HTTPS connection
    if curl -sSf "https://$DOMAIN" > /dev/null 2>&1; then
        log_success "HTTPS connection successful!"
    else
        log_warning "HTTPS connection test failed - checking certificate..."
    fi
    
    # Check certificate details
    echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null | openssl x509 -noout -dates
    
    log_info "SSL setup completed!"
    log_success "Your site should now be accessible at: https://$DOMAIN"
}

# Setup certificate renewal
setup_renewal() {
    log_info "Setting up automatic certificate renewal..."
    
    ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "
        # Create renewal script
        cat > /home/deploy/renew-certificates.sh << 'RENEWAL_SCRIPT'
#!/bin/bash
cd /home/deploy/michaelschiemer

# Stop nginx container
docker compose down web

# Renew certificate
docker run --rm \\
    -v \$(pwd)/ssl:/etc/letsencrypt \\
    -v \$(pwd)/ssl/certbot-webroot:/var/www/certbot \\
    certbot/certbot renew \\
        --webroot \\
        --webroot-path=/var/www/certbot

# Copy renewed certificates
if [ -f \"ssl/live/$DOMAIN/fullchain.pem\" ]; then
    cp ssl/live/$DOMAIN/fullchain.pem ssl/fullchain.pem
    cp ssl/live/$DOMAIN/privkey.pem ssl/privkey.pem
    chmod 644 ssl/fullchain.pem ssl/privkey.pem
fi

# Restart services
docker compose up -d
RENEWAL_SCRIPT

        chmod +x /home/deploy/renew-certificates.sh
        
        # Add cron job for automatic renewal (runs twice daily)
        (crontab -l 2>/dev/null; echo '0 12,0 * * * /home/deploy/renew-certificates.sh >> /var/log/letsencrypt-renewal.log 2>&1') | crontab -
    "
    
    log_success "Automatic certificate renewal configured"
}

# Main execution
main() {
    log_info "Starting SSL certificate setup for $DOMAIN"
    
    # Check DNS
    check_dns
    
    # Install certbot
    install_certbot
    
    # Prepare nginx
    prepare_nginx
    
    # Generate certificate
    generate_certificate
    
    # Clean up temporary nginx
    cleanup_nginx
    
    # Start application
    start_application
    
    # Test SSL
    test_ssl
    
    # Setup renewal
    setup_renewal
    
    log_success "SSL certificate setup completed successfully!"
    log_info "Next steps:"
    echo "  1. Test your site: https://$DOMAIN"
    echo "  2. Certificates will auto-renew twice daily"
    echo "  3. Check renewal logs: ssh $SERVER_USER@$SERVER_IP 'tail -f /var/log/letsencrypt-renewal.log'"
}

# Show usage
show_usage() {
    echo "Usage: $0 [--help]"
    echo ""
    echo "This script sets up Let's Encrypt SSL certificates for $DOMAIN"
    echo ""
    echo "Prerequisites:"
    echo "  - Domain $DOMAIN must point to $SERVER_IP"
    echo "  - SSH access to production server configured"
    echo "  - Docker and docker-compose installed on server"
    echo ""
    echo "Options:"
    echo "  --help    Show this help message"
}

# Parse arguments
case "${1:-}" in
    --help|-h)
        show_usage
        exit 0
        ;;
    "")
        main
        ;;
    *)
        log_error "Unknown option: $1"
        show_usage
        exit 1
        ;;
esac