#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import os
import time
import urllib.parse
import mimetypes
import re
import traceback
import sys
import signal
import socket
import threading
import gc

# Konfiguration
PORT = 8081
UPLOAD_DIR = "uploads"
SERVER_ADDRESS = "77.90.60.235"  # Ändern Sie diese zu Ihrer Server-IP
ADMIN_USERNAME = "admin"
ADMIN_PASSWORD = "0911"  # Ändern Sie dies zu Ihrem gewünschten Passwort
UPLOAD_PASSWORD = "0911"  # Passwort für den Upload-Bereich
LOG_FILE = "server.log"
BANNER_PATH = "/uploads/Vantastic_Banner.png"  # Pfad zum Banner relativ zur Webroot

# Caching-Konfiguration
FILE_CACHE_TIMEOUT = 60  # Dateiliste-Cache in Sekunden
file_list_cache = {"timestamp": 0, "data": []}
file_list_lock = threading.Lock()

# Stellen Sie sicher, dass das Upload-Verzeichnis existiert
if not os.path.exists(UPLOAD_DIR):
    os.makedirs(UPLOAD_DIR)

# Logging-Funktion
def log_message(message, level="INFO"):
    timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
    log_entry = f"[{timestamp}] [{level}] {message}\n"
    
    print(log_entry, end="")
    
    try:
        with open(LOG_FILE, "a") as log_file:
            log_file.write(log_entry)
    except Exception as e:
        print(f"Fehler beim Schreiben ins Log-File: {str(e)}")

# Signal-Handler für ordnungsgemäßes Herunterfahren
def signal_handler(sig, frame):
    log_message("Server wird heruntergefahren...", "INFO")
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

class FileServerHandler(BaseHTTPRequestHandler):
    # Errorhandling für Verbindungsabbrüche
    def handle(self):
        try:
            super().handle()
        except (BrokenPipeError, ConnectionResetError) as e:
            log_message(f"Verbindung abgebrochen: {str(e)}", "WARNING")
        except Exception as e:
            log_message(f"Fehler bei der Verbindungsbehandlung: {str(e)}", "ERROR")
            traceback.print_exc()
    
    def log_message(self, format, *args):
        """Verbesserte Protokollierung"""
        client_address = self.address_string()
        log_message(f"{client_address} - {format % args}", "INFO")
    
    def send_html_response(self, content, status=200):
        """Sendet eine HTML-Antwort"""
        try:
            self.send_response(status)
            self.send_header('Content-Type', 'text/html; charset=utf-8')
            
            # Prüfen, ob der Client Komprimierung unterstützt
            accept_encoding = self.headers.get('Accept-Encoding', '')
            if 'gzip' in accept_encoding:
                import gzip
                content_bytes = content.encode('utf-8')
                compressed_content = gzip.compress(content_bytes)
                
                self.send_header('Content-Encoding', 'gzip')
                self.send_header('Content-Length', str(len(compressed_content)))
                self.end_headers()
                self.wfile.write(compressed_content)
            else:
                self.end_headers()
                self.wfile.write(content.encode('utf-8'))
                
        except (BrokenPipeError, ConnectionResetError) as e:
            log_message(f"Verbindung abgebrochen beim Senden der HTML-Antwort: {str(e)}", "WARNING")
        except Exception as e:
            log_message(f"Fehler beim Senden der HTML-Antwort: {str(e)}", "ERROR")
    
    def send_json_response(self, data, status=200):
        """Sendet eine JSON-Antwort"""
        try:
            self.send_response(status)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            self.wfile.write(json.dumps(data).encode('utf-8'))
        except (BrokenPipeError, ConnectionResetError) as e:
            log_message(f"Verbindung abgebrochen beim Senden der JSON-Antwort: {str(e)}", "WARNING")
        except Exception as e:
            log_message(f"Fehler beim Senden der JSON-Antwort: {str(e)}", "ERROR")
    
    def send_error_response(self, message, status=500):
        """Sendet eine Fehlerantwort"""
        try:
            self.send_response(status)
            self.send_header('Content-Type', 'text/html; charset=utf-8')
            self.end_headers()
            error_page = f"""
            <!DOCTYPE html>
            <html lang="de">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>Fehler</title>
                <link rel="preconnect" href="https://fonts.googleapis.com">
                <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
                <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
                <style>
                    :root {{
                        --primary-color: #1E3A8A;
                        --primary-light: #2563EB;
                        --accent-color: #0EA5E9;
                        --text-color: #1E293B;
                        --light-text: #64748B;
                        --bg-color: #F8FAFC;
                        --white: #FFFFFF;
                        --danger-color: #EF4444;
                        --danger-light: #FEE2E2;
                    }}
                    
                    body {{
                        font-family: 'Inter', sans-serif;
                        line-height: 1.6;
                        background-color: var(--bg-color);
                        color: var(--text-color);
                        margin: 0;
                        padding: 20px;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        min-height: 100vh;
                    }}
                    
                    .error-container {{
                        background-color: var(--white);
                        border-radius: 12px;
                        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
                        padding: 2rem;
                        max-width: 500px;
                        width: 100%;
                        text-align: center;
                    }}
                    
                    .error-icon {{
                        font-size: 3rem;
                        color: var(--danger-color);
                        margin-bottom: 1rem;
                    }}
                    
                    h1 {{
                        color: var(--primary-color);
                        font-size: 1.5rem;
                        margin-bottom: 1rem;
                    }}
                    
                    .error-message {{
                        background-color: var(--danger-light);
                        color: var(--danger-color);
                        padding: 1rem;
                        border-radius: 8px;
                        margin-bottom: 1.5rem;
                    }}
                    
                    .back-link {{
                        display: inline-block;
                        background-color: var(--primary-color);
                        color: var(--white);
                        text-decoration: none;
                        padding: 0.75rem 1.5rem;
                        border-radius: 8px;
                        font-weight: 500;
                        transition: all 0.3s ease;
                    }}
                    
                    .back-link:hover {{
                        background-color: var(--primary-light);
                        transform: translateY(-2px);
                        box-shadow: 0 4px 12px rgba(30, 58, 138, 0.3);
                    }}
                </style>
            </head>
            <body>
                <div class="error-container">
                    <div class="error-icon">⚠️</div>
                    <h1>Ein Fehler ist aufgetreten</h1>
                    <div class="error-message">
                        <p>{message}</p>
                    </div>
                    <a href="/" class="back-link">Zurück zur Startseite</a>
                </div>
            </body>
            </html>
            """
            self.wfile.write(error_page.encode('utf-8'))
        except (BrokenPipeError, ConnectionResetError) as e:
            log_message(f"Verbindung abgebrochen beim Senden der Fehlerantwort: {str(e)}", "WARNING")
        except Exception as e:
            log_message(f"Fehler beim Senden der Fehlerantwort: {str(e)}", "ERROR")
    
    def check_admin_auth(self):
        """Überprüft, ob der Benutzer authentifiziert ist"""
        auth_header = self.headers.get('Authorization')
        if not auth_header:
            return False
        
        try:
            auth_type, auth_string = auth_header.split(' ', 1)
            if auth_type.lower() != 'basic':
                return False
            
            import base64
            decoded = base64.b64decode(auth_string).decode('utf-8')
            username, password = decoded.split(':', 1)
            
            return username == ADMIN_USERNAME and password == ADMIN_PASSWORD
        except Exception:
            return False
    
    def request_admin_auth(self):
        """Fordert Authentifizierung an"""
        try:
            self.send_response(401)
            self.send_header('WWW-Authenticate', 'Basic realm="Admin-Bereich"')
            self.send_header('Content-Type', 'text/html; charset=utf-8')
            self.end_headers()
            
            auth_page = """
            <!DOCTYPE html>
            <html lang="de">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>Authentifizierung erforderlich</title>
                <link rel="preconnect" href="https://fonts.googleapis.com">
                <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
                <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
                <style>
                    :root {
                        --primary-color: #1E3A8A;
                        --primary-light: #2563EB;
                        --accent-color: #0EA5E9;
                        --text-color: #1E293B;
                        --light-text: #64748B;
                        --bg-color: #F8FAFC;
                        --white: #FFFFFF;
                        --info-color: #3B82F6;
                        --info-light: #EFF6FF;
                    }
                    
                    body {
                        font-family: 'Inter', sans-serif;
                        line-height: 1.6;
                        background-color: var(--bg-color);
                        color: var(--text-color);
                        margin: 0;
                        padding: 20px;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        min-height: 100vh;
                    }
                    
                    .auth-container {
                        background-color: var(--white);
                        border-radius: 12px;
                        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
                        padding: 2rem;
                        max-width: 500px;
                        width: 100%;
                        text-align: center;
                    }
                    
                    .auth-icon {
                        font-size: 3rem;
                        color: var(--info-color);
                        margin-bottom: 1rem;
                    }
                    
                    h1 {
                        color: var(--primary-color);
                        font-size: 1.5rem;
                        margin-bottom: 1rem;
                    }
                    
                    .auth-message {
                        background-color: var(--info-light);
                        color: var(--info-color);
                        padding: 1rem;
                        border-radius: 8px;
                        margin-bottom: 1.5rem;
                    }
                    
                    .back-link {
                        display: inline-block;
                        background-color: var(--primary-color);
                        color: var(--white);
                        text-decoration: none;
                        padding: 0.75rem 1.5rem;
                        border-radius: 8px;
                        font-weight: 500;
                        transition: all 0.3s ease;
                    }
                    
                    .back-link:hover {
                        background-color: var(--primary-light);
                        transform: translateY(-2px);
                        box-shadow: 0 4px 12px rgba(30, 58, 138, 0.3);
                    }
                </style>
            </head>
            <body>
                <div class="auth-container">
                    <div class="auth-icon">🔒</div>
                    <h1>Authentifizierung erforderlich</h1>
                    <div class="auth-message">
                        <p>Bitte geben Sie Ihren Benutzernamen und Passwort ein, um auf den Admin-Bereich zuzugreifen.</p>
                    </div>
                    <a href="/" class="back-link">Zurück zur Startseite</a>
                </div>
            </body>
            </html>
            """
            self.wfile.write(auth_page.encode('utf-8'))
        except (BrokenPipeError, ConnectionResetError) as e:
            log_message(f"Verbindung abgebrochen beim Anfordern der Admin-Auth: {str(e)}", "WARNING")
        except Exception as e:
            log_message(f"Fehler beim Anfordern der Admin-Auth: {str(e)}", "ERROR")
    
    def generate_main_page(self):
        """Generiert die modernisierte Hauptseite"""
        banner_url = f"http://{SERVER_ADDRESS}{BANNER_PATH}"
        current_year = time.strftime('%Y')
        
        return f"""
        <!DOCTYPE html>
        <html lang="de">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Vantastic Uploads</title>
            <link rel="preconnect" href="https://fonts.googleapis.com">
            <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
            <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
            <style>
                :root {{
                    /* Haupt-Farbpalette */
                    --primary-color: #1E3A8A;
                    --primary-light: #2563EB;
                    --primary-dark: #1E40AF;
                    --accent-color: #0EA5E9;
                    --accent-light: #38BDF8;
                    --accent-dark: #0284C7;
                    
                    /* Text und Hintergrund */
                    --text-color: #1E293B;
                    --text-muted: #64748B;
                    --text-light: #94A3B8;
                    --bg-color: #F8FAFC;
                    --bg-card: #FFFFFF;
                    --bg-hover: #F1F5F9;
                    
                    /* Status-Farben */
                    --success-color: #10B981;
                    --success-light: #D1FAE5;
                    --warning-color: #F59E0B;
                    --warning-light: #FEF3C7;
                    --danger-color: #EF4444;
                    --danger-light: #FEE2E2;
                    
                    /* Abstände */
                    --space-xs: 0.25rem;
                    --space-sm: 0.5rem;
                    --space-md: 1rem;
                    --space-lg: 1.5rem;
                    --space-xl: 2rem;
                    --space-2xl: 3rem;
                    
                    /* Schatten */
                    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
                    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
                    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
                    
                    /* Rahmen */
                    --border-radius-sm: 0.375rem;
                    --border-radius-md: 0.5rem;
                    --border-radius-lg: 0.75rem;
                    --border-color: #E2E8F0;
                }}
                
                * {{
                    margin: 0;
                    padding: 0;
                    box-sizing: border-box;
                }}
                
                body {{
                    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
                    font-size: 16px;
                    line-height: 1.6;
                    color: var(--text-color);
                    background-color: var(--bg-color);
                    -webkit-font-smoothing: antialiased;
                    -moz-osx-font-smoothing: grayscale;
                }}
                
                .container {{
                    max-width: 1200px;
                    margin: 0 auto;
                    padding: var(--space-lg);
                }}
                
                /* Header-Bereich */
                .header {{
                    background-color: var(--bg-card);
                    box-shadow: var(--shadow-md);
                    padding: var(--space-lg) 0;
                    position: relative;
                    top: 0;
                    z-index: 10;
                }}
                
                .header .container {{
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    padding-top: var(--space-md);
                    padding-bottom: var(--space-md);
                }}
                
                .header-banner {{
                    width: 100%;            /* Volle Breite erzwingen */
    		    max-width: 1200px;      /* Maximale Breite begrenzen */
    		    height: auto;           /* Höhe proportional anpassen */
   		    min-height: 120px;      /* Minimale Höhe festlegen */
   		    max-height: 200px;      /* Maximale Höhe begrenzen */
    		    object-fit: contain;    /* Gesamtes Bild anzeigen, proportional */
    		    margin: 0 auto;         /* Zentrieren */
                }}
                
                /* Bedienleiste */
                .toolbar {{
                    background-color: var(--bg-card);
                    border-radius: var(--border-radius-lg);
                    box-shadow: var(--shadow-sm);
                    padding: var(--space-lg);
                    margin-bottom: var(--space-xl);
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    flex-wrap: wrap;
                    gap: var(--space-md);
                }}
                
                /* Schaltflächen */
                .btn {{
                    display: inline-flex;
                    align-items: center;
                    justify-content: center;
                    gap: var(--space-sm);
                    padding: var(--space-sm) var(--space-lg);
                    border-radius: var(--border-radius-md);
                    font-weight: 500;
                    font-size: 1rem;
                    cursor: pointer;
                    transition: all 0.3s ease;
                    border: none;
                    outline: none;
                    text-decoration: none;
                    white-space: nowrap;
                }}
                
                .btn-primary {{
                    background-color: var(--primary-color);
                    color: white;
                }}
                
                .btn-primary:hover, .btn-primary:focus {{
                    background-color: var(--primary-dark);
                    box-shadow: 0 4px 12px rgba(30, 58, 138, 0.3);
                    transform: translateY(-2px);
                }}
                
                .btn-accent {{
                    background-color: var(--accent-color);
                    color: white;
                }}
                
                .btn-accent:hover, .btn-accent:focus {{
                    background-color: var(--accent-dark);
                    box-shadow: 0 4px 12px rgba(14, 165, 233, 0.3);
                    transform: translateY(-2px);
                }}
                
                .btn-outline {{
                    background-color: transparent;
                    color: var(--primary-color);
                    border: 1px solid var(--primary-color);
                }}
                
                .btn-outline:hover, .btn-outline:focus {{
                    background-color: var(--primary-color);
                    color: white;
                    transform: translateY(-2px);
                }}
                
                .btn-danger {{
                    background-color: var(--danger-color);
                    color: white;
                }}
                
                .btn-danger:hover, .btn-danger:focus {{
                    background-color: #dc2626;
                    box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
                    transform: translateY(-2px);
                }}
                
                .btn-lg {{
                    padding: var(--space-md) var(--space-xl);
                    font-size: 1.125rem;
                }}
                
                .btn-fab {{
                    position: fixed;
                    bottom: 2rem;
                    right: 2rem;
                    width: 60px;
                    height: 60px;
                    border-radius: 50%;
                    background-color: var(--accent-color);
                    color: white;
                    font-size: 1.5rem;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    box-shadow: var(--shadow-lg);
                    transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
                    z-index: 100;
                }}
                
                .btn-fab:hover, .btn-fab:focus {{
                    background-color: var(--accent-dark);
                    box-shadow: 0 6px 18px rgba(14, 165, 233, 0.35);
                    transform: translateY(-4px) scale(1.05);
                }}
                
                /* Upload-Bereich */
                .upload-section {{
                    background-color: var(--bg-card);
                    border-radius: var(--border-radius-lg);
                    box-shadow: var(--shadow-md);
                    padding: var(--space-xl);
                    margin-bottom: var(--space-2xl);
                }}
                
                .section-title {{
                    color: var(--primary-color);
                    font-size: 1.5rem;
                    font-weight: 600;
                    margin-bottom: var(--space-lg);
                    position: relative;
                    padding-bottom: var(--space-sm);
                }}
                
                .section-title::after {{
                    content: '';
                    position: absolute;
                    bottom: 0;
                    left: 0;
                    width: 50px;
                    height: 3px;
                    background-color: var(--accent-color);
                    border-radius: 3px;
                }}
                
                .drop-area {{
                    border: 2px dashed var(--accent-light);
                    border-radius: var(--border-radius-lg);
                    padding: var(--space-2xl);
                    text-align: center;
                    color: var(--text-muted);
                    background-color: rgba(14, 165, 233, 0.05);
                    transition: all 0.3s ease;
                    position: relative;
                    overflow: hidden;
                }}
                
                .drop-area:hover, .drop-area.highlight {{
                    background-color: rgba(14, 165, 233, 0.1);
                    border-color: var(--accent-color);
                    cursor: pointer;
                }}
                
                .drop-icon {{
                    font-size: 2.5rem;
                    color: var(--accent-color);
                    margin-bottom: var(--space-md);
                }}
                
                .drop-text {{
                    font-size: 1.125rem;
                    margin-bottom: var(--space-lg);
                }}
                
                .drop-hint {{
                    font-size: 0.875rem;
                    color: var(--text-light);
                }}
                
                .file-input {{
                    display: none;
                }}
                
                .file-info {{
                    margin-top: var(--space-lg);
                    padding: var(--space-lg);
                    background-color: var(--bg-hover);
                    border-radius: var(--border-radius-md);
                    display: none;
                }}
                
                .file-info-title {{
                    font-weight: 600;
                    margin-bottom: var(--space-sm);
                }}
                
                .file-item-preview {{
                    display: flex;
                    align-items: center;
                    padding: var(--space-sm) 0;
                }}
                
                .file-item-icon {{
                    margin-right: var(--space-md);
                    color: var(--accent-color);
                    font-size: 1.25rem;
                }}
                
                .file-item-name {{
                    flex-grow: 1;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }}
                
                .file-item-size {{
                    color: var(--text-muted);
                    font-size: 0.875rem;
                    white-space: nowrap;
                    margin-left: var(--space-md);
                }}
                
                .upload-progress {{
                    height: 8px;
                    width: 100%;
                    background-color: var(--bg-hover);
                    border-radius: var(--border-radius-sm);
                    overflow: hidden;
                    margin-top: var(--space-lg);
                    display: none;
                }}
                
                .progress-bar {{
                    height: 100%;
                    background-color: var(--accent-color);
                    width: 0%;
                    transition: width 0.2s ease;
                }}
                
                /* Benachrichtigungen */
                .alert {{
                    padding: var(--space-lg);
                    border-radius: var(--border-radius-md);
                    margin-bottom: var(--space-lg);
                    font-weight: 500;
                    display: flex;
                    align-items: center;
                    gap: var(--space-md);
                    opacity: 0;
                    transform: translateY(-10px);
                    transition: all 0.3s ease;
                    position: fixed;
                    top: var(--space-lg);
                    right: var(--space-lg);
                    z-index: 1000;
                    max-width: 400px;
                    box-shadow: var(--shadow-lg);
                }}
                
                .alert.show {{
                    opacity: 1;
                    transform: translateY(0);
                }}
                
                .alert-success {{
                    background-color: var(--success-light);
                    color: var(--success-color);
                }}
                
                .alert-error {{
                    background-color: var(--danger-light);
                    color: var(--danger-color);
                }}
                
                .alert-icon {{
                    font-size: 1.25rem;
                }}
                
                .alert-close {{
                    margin-left: auto;
                    cursor: pointer;
                    opacity: 0.7;
                    transition: opacity 0.2s ease;
                }}
                
                .alert-close:hover {{
                    opacity: 1;
                }}
                
                /* Dateianzeige */
                .view-options {{
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin-bottom: var(--space-lg);
                }}
                
                .view-selector {{
                    display: flex;
                    background-color: var(--bg-hover);
                    border-radius: var(--border-radius-md);
                    overflow: hidden;
                    padding: var(--space-xs);
                }}
                
                .view-selector button {{
                    background: none;
                    border: none;
                    outline: none;
                    padding: var(--space-sm) var(--space-md);
                    cursor: pointer;
                    transition: all 0.2s ease;
                    border-radius: var(--border-radius-sm);
                    font-size: 0.875rem;
                    color: var(--text-muted);
                }}
                
                .view-selector button.active {{
                    background-color: var(--bg-card);
                    color: var(--primary-color);
                    box-shadow: var(--shadow-sm);
                }}
                
                .view-selector button:hover:not(.active) {{
                    color: var(--text-color);
                }}
                
                .refresh-btn {{
                    background: none;
                    border: none;
                    outline: none;
                    color: var(--primary-color);
                    font-size: 1rem;
                    cursor: pointer;
                    transition: all 0.2s ease;
                    display: flex;
                    align-items: center;
                    gap: var(--space-sm);
                }}
                
                .refresh-btn:hover {{
                    color: var(--primary-dark);
                    transform: translateY(-2px);
                }}
                
                /* Spinner für Laden */
                .loading {{
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    padding: var(--space-2xl);
                }}
                
                .spinner {{
                    width: 40px;
                    height: 40px;
                    border: 3px solid rgba(14, 165, 233, 0.2);
                    border-radius: 50%;
                    border-top-color: var(--accent-color);
                    animation: spinner 1s linear infinite;
                }}
                
                @keyframes spinner {{
                    to {{ transform: rotate(360deg); }}
                }}
                
                /* Dateiliste */
                .files-container {{
                    margin-bottom: var(--space-2xl);
                }}
                
                /* Grid-Ansicht */
                .files-grid {{
                    display: grid;
                    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
                    gap: var(--space-lg);
                }}
                
                .file-card {{
                    background-color: var(--bg-card);
                    border-radius: var(--border-radius-lg);
                    box-shadow: var(--shadow-sm);
                    overflow: hidden;
                    transition: all 0.3s ease;
                    position: relative;
                }}
                
                .file-card:hover {{
                    transform: translateY(-4px);
                    box-shadow: var(--shadow-md);
                }}
                
                .file-card-preview {{
                    height: 160px;
                    background-color: var(--bg-hover);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    overflow: hidden;
                    position: relative;
                }}
                
                .file-card-preview img {{
                    max-width: 100%;
                    max-height: 100%;
                    object-fit: contain;
                }}
                
                .file-card-icon {{
                    font-size: 3rem;
                    color: var(--accent-color);
                }}
                
                .file-card-content {{
                    padding: var(--space-lg);
                }}
                
                .file-card-name {{
                    font-weight: 600;
                    margin-bottom: var(--space-sm);
                    display: -webkit-box;
                    -webkit-line-clamp: 2;
                    -webkit-box-orient: vertical;
                    overflow: hidden;
                    word-break: break-word;
                }}
                
                .file-card-meta {{
                    color: var(--text-muted);
                    font-size: 0.875rem;
                    margin-bottom: var(--space-md);
                }}
                
                .file-card-actions {{
                    display: flex;
                    justify-content: space-between;
                    margin-top: var(--space-md);
                }}
                
                .action-btn {{
                    background-color: var(--bg-hover);
                    color: var(--text-color);
                    border: none;
                    padding: var(--space-sm) var(--space-md);
                    border-radius: var(--border-radius-md);
                    font-size: 0.875rem;
                    cursor: pointer;
                    transition: all 0.2s ease;
                    display: flex;
                    align-items: center;
                    gap: var(--space-xs);
                }}
                
                .action-btn:hover {{
                    background-color: var(--primary-color);
                    color: white;
                }}
                
                .action-btn.view-btn:hover {{
                    background-color: var(--accent-color);
                }}
                
                .file-card-overlay {{
                    position: absolute;
                    top: 0;
                    left: 0;
                    right: 0;
                    bottom: 0;
                    background-color: rgba(30, 58, 138, 0.8);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    gap: var(--space-md);
                    opacity: 0;
                    transition: opacity 0.3s ease;
                }}
                
                .file-card:hover .file-card-overlay {{
                    opacity: 1;
                }}
                
                .overlay-btn {{
                    background-color: white;
                    color: var(--primary-color);
                    border: none;
                    width: 40px;
                    height: 40px;
                    border-radius: 50%;
                    font-size: 1rem;
                    cursor: pointer;
                    transition: all 0.2s ease;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }}
                
                .overlay-btn:hover {{
                    background-color: var(--accent-color);
                    color: white;
                    transform: scale(1.1);
                }}
                
                /* Listenansicht */
                .files-list {{
                    display: none;
                }}
                
                .file-row {{
                    background-color: var(--bg-card);
                    border-radius: var(--border-radius-md);
                    padding: var(--space-md) var(--space-lg);
                    margin-bottom: var(--space-md);
                    box-shadow: var(--shadow-sm);
                    display: flex;
                    align-items: center;
                    transition: all 0.2s ease;
                }}
                
                .file-row:hover {{
                    background-color: var(--bg-hover);
                    transform: translateX(4px);
                }}
                
                .file-row-icon {{
                    flex: 0 0 40px;
                    font-size: 1.5rem;
                    color: var(--accent-color);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }}
                
                .file-row-content {{
                    flex: 1;
                    min-width: 0;
                    padding: 0 var(--space-lg);
                }}
                
                .file-row-name {{
                    font-weight: 500;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }}
                
                .file-row-meta {{
                    color: var(--text-muted);
                    font-size: 0.875rem;
                }}
                
                .file-row-actions {{
                    display: flex;
                    gap: var(--space-sm);
                }}
                
                /* Keine Dateien Zustand */
                .empty-state {{
                    text-align: center;
                    padding: var(--space-2xl);
                    color: var(--text-muted);
                }}
                
                .empty-icon {{
                    font-size: 3rem;
                    color: var(--accent-light);
                    margin-bottom: var(--space-lg);
                }}
                
                .empty-title {{
                    font-size: 1.25rem;
                    margin-bottom: var(--space-md);
                }}
                
                .empty-message {{
                    margin-bottom: var(--space-lg);
                }}
                
                /* Paginierung */
                .pagination {{
                    display: flex;
                    justify-content: center;
                    gap: var(--space-sm);
                    margin-top: var(--space-xl);
                }}
                
                .pagination-btn {{
                    width: 40px;
                    height: 40px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    border-radius: var(--border-radius-md);
                    transition: all 0.2s ease;
                    cursor: pointer;
                    font-weight: 500;
                    border: 1px solid var(--border-color);
                    background-color: var(--bg-card);
                }}
                
                .pagination-btn.active {{
                    background-color: var(--primary-color);
                    color: white;
                    border-color: var(--primary-color);
                }}
                
                .pagination-btn:hover:not(.active):not(.disabled) {{
                    background-color: var(--bg-hover);
                    border-color: var(--primary-light);
                }}
                
                .pagination-btn.disabled {{
                    opacity: 0.5;
                    cursor: not-allowed;
                }}
                
                /* Modal-Fenster */
                .modal {{
                    display: none;
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background-color: rgba(15, 23, 42, 0.8);
                    z-index: 1000;
                    padding: var(--space-md);
                    overflow-y: auto;
                }}
                
                .modal-content {{
                    background-color: var(--bg-card);
                    border-radius: var(--border-radius-lg);
                    box-shadow: var(--shadow-lg);
                    width: 100%;
                    max-width: 800px;
                    margin: 5vh auto;
                    animation: modalEnter 0.3s ease;
                    overflow: hidden;
                    display: flex;
                    flex-direction: column;
                    max-height: 90vh;
                }}
                
                @keyframes modalEnter {{
                    from {{ opacity: 0; transform: scale(0.9); }}
                    to {{ opacity: 1; transform: scale(1); }}
                }}
                
                .modal-header {{
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    padding: var(--space-lg);
                    border-bottom: 1px solid var(--border-color);
                }}
                
                .modal-title {{
                    font-weight: 600;
                    color: var(--primary-color);
                    font-size: 1.25rem;
                }}
                
                .modal-close {{
                    background: none;
                    border: none;
                    font-size: 1.5rem;
                    color: var(--text-muted);
                    cursor: pointer;
                    transition: color 0.2s ease;
                }}
                
                .modal-close:hover {{
                    color: var(--danger-color);
                }}
                
                .modal-body {{
                    padding: var(--space-lg);
                    overflow-y: auto;
                    flex: 1;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }}
                
                .modal-body img {{
                    max-width: 100%;
                    max-height: 70vh;
                    object-fit: contain;
                }}
                
                .modal-body video,
                .modal-body audio {{
                    width: 100%;
                }}
                
                .modal-footer {{
                    padding: var(--space-lg);
                    border-top: 1px solid var(--border-color);
                    display: flex;
                    justify-content: flex-end;
                    gap: var(--space-md);
                }}
                
                /* Password-Modal */
                .password-modal-content {{
                    max-width: 400px;
                    text-align: center;
                }}
                
                .password-form {{
                    margin-bottom: var(--space-lg);
                }}
                
                .form-group {{
                    margin-bottom: var(--space-md);
                }}
                
                .form-input {{
                    width: 100%;
                    padding: var(--space-md);
                    border: 1px solid var(--border-color);
                    border-radius: var(--border-radius-md);
                    font-size: 1rem;
                    transition: all 0.2s ease;
                }}
                
                .form-input:focus {{
                    border-color: var(--accent-color);
                    box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.2);
                    outline: none;
                }}
                
                .form-error {{
                    color: var(--danger-color);
                    font-size: 0.875rem;
                    margin-top: var(--space-sm);
                    display: none;
                }}
                
                /* Toast (Kopieren) */
                .toast {{
                    position: fixed;
                    left: 50%;
                    transform: translateX(-50%);
                    bottom: var(--space-xl);
                    background-color: var(--primary-color);
                    color: white;
                    padding: var(--space-md) var(--space-xl);
                    border-radius: var(--border-radius-md);
                    box-shadow: var(--shadow-lg);
                    display: flex;
                    align-items: center;
                    gap: var(--space-md);
                    opacity: 0;
                    transition: all 0.3s ease;
                    z-index: 1001;
                }}
                
                .toast.show {{
                    opacity: 1;
                    transform: translate(-50%, -20px);
                }}
                
                /* Footer */
                .footer {{
                    background-color: var(--bg-card);
                    box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.05);
                    padding: var(--space-xl) 0;
                    text-align: center;
                    color: var(--text-muted);
                    margin-top: var(--space-2xl);
                }}
                
                .footer-content {{
                    max-width: 600px;
                    margin: 0 auto;
                }}
                
                /* Responsive Design */
                @media (max-width: 768px) {{
                    .container {{
                        padding: var(--space-md);
                    }}
                    
                    .upload-section, .files-container {{
                        padding: var(--space-lg);
                    }}
                    
                    .files-grid {{
                        grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
                    }}
                    
                    .toolbar {{
                        flex-direction: column;
                        align-items: flex-start;
                    }}
                    
                    .file-row {{
                        flex-direction: column;
                        align-items: flex-start;
                    }}
                    
                    .file-row-icon {{
                        margin-bottom: var(--space-sm);
                    }}
                    
                    .file-row-content {{
                        padding: var(--space-sm) 0;
                        width: 100%;
                    }}
                    
                    .file-row-actions {{
                        width: 100%;
                        justify-content: space-between;
                        margin-top: var(--space-sm);
                    }}
                    
                    .modal-content {{
                        margin: 0;
                        max-height: 100vh;
                        height: 100%;
                        border-radius: 0;
                    }}
                    
                    .btn-fab {{
                        bottom: var(--space-lg);
                        right: var(--space-lg);
                    }}
                }}
            </style>
        </head>
        <body>
            <!-- Header mit Logo -->
            <header class="header">
                <div class="container">
                    <img src="{banner_url}" alt="Vantastic Uploads" class="header-banner">
                </div>
            </header>
            
            <div class="container">
                <!-- Toolbar -->
                <div class="toolbar">
                    <a href="/admin" class="btn btn-primary">
                        <i class="fas fa-cog"></i> Verwaltungsbereich
                    </a>
                </div>
                
                <!-- Upload-Bereich -->
                <section class="upload-section">
                    <h2 class="section-title">Dateien hochladen</h2>
                    
                    <div id="dropArea" class="drop-area">
                        <div class="drop-icon">
                            <i class="fas fa-cloud-upload-alt"></i>
                        </div>
                        <div class="drop-text">Dateien hier hinziehen oder klicken zum Auswählen</div>
                        <div class="drop-hint">Maximale Dateigröße: 1 GB</div>
                        <input type="file" id="fileInput" class="file-input" multiple>
                    </div>
                    
                    <div id="fileInfo" class="file-info">
                        <div class="file-info-title">Ausgewählte Dateien:</div>
                        <div id="fileListPreview"></div>
                        <button id="uploadBtn" class="btn btn-accent btn-lg" style="margin-top: var(--space-lg); width: 100%;">
                            <i class="fas fa-upload"></i> Dateien hochladen
                        </button>
                    </div>
                    
                    <div id="uploadProgress" class="upload-progress">
                        <div id="progressBar" class="progress-bar"></div>
                    </div>
                </section>
                
                <!-- Dateienbereich -->
                <section class="files-container">
                    <div class="view-options">
                        <h2 class="section-title">Verfügbare Dateien</h2>
                        
                        <div class="toolbar-actions">
                            <div class="view-selector">
                                <button id="gridViewBtn" class="active"><i class="fas fa-th"></i> Kacheln</button>
                                <button id="listViewBtn"><i class="fas fa-list"></i> Liste</button>
                            </div>
                        </div>
                        
                        <button id="refreshBtn" class="refresh-btn">
                            <i class="fas fa-sync-alt"></i> Aktualisieren
                        </button>
                    </div>
                    
                    <!-- Ladeanimation -->
                    <div id="loading" class="loading">
                        <div class="spinner"></div>
                    </div>
                    
                    <!-- Grid-Ansicht (Standard) -->
                    <div id="filesGrid" class="files-grid">
                        <!-- Hier werden die Dateikarten dynamisch eingefügt -->
                    </div>
                    
                    <!-- Listenansicht (Alternative) -->
                    <div id="filesList" class="files-list">
                        <!-- Hier werden die Dateilisteneinträge dynamisch eingefügt -->
                    </div>
                    
                    <!-- Paginierung -->
                    <div id="pagination" class="pagination"></div>
                </section>
            </div>
            
            <!-- Erfolgsmeldung Toast -->
            <div id="successAlert" class="alert alert-success">
                <div class="alert-icon"><i class="fas fa-check-circle"></i></div>
                <div class="alert-message">Datei erfolgreich hochgeladen!</div>
                <div class="alert-close"><i class="fas fa-times"></i></div>
            </div>
            
            <!-- Fehlermeldung Toast -->
            <div id="errorAlert" class="alert alert-error">
                <div class="alert-icon"><i class="fas fa-exclamation-circle"></i></div>
                <div class="alert-message">Fehler beim Hochladen der Datei.</div>
                <div class="alert-close"><i class="fas fa-times"></i></div>
            </div>
            
            <!-- Toast Benachrichtigung (Kopieren) -->
            <div id="copyToast" class="toast">
                <i class="fas fa-check-circle"></i>
                <span>Link in Zwischenablage kopiert!</span>
            </div>
            
            <!-- Schwebender Upload-Button (FAB) -->
            <button id="fabUploadBtn" class="btn-fab">
                <i class="fas fa-plus"></i>
            </button>
            
            <!-- Modal-Fenster für Dateivorschau -->
            <div id="fileViewerModal" class="modal">
                <div class="modal-content">
                    <div class="modal-header">
                        <h3 id="modalTitle" class="modal-title">Dateiname</h3>
                        <button class="modal-close" onclick="closeModal()">×</button>
                    </div>
                    <div id="modalBody" class="modal-body">
                        <!-- Hier wird der Inhalt dynamisch eingefügt -->
                    </div>
                    <div class="modal-footer">
                        <a id="modalDownloadLink" href="#" class="btn btn-accent">
                            <i class="fas fa-download"></i> Herunterladen
                        </a>
                    </div>
                </div>
            </div>
            
            <!-- Passwort-Modal für Upload -->
            <div id="uploadPasswordModal" class="modal">
                <div class="modal-content password-modal-content">
                    <div class="modal-header">
                        <h3 class="modal-title">Passwort erforderlich</h3>
                        <button class="modal-close" onclick="closePasswordModal()">×</button>
                    </div>
                    <div class="modal-body">
                        <div class="password-form">
                            <p style="margin-bottom: var(--space-lg);">Bitte geben Sie das Passwort ein, um Dateien hochzuladen:</p>
                            <div class="form-group">
                                <input type="password" id="uploadPassword" class="form-input" placeholder="Passwort eingeben">
                                <div id="passwordErrorMessage" class="form-error">Falsches Passwort. Bitte versuchen Sie es erneut.</div>
                            </div>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-outline" onclick="closePasswordModal()">Abbrechen</button>
                        <button class="btn btn-accent" onclick="verifyUploadPassword()">Bestätigen</button>
                    </div>
                </div>
            </div>
            
            <!-- Footer -->
            <footer class="footer">
                <div class="footer-content">
                    <p>&copy; {current_year} Vantastic Uploads. Alle Rechte vorbehalten.</p>
                </div>
            </footer>
            
            <script>
                // DOM-Elemente
                const dropArea = document.getElementById('dropArea');
                const fileInput = document.getElementById('fileInput');
                const fileInfo = document.getElementById('fileInfo');
                const fileListPreview = document.getElementById('fileListPreview');
                const uploadBtn = document.getElementById('uploadBtn');
                const uploadProgress = document.getElementById('uploadProgress');
                const progressBar = document.getElementById('progressBar');
                const loading = document.getElementById('loading');
                const filesGrid = document.getElementById('filesGrid');
                const filesList = document.getElementById('filesList');
                const pagination = document.getElementById('pagination');
                const successAlert = document.getElementById('successAlert');
                const errorAlert = document.getElementById('errorAlert');
                const copyToast = document.getElementById('copyToast');
                const fileViewerModal = document.getElementById('fileViewerModal');
                const modalTitle = document.getElementById('modalTitle');
                const modalBody = document.getElementById('modalBody');
                const modalDownloadLink = document.getElementById('modalDownloadLink');
                const uploadPasswordModal = document.getElementById('uploadPasswordModal');
                const uploadPasswordInput = document.getElementById('uploadPassword');
                const passwordErrorMessage = document.getElementById('passwordErrorMessage');
                const refreshBtn = document.getElementById('refreshBtn');
                const fabUploadBtn = document.getElementById('fabUploadBtn');
                const gridViewBtn = document.getElementById('gridViewBtn');
                const listViewBtn = document.getElementById('listViewBtn');
                
                // Ansichtseinstellung (Grid/Liste)
                let currentView = 'grid';
                
                // Paginierungsvariablen
                let currentPage = 1;
                const filesPerPage = 12;
                let allFiles = [];
                
                // Ansicht umschalten
                gridViewBtn.addEventListener('click', () => {{
                    if (currentView !== 'grid') {{
                        currentView = 'grid';
                        filesGrid.style.display = 'grid';
                        filesList.style.display = 'none';
                        gridViewBtn.classList.add('active');
                        listViewBtn.classList.remove('active');
                        // Lokale Einstellung speichern
                        localStorage.setItem('preferredView', 'grid');
                    }}
                }});
                
                listViewBtn.addEventListener('click', () => {{
                    if (currentView !== 'list') {{
                        currentView = 'list';
                        filesGrid.style.display = 'none';
                        filesList.style.display = 'block';
                        gridViewBtn.classList.remove('active');
                        listViewBtn.classList.add('active');
                        // Lokale Einstellung speichern
                        localStorage.setItem('preferredView', 'list');
                    }}
                }});
                
                // Gespeicherte Ansichtseinstellung laden
                document.addEventListener('DOMContentLoaded', () => {{
                    const savedView = localStorage.getItem('preferredView');
                    if (savedView === 'list') {{
                        listViewBtn.click();
                    }}
                }});
                
                // FAB-Button zum Upload
                fabUploadBtn.addEventListener('click', () => {{
                    // Zum Upload-Bereich scrollen
                    const uploadSection = document.querySelector('.upload-section');
                    uploadSection.scrollIntoView({{ behavior: 'smooth' }});
                    // Nach kurzem Delay das Passwort-Modal öffnen
                    setTimeout(() => {{
                        showUploadPasswordModal();
                    }}, 500);
                }});
                
                // Alert-Schließen-Buttons
                document.querySelectorAll('.alert-close').forEach(closeBtn => {{
                    closeBtn.addEventListener('click', (e) => {{
                        const alert = e.target.closest('.alert');
                        alert.classList.remove('show');
                    }});
                }});
                
                // Benachrichtigung anzeigen
                function showAlert(alert, message) {{
                    const messageEl = alert.querySelector('.alert-message');
                    messageEl.textContent = message;
                    
                    alert.classList.add('show');
                    
                    // Nach 5 Sekunden ausblenden
                    setTimeout(() => {{
                        alert.classList.remove('show');
                    }}, 5000);
                }}
                
                // Passwort-Modal anzeigen
function showUploadPasswordModal() {{
    // Prüfen, ob das Passwort bereits eingegeben wurde
    const passwordVerified = sessionStorage.getItem('passwordVerified');
    
    if (passwordVerified === 'true') {{
        // Wenn das Passwort bereits verifiziert wurde
        if (window.droppedFiles && window.droppedFiles.length > 0) {{
            handleFiles(window.droppedFiles);
            window.droppedFiles = null;
        }} else {{
            fileInput.click();
        }}
        return;
    }}
    
    uploadPasswordModal.style.display = 'block';
    uploadPasswordInput.value = '';
    passwordErrorMessage.style.display = 'none';
    
    // Fokus auf das Password-Feld setzen
    setTimeout(() => uploadPasswordInput.focus(), 100);
    
    // Enter-Taste für Bestätigung
    uploadPasswordInput.addEventListener('keydown', function(e) {{
        if (e.key === 'Enter') {{
            verifyUploadPassword();
            e.preventDefault();
        }}
    }});
}}
                
                // Passwort-Modal schließen
function closePasswordModal() {{
    uploadPasswordModal.style.display = 'none';
}}
                
// Passwort überprüfen
function verifyUploadPassword() {{
    const password = uploadPasswordInput.value;
    
    if (password === "{UPLOAD_PASSWORD}") {{
        // Passwort korrekt
        closePasswordModal();
        
        // Passwort für diese Session speichern
        sessionStorage.setItem('passwordVerified', 'true');
        
        // Wenn Dateien bereits gedroppt wurden
        if (window.droppedFiles && window.droppedFiles.length > 0) {{
            handleFiles(window.droppedFiles);
            window.droppedFiles = null;
        }} else {{
            // Dateiauswahl öffnen
            fileInput.click();
        }}
    }} else {{
        // Falsches Passwort
        passwordErrorMessage.style.display = 'block';
        uploadPasswordInput.focus();
    }}
}}
                
                // Event-Listener für Drag & Drop
                ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {{
                    dropArea.addEventListener(eventName, preventDefaults, false);
                }});
                
                function preventDefaults(e) {{
                    e.preventDefault();
                    e.stopPropagation();
                }}
                
                ['dragenter', 'dragover'].forEach(eventName => {{
                    dropArea.addEventListener(eventName, highlight, false);
                }});
                
                ['dragleave', 'drop'].forEach(eventName => {{
                    dropArea.addEventListener(eventName, unhighlight, false);
                }});
                
                function highlight() {{
                    dropArea.classList.add('highlight');
                }}
                
                function unhighlight() {{
                    dropArea.classList.remove('highlight');
                }}
                
                // Klick auf Drop-Area
                dropArea.addEventListener('click', () => {{
                    showUploadPasswordModal();
                }});
                
// Event-Handler für Datei-Drop
dropArea.addEventListener('drop', function(e) {{
    e.preventDefault(); // Verhindere Standard-Browser-Aktion
    
    // Dateien speichern
    window.droppedFiles = e.dataTransfer.files;
    
    // Passwort-Dialog zeigen
    showUploadPasswordModal();
}});
                
                // Event-Handler für Dateiauswahl
                fileInput.addEventListener('change', function() {{
                    handleFiles(this.files);
                }});

		// Automatisches Upload-Starten nach Dateiauswahl
fileInput.addEventListener('change', function() {{
   // Wenn die Datei nach Passwort-Überprüfung ausgewählt wurde, bereite sie vor
   if (this.files.length > 0) {{
      handleFiles(this.files);
      // Optional: Automatisches Hochladen, wenn gewünscht
      // uploadFiles();
   }}
}});
                
                // Datei verarbeiten
                function handleFiles(files) {{
                    if (files.length === 0) return;
                    
                    // Dateien im Vorschaubereich anzeigen
                    fileInfo.style.display = 'block';
                    fileListPreview.innerHTML = '';
                    
                    for (let i = 0; i < files.length; i++) {{
                        const file = files[i];
                        const fileItem = document.createElement('div');
                        fileItem.className = 'file-item-preview';
                        
                        // Icon je nach Dateityp
                        const fileIcon = document.createElement('div');
                        fileIcon.className = 'file-item-icon';
                        fileIcon.innerHTML = getFileTypeIcon(file.name);
                        
                        const fileName = document.createElement('div');
                        fileName.className = 'file-item-name';
                        fileName.textContent = file.name;
                        
                        const fileSize = document.createElement('div');
                        fileSize.className = 'file-item-size';
                        fileSize.textContent = formatFileSize(file.size);
                        
                        fileItem.appendChild(fileIcon);
                        fileItem.appendChild(fileName);
                        fileItem.appendChild(fileSize);
                        
                        fileListPreview.appendChild(fileItem);
                    }}
                    
                    // Upload-Button anzeigen
                    uploadBtn.style.display = 'block';
                }}
                
                // Event-Handler für Upload-Button
                uploadBtn.addEventListener('click', uploadFiles);
                
                // Dateien hochladen
                function uploadFiles() {{
                    const files = fileInput.files;
                    if (files.length === 0) return;
                    
                    // UI-Status zurücksetzen
                    uploadProgress.style.display = 'block';
                    progressBar.style.width = '0%';
                    uploadBtn.disabled = true;
                    
                    let totalUploaded = 0;
                    let successCount = 0;
                    let errorCount = 0;
                    
                    const totalFiles = files.length;
                    
                    // Alle Dateien einzeln hochladen
                    for (let i = 0; i < files.length; i++) {{
                        const file = files[i];
                        const formData = new FormData();
                        formData.append('file', file);
                        
                        const xhr = new XMLHttpRequest();
                        
                        xhr.upload.addEventListener('progress', function(e) {{
                            if (e.lengthComputable) {{
                                // Anteilige Fortschrittsanzeige
                                const fileProgress = (e.loaded / e.total) * (1 / totalFiles);
                                const overallProgress = (i / totalFiles) + fileProgress;
                                progressBar.style.width = (overallProgress * 100) + '%';
                            }}
                        }});
                        
                        xhr.addEventListener('load', function() {{
                            totalUploaded++;
                            
                            if (xhr.status === 200) {{
                                const response = JSON.parse(xhr.responseText);
                                
                                if (response.success) {{
                                    successCount++;
                                }} else {{
                                    errorCount++;
                                    console.error(`Fehler beim Upload von ${{file.name}}: ${{response.error || 'Unbekannter Fehler'}}`);
                                }}
                            }} else {{
                                errorCount++;
                                console.error(`HTTP-Fehler beim Upload von ${{file.name}}: ${{xhr.status}}`);
                            }}
                            
                            // Wenn alle Uploads abgeschlossen sind
                            if (totalUploaded === totalFiles) {{
                                uploadProgress.style.display = 'none';
                                uploadBtn.disabled = false;
                                
                                if (errorCount === 0) {{
                                    showAlert(successAlert, `${{successCount}} Datei(en) erfolgreich hochgeladen.`);
                                }} else if (successCount === 0) {{
                                    showAlert(errorAlert, `Beim Hochladen der Dateien sind Fehler aufgetreten.`);
                                }} else {{
                                    showAlert(successAlert, `${{successCount}} von ${{totalFiles}} Datei(en) erfolgreich hochgeladen. ${{errorCount}} fehlgeschlagen.`);
                                }}
                                
                                // Formular zurücksetzen
                                fileInput.value = '';
                                fileInfo.style.display = 'none';
                                fileListPreview.innerHTML = '';
                                
                                // Dateien neu laden
                                loadFiles();
                            }}
                        }});
                        
                        xhr.addEventListener('error', function() {{
                            totalUploaded++;
                            errorCount++;
                            
                            if (totalUploaded === totalFiles) {{
                                uploadProgress.style.display = 'none';
                                uploadBtn.disabled = false;
                                
                                showAlert(errorAlert, 'Netzwerkfehler beim Hochladen der Dateien.');
                                
                                // Formular zurücksetzen
                                fileInput.value = '';
                                fileInfo.style.display = 'none';
                            }}
                        }});
                        
                        xhr.open('POST', '/upload');
                        xhr.send(formData);
                    }}
                }}
                
                // Laden der Dateien vom Server
                function loadFiles() {{
                    loading.style.display = 'flex';
                    filesGrid.innerHTML = '';
                    filesList.innerHTML = '';
                    pagination.innerHTML = '';
                    
                    // Cache für die API-Antwort verwenden, wenn verfügbar
                    const cachedFiles = sessionStorage.getItem('fileListCache');
                    const cacheTimestamp = sessionStorage.getItem('fileListCacheTime');
                    const now = Date.now();
                    
                    // Cache verwenden, wenn er nicht älter als 60 Sekunden ist
                    if (cachedFiles && cacheTimestamp && (now - parseInt(cacheTimestamp)) < 60000) {{
                        try {{
                            const files = JSON.parse(cachedFiles);
                            processFiles(files);
                            return;
                        }} catch (e) {{
                            console.error('Fehler beim Verarbeiten des Cache:', e);
                            // Bei Fehlern trotzdem vom Server laden
                        }}
                    }}
                    
                    fetch('/list-files')
                        .then(response => response.json())
                        .then(files => {{
                            // Ergebnis im Cache speichern
                            sessionStorage.setItem('fileListCache', JSON.stringify(files));
                            sessionStorage.setItem('fileListCacheTime', Date.now().toString());
                            
                            processFiles(files);
                        }})
                        .catch(error => {{
                            loading.style.display = 'none';
                            
                            // Leerer Zustand anzeigen
                            const emptyState = `
                                <div class="empty-state">
                                    <div class="empty-icon">
                                        <i class="fas fa-exclamation-circle"></i>
                                    </div>
                                    <div class="empty-title">Fehler beim Laden der Dateien</div>
                                    <div class="empty-message">${{error.message}}</div>
                                    <button class="btn btn-accent" onclick="loadFiles()">
                                        <i class="fas fa-sync-alt"></i> Erneut versuchen
                                    </button>
                                </div>
                            `;
                            
                            filesGrid.innerHTML = emptyState;
                            filesList.innerHTML = emptyState;
                        }});
                }}
                
                // Verarbeitet die geladenen Dateien
                function processFiles(files) {{
                    loading.style.display = 'none';
                    
                    // Dateien nach Datum sortieren (neueste zuerst)
                    files.sort((a, b) => b.timestamp - a.timestamp);
                    
                    // Alle Dateien speichern
                    allFiles = files;
                    
                    if (files.length === 0) {{
                        // Leerer Zustand anzeigen
                        const emptyState = `
                            <div class="empty-state">
                                <div class="empty-icon">
                                    <i class="fas fa-file-upload"></i>
                                </div>
                                <div class="empty-title">Keine Dateien vorhanden</div>
                                <div class="empty-message">Laden Sie Ihre ersten Dateien hoch, um sie hier zu sehen.</div>
                                <button class="btn btn-accent" onclick="showUploadPasswordModal()">
                                    <i class="fas fa-upload"></i> Dateien hochladen
                                </button>
                            </div>
                        `;
                        
                        filesGrid.innerHTML = emptyState;
                        filesList.innerHTML = emptyState;
                        return;
                    }}
                    
                    // Paginierung einrichten und Dateien anzeigen
                    displayPaginatedFiles();
                }}
                
                // Zeigt paginierte Dateien an
                function displayPaginatedFiles() {{
                    // Berechnen der Start- und Endindizes für die aktuelle Seite
                    const startIndex = (currentPage - 1) * filesPerPage;
                    const endIndex = Math.min(startIndex + filesPerPage, allFiles.length);
                    
                    // Nur die Dateien für die aktuelle Seite filtern
                    const currentPageFiles = allFiles.slice(startIndex, endIndex);
                    
                    // Listen leeren
                    filesGrid.innerHTML = '';
                    filesList.innerHTML = '';
                    
                    // Dateien in Grid-Ansicht anzeigen
                    currentPageFiles.forEach(file => {{
                        // Grid-Ansicht: Karten
                        const isImage = isImageFile(file.name);
                        
                        // Karten-Ansicht (Grid)
                        const fileCard = document.createElement('div');
                        fileCard.className = 'file-card';
                        
                        // Preview-Bereich
                        const preview = document.createElement('div');
                        preview.className = 'file-card-preview';
                        
                        // Für Bilder eine Thumbnail-Vorschau anzeigen
                        if (isImage) {{
                            const img = document.createElement('img');
                            img.src = `${{file.download_url}}?view=true`;
                            img.alt = file.name;
                            img.loading = 'lazy'; // Lazy loading für bessere Performance
                            preview.appendChild(img);
                        }} else {{
                            // Icon für andere Dateitypen
                            const icon = document.createElement('div');
                            icon.className = 'file-card-icon';
                            icon.innerHTML = getFileTypeIcon(file.name);
                            preview.appendChild(icon);
                        }}
                        
                        // Overlay mit Schnellaktionen
                        const overlay = document.createElement('div');
                        overlay.className = 'file-card-overlay';
                        
                        // Direkte Aktionen im Overlay
                        const viewable = isViewableInBrowser(file.name);
                        
                        if (viewable) {{
                            const viewBtn = document.createElement('button');
                            viewBtn.className = 'overlay-btn';
                            viewBtn.innerHTML = '<i class="fas fa-eye"></i>';
                            viewBtn.title = 'Anzeigen';
                            viewBtn.onclick = () => showFileInModal(file);
                            overlay.appendChild(viewBtn);
                        }}
                        
                        const downloadBtn = document.createElement('a');
                        downloadBtn.className = 'overlay-btn';
                        downloadBtn.href = file.download_url;
                        downloadBtn.innerHTML = '<i class="fas fa-download"></i>';
                        downloadBtn.title = 'Herunterladen';
                        downloadBtn.setAttribute('download', '');
                        overlay.appendChild(downloadBtn);
                        
                        const copyBtn = document.createElement('button');
                        copyBtn.className = 'overlay-btn';
                        copyBtn.innerHTML = '<i class="fas fa-link"></i>';
                        copyBtn.title = 'Link kopieren';
                        copyBtn.onclick = () => {{
                            copyToClipboard(file.full_url);
                            showCopyToast();
                        }};
                        overlay.appendChild(copyBtn);
                        
                        preview.appendChild(overlay);
                        fileCard.appendChild(preview);
                        
                        // Inhalt/Details
                        const content = document.createElement('div');
                        content.className = 'file-card-content';
                        
                        const name = document.createElement('div');
                        name.className = 'file-card-name';
                        name.textContent = file.name;
                        content.appendChild(name);
                        
                        const meta = document.createElement('div');
                        meta.className = 'file-card-meta';
                        meta.textContent = `${{formatFileSize(file.size)}} • ${{formatDate(file.timestamp)}}`;
                        content.appendChild(meta);
                        
                        fileCard.appendChild(content);
                        filesGrid.appendChild(fileCard);
                        
                        // Listenansicht
                        const fileRow = document.createElement('div');
                        fileRow.className = 'file-row';
                        
                        const fileRowIcon = document.createElement('div');
                        fileRowIcon.className = 'file-row-icon';
                        fileRowIcon.innerHTML = getFileTypeIcon(file.name);
                        
                        const fileRowContent = document.createElement('div');
                        fileRowContent.className = 'file-row-content';
                        
                        const fileRowName = document.createElement('div');
                        fileRowName.className = 'file-row-name';
                        fileRowName.textContent = file.name;
                        fileRowContent.appendChild(fileRowName);
                        
                        const fileRowMeta = document.createElement('div');
                        fileRowMeta.className = 'file-row-meta';
                        fileRowMeta.textContent = `${{formatFileSize(file.size)}} • ${{formatDate(file.timestamp)}}`;
                        fileRowContent.appendChild(fileRowMeta);
                        
                        const fileRowActions = document.createElement('div');
                        fileRowActions.className = 'file-row-actions';
                        
                        if (viewable) {{
                            const viewAction = document.createElement('button');
                            viewAction.className = 'action-btn view-btn';
                            viewAction.innerHTML = '<i class="fas fa-eye"></i> Anzeigen';
                            viewAction.onclick = () => showFileInModal(file);
                            fileRowActions.appendChild(viewAction);
                        }}
                        
                        const downloadAction = document.createElement('a');
                        downloadAction.className = 'action-btn';
                        downloadAction.href = file.download_url;
                        downloadAction.innerHTML = '<i class="fas fa-download"></i> Download';
                        downloadAction.setAttribute('download', '');
                        fileRowActions.appendChild(downloadAction);
                        
                        const copyAction = document.createElement('button');
                        copyAction.className = 'action-btn';
                        copyAction.innerHTML = '<i class="fas fa-link"></i> Link kopieren';
                        copyAction.onclick = () => {{
                            copyToClipboard(file.full_url);
                            showCopyToast();
                        }};
                        fileRowActions.appendChild(copyAction);
                        
                        fileRow.appendChild(fileRowIcon);
                        fileRow.appendChild(fileRowContent);
                        fileRow.appendChild(fileRowActions);
                        
                        filesList.appendChild(fileRow);
                    }});
                    
                    // Paginierung aktualisieren
                    updatePagination();
                }}
                
                // Aktualisiert die Paginierungssteuerung
                function updatePagination() {{
                    pagination.innerHTML = '';
                    
                    const totalPages = Math.ceil(allFiles.length / filesPerPage);
                    
                    if (totalPages <= 1) return;
                    
                    // Zurück-Button
                    const prevBtn = document.createElement('button');
                    prevBtn.className = 'pagination-btn' + (currentPage === 1 ? ' disabled' : '');
                    prevBtn.innerHTML = '<i class="fas fa-chevron-left"></i>';
                    prevBtn.disabled = currentPage === 1;
                    
                    if (currentPage > 1) {{
                        prevBtn.onclick = () => {{
                            currentPage--;
                            displayPaginatedFiles();
                            // Nach oben scrollen
                            window.scrollTo({{ top: document.querySelector('.files-container').offsetTop - 20, behavior: 'smooth' }});
                        }};
                    }}
                    
                    pagination.appendChild(prevBtn);
                    
                    // Seitenzahlen
                    const maxVisiblePages = 5;
                    let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
                    let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);
                    
                    if (endPage - startPage + 1 < maxVisiblePages) {{
                        startPage = Math.max(1, endPage - maxVisiblePages + 1);
                    }}
                    
                    for (let i = startPage; i <= endPage; i++) {{
                        const pageBtn = document.createElement('button');
                        pageBtn.className = 'pagination-btn' + (i === currentPage ? ' active' : '');
                        pageBtn.textContent = i;
                        
                        if (i !== currentPage) {{
                            pageBtn.onclick = () => {{
                                currentPage = i;
                                displayPaginatedFiles();
                                // Nach oben scrollen
                                window.scrollTo({{ top: document.querySelector('.files-container').offsetTop - 20, behavior: 'smooth' }});
                            }};
                        }}
                        
                        pagination.appendChild(pageBtn);
                    }}
                    
                    // Weiter-Button
                    const nextBtn = document.createElement('button');
                    nextBtn.className = 'pagination-btn' + (currentPage === totalPages ? ' disabled' : '');
                    nextBtn.innerHTML = '<i class="fas fa-chevron-right"></i>';
                    nextBtn.disabled = currentPage === totalPages;
                    
                    if (currentPage < totalPages) {{
                        nextBtn.onclick = () => {{
                            currentPage++;
                            displayPaginatedFiles();
                            // Nach oben scrollen
                            window.scrollTo({{ top: document.querySelector('.files-container').offsetTop - 20, behavior: 'smooth' }});
                        }};
                    }}
                    
                    pagination.appendChild(nextBtn);
                }}
                
                // Prüft, ob die Datei ein Bild ist
                function isImageFile(filename) {{
                    const extension = filename.split('.').pop().toLowerCase();
                    return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(extension);
                }}
                
                // Prüft, ob eine Datei direkt im Browser angezeigt werden kann
                function isViewableInBrowser(filename) {{
                    const extension = filename.split('.').pop().toLowerCase();
                    const viewableExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'mp3', 'mp4', 'webm', 'ogg', 'pdf', 'txt'];
                    return viewableExtensions.includes(extension);
                }}
                
                // Modal öffnen und Datei anzeigen
                function showFileInModal(file) {{
                    // Modal-Titel setzen
                    modalTitle.textContent = file.name;
                    
                    // Download-Link setzen
                    modalDownloadLink.href = file.download_url;
                    
                    // Modal-Inhalt leeren
                    modalBody.innerHTML = '';
                    
                    // Dateityp bestimmen und entsprechenden Inhalt laden
                    const fileExtension = file.name.split('.').pop().toLowerCase();
                    
                    if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(fileExtension)) {{
                        // Bild anzeigen
                        const img = document.createElement('img');
                        img.src = file.download_url + '?view=true';
                        img.alt = file.name;
                        modalBody.appendChild(img);
                    }} else if (['mp4', 'webm', 'ogg'].includes(fileExtension)) {{
                        // Video anzeigen
                        const video = document.createElement('video');
                        video.controls = true;
                        video.autoplay = false;
                        const source = document.createElement('source');
                        source.src = file.download_url + '?view=true';
                        source.type = `video/${{fileExtension}}`;
                        video.appendChild(source);
                        modalBody.appendChild(video);
                    }} else if (['mp3', 'wav'].includes(fileExtension)) {{
                        // Audio anzeigen
                        const audio = document.createElement('audio');
                        audio.controls = true;
                        audio.autoplay = false;
                        const source = document.createElement('source');
                        source.src = file.download_url + '?view=true';
                        source.type = `audio/${{fileExtension === 'mp3' ? 'mpeg' : fileExtension}}`;
                        audio.appendChild(source);
                        modalBody.appendChild(audio);
                    }} else if (fileExtension === 'pdf') {{
                        // PDF anzeigen
                        const iframe = document.createElement('iframe');
                        iframe.src = file.download_url + '?view=true';
                        iframe.width = '100%';
                        iframe.height = '70vh';
                        iframe.style.border = 'none';
                        modalBody.appendChild(iframe);
                    }} else if (fileExtension === 'txt') {{
                        // Text anzeigen mit Ladeanimation
                        const loadingSpinner = document.createElement('div');
                        loadingSpinner.className = 'spinner';
                        modalBody.appendChild(loadingSpinner);
                        
                        fetch(file.download_url + '?view=true')
                            .then(response => response.text())
                            .then(text => {{
                                modalBody.innerHTML = '';  // Spinner entfernen
                                const pre = document.createElement('pre');
                                pre.style.textAlign = 'left';
                                pre.style.overflow = 'auto';
                                pre.style.padding = 'var(--space-md)';
                                pre.style.whiteSpace = 'pre-wrap';
                                pre.style.wordBreak = 'break-word';
                                pre.style.maxHeight = '70vh';
                                pre.style.background = '#f8f9fa';
                                pre.style.borderRadius = 'var(--border-radius-sm)';
                                pre.textContent = text;
                                modalBody.appendChild(pre);
                            }})
                            .catch(error => {{
                                modalBody.innerHTML = '';
                                modalBody.textContent = 'Fehler beim Laden der Textdatei: ' + error.message;
                            }});
                    }} else {{
                        // Nicht anzeigbarer Dateityp
                        const notViewableMessage = document.createElement('div');
                        notViewableMessage.style.textAlign = 'center';
                        notViewableMessage.style.padding = 'var(--space-2xl)';
                        
                        const icon = document.createElement('div');
                        icon.innerHTML = '<i class="fas fa-file-download"></i>';
                        icon.style.fontSize = '4rem';
                        icon.style.color = 'var(--accent-color)';
                        icon.style.marginBottom = 'var(--space-lg)';
                        
                        const message = document.createElement('p');
                        message.textContent = 'Dieser Dateityp kann nicht direkt angezeigt werden.';
                        message.style.marginBottom = 'var(--space-md)';
                        
                        const downloadHint = document.createElement('p');
                        downloadHint.textContent = 'Bitte laden Sie die Datei herunter, um sie zu öffnen.';
                        downloadHint.style.color = 'var(--text-muted)';
                        
                        notViewableMessage.appendChild(icon);
                        notViewableMessage.appendChild(message);
                        notViewableMessage.appendChild(downloadHint);
                        
                        modalBody.appendChild(notViewableMessage);
                    }}
                    
                    // Modal anzeigen mit Animation
                    fileViewerModal.style.display = 'block';
                    document.body.style.overflow = 'hidden'; // Scroll verhindern
                    
                    // Bei Klick außerhalb des Modals schließen
                    fileViewerModal.addEventListener('click', function(event) {{
                        if (event.target === fileViewerModal) {{
                            closeModal();
                        }}
                    }});
                    
                    // ESC-Taste zum Schließen
                    document.addEventListener('keydown', closeModalOnEscape);
                }}
                
                // Schließen mit ESC-Taste
                function closeModalOnEscape(e) {{
                    if (e.key === 'Escape') {{
                        closeModal();
                    }}
                }}
                
                // Modal schließen
                function closeModal() {{
                    fileViewerModal.style.display = 'none';
                    document.body.style.overflow = ''; // Scroll wiederherstellen
                    modalBody.innerHTML = '';  // Inhalte entfernen
                    document.removeEventListener('keydown', closeModalOnEscape);
                }}
                
                // Zeigt den Copy-Toast an
                function showCopyToast() {{
                    copyToast.classList.add('show');
                    setTimeout(() => {{
                        copyToast.classList.remove('show');
                    }}, 2000);
                }}
                
                // Hilfsfunktionen
                function formatFileSize(bytes) {{
                    if (bytes < 1024) return bytes + ' Bytes';
                    else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
                    else if (bytes < 1073741824) return (bytes / 1048576).toFixed(1) + ' MB';
                    else return (bytes / 1073741824).toFixed(1) + ' GB';
                }}
                
                function formatDate(timestamp) {{
                    const date = new Date(timestamp * 1000);
                    const options = {{ 
                        day: '2-digit', 
                        month: '2-digit', 
                        year: 'numeric',
                        hour: '2-digit',
                        minute: '2-digit'
                    }};
                    return new Intl.DateTimeFormat('de-DE', options).format(date);
                }}
                
                // Liefert ein Icon basierend auf dem Dateityp
                function getFileTypeIcon(filename) {{
                    const ext = filename.split('.').pop().toLowerCase();
                    
                    // Dateityp Icon Mapping
                    const iconMap = {{
                        // Dokumente
                        'pdf': '<i class="fas fa-file-pdf"></i>',
                        'doc': '<i class="fas fa-file-word"></i>',
                        'docx': '<i class="fas fa-file-word"></i>',
                        'xls': '<i class="fas fa-file-excel"></i>',
                        'xlsx': '<i class="fas fa-file-excel"></i>',
                        'ppt': '<i class="fas fa-file-powerpoint"></i>',
                        'pptx': '<i class="fas fa-file-powerpoint"></i>',
                        'txt': '<i class="fas fa-file-alt"></i>',
                        
                        // Bilder
                        'jpg': '<i class="fas fa-file-image"></i>',
                        'jpeg': '<i class="fas fa-file-image"></i>',
                        'png': '<i class="fas fa-file-image"></i>',
                        'gif': '<i class="fas fa-file-image"></i>',
                        'svg': '<i class="fas fa-file-image"></i>',
                        'webp': '<i class="fas fa-file-image"></i>',
                        'bmp': '<i class="fas fa-file-image"></i>',
                        
                        // Audio & Video
                        'mp3': '<i class="fas fa-file-audio"></i>',
                        'wav': '<i class="fas fa-file-audio"></i>',
                        'ogg': '<i class="fas fa-file-audio"></i>',
                        'mp4': '<i class="fas fa-file-video"></i>',
                        'webm': '<i class="fas fa-file-video"></i>',
                        'avi': '<i class="fas fa-file-video"></i>',
                        'mov': '<i class="fas fa-file-video"></i>',
                        
                        // Archive
                        'zip': '<i class="fas fa-file-archive"></i>',
                        'rar': '<i class="fas fa-file-archive"></i>',
                        '7z': '<i class="fas fa-file-archive"></i>',
                        'tar': '<i class="fas fa-file-archive"></i>',
                        'gz': '<i class="fas fa-file-archive"></i>',
                        
                        // Code
                        'html': '<i class="fas fa-file-code"></i>',
                        'css': '<i class="fas fa-file-code"></i>',
                        'js': '<i class="fas fa-file-code"></i>',
                        'php': '<i class="fas fa-file-code"></i>',
                        'py': '<i class="fas fa-file-code"></i>',
                        'json': '<i class="fas fa-file-code"></i>',
                        'xml': '<i class="fas fa-file-code"></i>',
                        
                        // Sonstige
                        'exe': '<i class="fas fa-cog"></i>',
                    }};
                    
                    return iconMap[ext] || '<i class="fas fa-file"></i>';
                }}
                
                // In die Zwischenablage kopieren
                function copyToClipboard(text) {{
                    if (navigator.clipboard && navigator.clipboard.writeText) {{
                        navigator.clipboard.writeText(text)
                            .catch(err => {{
                                console.error('Fehler beim Kopieren: ', err);
                                fallbackCopyTextToClipboard(text);
                            }});
                    }} else {{
                        fallbackCopyTextToClipboard(text);
                    }}
                }}
                
                // Fallback für ältere Browser
                function fallbackCopyTextToClipboard(text) {{
                    const textArea = document.createElement('textarea');
                    textArea.value = text;
                    textArea.style.position = 'fixed';
                    textArea.style.left = '-9999px';
                    textArea.style.top = '-9999px';
                    document.body.appendChild(textArea);
                    textArea.focus();
                    textArea.select();
                    
                    try {{
                        document.execCommand('copy');
                    }} catch (err) {{
                        console.error('Fallback Fehler beim Kopieren: ', err);
                    }}
                    
                    document.body.removeChild(textArea);
                }}
                
                // Wenn Dateien gedroppt wurden und das Passwort korrekt ist, diese verwenden
                document.addEventListener('uploadPasswordCorrect', function() {{
                    if (window.droppedFiles && window.droppedFiles.length > 0) {{
                        handleFiles(window.droppedFiles);
                        window.droppedFiles = null;
                    }}
                }});
                
                // Aktualisierungsbutton
                refreshBtn.addEventListener('click', function() {{
                    // Cache leeren, um frische Daten zu bekommen
                    sessionStorage.removeItem('fileListCache');
                    // Animation für Refresh-Button
                    this.classList.add('rotating');
                    setTimeout(() => {{
                        this.classList.remove('rotating');
                    }}, 500);
                    // Dateien neu laden
                    loadFiles();
                }});
                
                // Initialisieren
                document.addEventListener('DOMContentLoaded', function() {{
                    // Dateien mit leichter Verzögerung für bessere Benutzererfahrung laden
                    setTimeout(loadFiles, 100);
                    
                    // Style für die Rotation des Refresh-Buttons hinzufügen
                    const style = document.createElement('style');
                    style.textContent = `
                        @keyframes rotation {{
                            from {{ transform: rotate(0deg); }}
                            to {{ transform: rotate(360deg); }}
                        }}
                        .rotating i {{
                            animation: rotation 0.5s linear;
                        }}
                    `;
                    document.head.appendChild(style);
                }});
            </script>
        </body>
        </html>
        """
    
    def generate_admin_page(self):
        """Generiert die modernisierte Admin-Seite"""
        banner_url = f"http://{SERVER_ADDRESS}{BANNER_PATH}"
        current_year = time.strftime('%Y')
        
        return f"""
        <!DOCTYPE html>
        <html lang="de">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Vantastic Uploads - Admin</title>
            <link rel="preconnect" href="https://fonts.googleapis.com">
            <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
            <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
            <style>
                :root {{
                    /* Haupt-Farbpalette */
                    --primary-color: #1E3A8A;
                    --primary-light: #2563EB;
                    --primary-dark: #1E40AF;
                    --accent-color: #0EA5E9;
                    --accent-light: #38BDF8;
                    --accent-dark: #0284C7;
                    
                    /* Verwaltungsfarben */
                    --admin-color: #7E22CE;
                    --admin-light: #A855F7;
                    --admin-dark: #6B21A8;
                    
                    /* Text und Hintergrund */
                    --text-color: #1E293B;
                    --text-muted: #64748B;
                    --text-light: #94A3B8;
                    --bg-color: #F8FAFC;
                    --bg-card: #FFFFFF;
                    --bg-hover: #F1F5F9;
                    
                    /* Status-Farben */
                    --success-color: #10B981;
                    --success-light: #D1FAE5;
                    --warning-color: #F59E0B;
                    --warning-light: #FEF3C7;
                    --danger-color: #EF4444;
                    --danger-light: #FEE2E2;
                    
                    /* Abstände */
                    --space-xs: 0.25rem;
                    --space-sm: 0.5rem;
                    --space-md: 1rem;
                    --space-lg: 1.5rem;
                    --space-xl: 2rem;
                    --space-2xl: 3rem;
                    
                    /* Schatten */
                    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
                    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
                    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
                    
                    /* Rahmen */
                    --border-radius-sm: 0.375rem;
                    --border-radius-md: 0.5rem;
                    --border-radius-lg: 0.75rem;
                    --border-color: #E2E8F0;
                }}
                
                * {{
                    margin: 0;
                    padding: 0;
                    box-sizing: border-box;
                }}
                
                body {{
                    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
                    font-size: 16px;
                    line-height: 1.6;
                    color: var(--text-color);
                    background-color: var(--bg-color);
                    -webkit-font-smoothing: antialiased;
                    -moz-osx-font-smoothing: grayscale;
                }}
                
                .container {{
                    max-width: 1200px;
                    margin: 0 auto;
                    padding: var(--space-lg);
                }}
                
                /* Header-Bereich */
                .header {{
                    background-color: var(--bg-card);
                    box-shadow: var(--shadow-md);
                    padding: var(--space-lg) 0;
                    position: relative;
                    top: 0;
                    z-index: 10;
                }}
                
                .header .container {{
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    padding-top: var(--space-md);
                    padding-bottom: var(--space-md);
                }}
                
                .header-banner {{
                    width: 100%;
    	 	    max-width: 1200px;
    		    min-height: 150px;
   		    object-fit: scale-down;  /* Versucht das Bild zu vergrößern, wobei das Seitenverhältnis
		beibehalten wird */
    		    margin: 0 auto;
    		    image-rendering: -webkit-optimize-contrast;  /* Verbesserung für Chrome */
   	 	    image-rendering: crisp-edges;  /* Allgemeine Verbesserung */
                }}
                
                /* Admin-Badge */
                .admin-badge {{
                    position: absolute;
                    top: 10px;
                    right: 10px;
                    background-color: var(--admin-color);
                    color: white;
                    padding: var(--space-xs) var(--space-md);
                    border-radius: var(--border-radius-md);
                    font-size: 0.875rem;
                    font-weight: 500;
                }}
                
                /* Bedienleiste */
                .toolbar {{
                    background-color: var(--bg-card);
                    border-radius: var(--border-radius-lg);
                    box-shadow: var(--shadow-sm);
                    padding: var(--space-lg);
                    margin-bottom: var(--space-xl);
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    flex-wrap: wrap;
                    gap: var(--space-md);
                }}
                
                /* Suche */
                .search-container {{
                    flex: 1;
                    max-width: 600px;
                    position: relative;
                }}
                
                .search-input {{
                    width: 100%;
                    padding: var(--space-md) var(--space-lg);
                    padding-left: calc(var(--space-lg) + 20px);
                    border: 1px solid var(--border-color);
                    border-radius: var(--border-radius-md);
                    font-size: 1rem;
                    transition: all 0.2s ease;
                }}
                
                .search-input:focus {{
                    outline: none;
                    border-color: var(--admin-color);
                    box-shadow: 0 0 0 3px rgba(126, 34, 206, 0.1);
                }}
                
                .search-icon {{
                    position: absolute;
                    left: var(--space-md);
                    top: 50%;
                    transform: translateY(-50%);
                    color: var(--text-muted);
                }}
                
                /* Schaltflächen */
                .btn {{
                    display: inline-flex;
                    align-items: center;
                    justify-content: center;
                    gap: var(--space-sm);
                    padding: var(--space-sm) var(--space-lg);
                    border-radius: var(--border-radius-md);
                    font-weight: 500;
                    font-size: 1rem;
                    cursor: pointer;
                    transition: all 0.3s ease;
                    border: none;
                    outline: none;
                    text-decoration: none;
                    white-space: nowrap;
                }}
                
                .btn-primary {{
                    background-color: var(--primary-color);
                    color: white;
                }}
                
                .btn-primary:hover, .btn-primary:focus {{
                    background-color: var(--primary-dark);
                    box-shadow: 0 4px 12px rgba(30, 58, 138, 0.3);
                    transform: translateY(-2px);
                }}
                
                .btn-admin {{
                    background-color: var(--admin-color);
                    color: white;
                }}
                
                .btn-admin:hover, .btn-admin:focus {{
                    background-color: var(--admin-dark);
                    box-shadow: 0 4px 12px rgba(126, 34, 206, 0.3);
                    transform: translateY(-2px);
                }}
                
                .btn-accent {{
                    background-color: var(--accent-color);
                    color: white;
                }}
                
                .btn-accent:hover, .btn-accent:focus {{
                    background-color: var(--accent-dark);
                    box-shadow: 0 4px 12px rgba(14, 165, 233, 0.3);
                    transform: translateY(-2px);
                }}
                
                .btn-outline {{
                    background-color: transparent;
                    color: var(--primary-color);
                    border: 1px solid var(--primary-color);
                }}
                
                .btn-outline:hover, .btn-outline:focus {{
                    background-color: var(--primary-color);
                    color: white;
                    transform: translateY(-2px);
                }}
                
                .btn-danger {{
                    background-color: var(--danger-color);
                    color: white;
                }}
                
                .btn-danger:hover, .btn-danger:focus {{
                    background-color: #dc2626;
                    box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
                    transform: translateY(-2px);
                }}
                
                /* Dateibereich */
                .files-section {{
                    background-color: var(--bg-card);
                    border-radius: var(--border-radius-lg);
                    box-shadow: var(--shadow-md);
                    padding: var(--space-xl);
                    margin-bottom: var(--space-2xl);
                }}
                
                .section-title {{
                    color: var(--admin-color);
                    font-size: 1.5rem;
                    font-weight: 600;
                    margin-bottom: var(--space-lg);
                    position: relative;
                    padding-bottom: var(--space-sm);
                }}
                
                .section-title::after {{
                    content: '';
                    position: absolute;
                    bottom: 0;
                    left: 0;
                    width: 50px;
                    height: 3px;
                    background-color: var(--admin-color);
                    border-radius: 3px;
                }}
                
                /* Spinner für Laden */
                .loading {{
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    padding: var(--space-2xl);
                }}
                
                .spinner {{
                    width: 40px;
                    height: 40px;
                    border: 3px solid rgba(126, 34, 206, 0.2);
                    border-radius: 50%;
                    border-top-color: var(--admin-color);
                    animation: spinner 1s linear infinite;
                }}
                
                @keyframes spinner {{
                    to {{ transform: rotate(360deg); }}
                }}
                
                /* Dateiliste */
                .file-row {{
                    background-color: var(--bg-card);
                    border-left: 3px solid transparent;
                    padding: var(--space-md) var(--space-lg);
                    margin-bottom: var(--space-md);
                    box-shadow: var(--shadow-sm);
                    display: flex;
                    align-items: center;
                    border-radius: var(--border-radius-md);
                    transition: all 0.3s ease;
                }}
                
                .file-row:hover {{
                    background-color: var(--bg-hover);
                    border-left-color: var(--admin-color);
                    transform: translateX(5px);
                }}
                
                .file-row-icon {{
                    flex: 0 0 40px;
                    font-size: 1.5rem;
                    color: var(--admin-color);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }}
                
                .file-row-content {{
                    flex: 1;
                    min-width: 0;
                    padding: 0 var(--space-lg);
                }}
                
                .file-row-name {{
                    font-weight: 500;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }}
                
                .file-row-meta {{
                    color: var(--text-muted);
                    font-size: 0.875rem;
                }}
                
                .file-row-actions {{
                    display: flex;
                    gap: var(--space-sm);
                }}
                
                .action-btn {{
                    background-color: var(--bg-hover);
                    color: var(--text-color);
                    border: none;
                    padding: var(--space-sm) var(--space-md);
                    border-radius: var(--border-radius-md);
                    font-size: 0.875rem;
                    cursor: pointer;
                    transition: all 0.2s ease;
                    display: flex;
                    align-items: center;
                    gap: var(--space-xs);
                }}
                
                .action-btn:hover {{
                    background-color: var(--admin-color);
                    color: white;
                }}
                
                .action-btn.view-btn:hover {{
                    background-color: var(--accent-color);
                }}
                
                .action-btn.delete-btn:hover {{
                    background-color: var(--danger-color);
                }}
                
                /* Keine Dateien Zustand */
                .empty-state {{
                    text-align: center;
                    padding: var(--space-2xl);
                    color: var(--text-muted);
                }}
                
                .empty-icon {{
                    font-size: 3rem;
                    color: var(--admin-light);
                    margin-bottom: var(--space-lg);
                }}
                
                .empty-title {{
                    font-size: 1.25rem;
                    margin-bottom: var(--space-md);
                }}
                
                .empty-message {{
                    margin-bottom: var(--space-lg);
                }}
                
                /* Paginierung */
                .pagination {{
                    display: flex;
                    justify-content: center;
                    gap: var(--space-sm);
                    margin-top: var(--space-xl);
                }}
                
                .pagination-btn {{
                    width: 40px;
                    height: 40px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    border-radius: var(--border-radius-md);
                    transition: all 0.2s ease;
                    cursor: pointer;
                    font-weight: 500;
                    border: 1px solid var(--border-color);
                    background-color: var(--bg-card);
                }}
                
                .pagination-btn.active {{
                    background-color: var(--admin-color);
                    color: white;
                    border-color: var(--admin-color);
                }}
                
                .pagination-btn:hover:not(.active):not(.disabled) {{
                    background-color: var(--bg-hover);
                    border-color: var(--admin-light);
                }}
                
                .pagination-btn.disabled {{
                    opacity: 0.5;
                    cursor: not-allowed;
                }}
                
                /* Benachrichtigungen */
                .alert {{
                    padding: var(--space-lg);
                    border-radius: var(--border-radius-md);
                    margin-bottom: var(--space-lg);
                    font-weight: 500;
                    display: flex;
                    align-items: center;
                    gap: var(--space-md);
                    opacity: 0;
                    transform: translateY(-10px);
                    transition: all 0.3s ease;
                    position: fixed;
                    top: var(--space-lg);
                    right: var(--space-lg);
                    z-index: 1000;
                    max-width: 400px;
                    box-shadow: var(--shadow-lg);
                }}
                
                .alert.show {{
                    opacity: 1;
                    transform: translateY(0);
                }}
                
                .alert-success {{
                    background-color: var(--success-light);
                    color: var(--success-color);
                }}
                
                .alert-error {{
                    background-color: var(--danger-light);
                    color: var(--danger-color);
                }}
                
                .alert-icon {{
                    font-size: 1.25rem;
                }}
                
                .alert-close {{
                    margin-left: auto;
                    cursor: pointer;
                    opacity: 0.7;
                    transition: opacity 0.2s ease;
                }}
                
                .alert-close:hover {{
                    opacity: 1;
                }}
                
                /* Modal-Fenster */
                .modal {{
                    display: none;
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background-color: rgba(15, 23, 42, 0.8);
                    z-index: 1000;
                    padding: var(--space-md);
                    overflow-y: auto;
                }}
                
                .modal-content {{
                    background-color: var(--bg-card);
                    border-radius: var(--border-radius-lg);
                    box-shadow: var(--shadow-lg);
                    width: 100%;
                    max-width: 800px;
                    margin: 5vh auto;
                    animation: modalEnter 0.3s ease;
                    overflow: hidden;
                    display: flex;
                    flex-direction: column;
                    max-height: 90vh;
                }}
                
                @keyframes modalEnter {{
                    from {{ opacity: 0; transform: scale(0.9); }}
                    to {{ opacity: 1; transform: scale(1); }}
                }}
                
                .modal-header {{
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    padding: var(--space-lg);
                    border-bottom: 1px solid var(--border-color);
                }}
                
                .modal-title {{
                    font-weight: 600;
                    color: var(--admin-color);
                    font-size: 1.25rem;
                }}
                
                .modal-close {{
                    background: none;
                    border: none;
                    font-size: 1.5rem;
                    color: var(--text-muted);
                    cursor: pointer;
                    transition: color 0.2s ease;
                }}
                
                .modal-close:hover {{
                    color: var(--danger-color);
                }}
                
                .modal-body {{
                    padding: var(--space-lg);
                    overflow-y: auto;
                    flex: 1;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }}
                
                .modal-body img {{
                    max-width: 100%;
                    max-height: 70vh;
                    object-fit: contain;
                }}
                
                .modal-body video,
                .modal-body audio {{
                    width: 100%;
                }}
                
                .modal-footer {{
                    padding: var(--space-lg);
                    border-top: 1px solid var(--border-color);
                    display: flex;
                    justify-content: flex-end;
                    gap: var(--space-md);
                }}
                
                /* Bestätigungs-Dialog */
                .confirm-modal-content {{
                    max-width: 500px;
                }}
                
                .file-info-box {{
                    background-color: var(--bg-hover);
                    padding: var(--space-md);
                    border-radius: var(--border-radius-md);
                    margin: var(--space-md) 0;
                    font-family: monospace;
                    word-break: break-all;
                }}
                
                .warning-text {{
                    color: var(--danger-color);
                    font-weight: 500;
                }}
                
                /* Toast (Kopieren) */
                .toast {{
                    position: fixed;
                    left: 50%;
                    transform: translateX(-50%);
                    bottom: var(--space-xl);
                    background-color: var(--admin-color);
                    color: white;
                    padding: var(--space-md) var(--space-xl);
                    border-radius: var(--border-radius-md);
                    box-shadow: var(--shadow-lg);
                    display: flex;
                    align-items: center;
                    gap: var(--space-md);
                    opacity: 0;
                    transition: all 0.3s ease;
                    z-index: 1001;
                }}
                
                .toast.show {{
                    opacity: 1;
                    transform: translate(-50%, -20px);
                }}
                
                /* Footer */
                .footer {{
                    background-color: var(--bg-card);
                    box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.05);
                    padding: var(--space-xl) 0;
                    text-align: center;
                    color: var(--text-muted);
                    margin-top: var(--space-2xl);
                }}
                
                .footer-content {{
                    max-width: 600px;
                    margin: 0 auto;
                }}
                
                /* Responsive Design */
                @media (max-width: 768px) {{
                    .container {{
                        padding: var(--space-md);
                    }}
                    
                    .files-section {{
                        padding: var(--space-lg);
                    }}
                    
                    .toolbar {{
                        flex-direction: column;
                        align-items: flex-start;
                    }}
                    
                    .search-container {{
                        width: 100%;
                        max-width: none;
                    }}
                    
                    .file-row {{
                        flex-direction: column;
                        align-items: flex-start;
                    }}
                    
                    .file-row-icon {{
                        margin-bottom: var(--space-sm);
                    }}
                    
                    .file-row-content {{
                        padding: var(--space-sm) 0;
                        width: 100%;
                    }}
                    
                    .file-row-actions {{
                        width: 100%;
                        justify-content: space-between;
                        margin-top: var(--space-sm);
                    }}
                    
                    .modal-content {{
                        margin: 0;
                        max-height: 100vh;
                        height: 100%;
                        border-radius: 0;
                    }}
                }}
            </style>
        </head>
        <body>
            <!-- Header mit Logo -->
            <header class="header">
                <div class="container">
                    <img src="{banner_url}" alt="Vantastic Uploads" class="header-banner">
                    <div class="admin-badge">Verwaltungsbereich</div>
                </div>
            </header>
            
            <div class="container">
                <!-- Toolbar mit Suche und Aktionsbuttons -->
                <div class="toolbar">
                    <a href="/" class="btn btn-primary">
                        <i class="fas fa-arrow-left"></i> Zurück zur Startseite
                    </a>
                    
                    <div class="search-container">
                        <i class="fas fa-search search-icon"></i>
                        <input type="text" id="searchInput" class="search-input" placeholder="Dateien suchen...">
                    </div>
                    
                    <button id="refreshBtn" class="btn btn-outline">
                        <i class="fas fa-sync-alt"></i> Aktualisieren
                    </button>
                </div>
                
                <!-- Hauptbereich: Dateiverwaltung -->
                <section class="files-section">
                    <h2 class="section-title">Dateiverwaltung</h2>
                    
                    <!-- Ladeanimation -->
                    <div id="loading" class="loading">
                        <div class="spinner"></div>
                    </div>
                    
                    <!-- Dateiliste (wird dynamisch befüllt) -->
                    <div id="filesList"></div>
                    
                    <!-- Paginierung (wird dynamisch befüllt) -->
                    <div id="pagination" class="pagination"></div>
                </section>
            </div>
            
            <!-- Erfolgsmeldung -->
            <div id="successAlert" class="alert alert-success">
                <div class="alert-icon"><i class="fas fa-check-circle"></i></div>
                <div class="alert-message">Datei erfolgreich gelöscht!</div>
                <div class="alert-close"><i class="fas fa-times"></i></div>
            </div>
            
            <!-- Fehlermeldung -->
            <div id="errorAlert" class="alert alert-error">
                <div class="alert-icon"><i class="fas fa-exclamation-circle"></i></div>
                <div class="alert-message">Fehler beim Löschen der Datei.</div>
                <div class="alert-close"><i class="fas fa-times"></i></div>
            </div>
            
            <!-- Toast Benachrichtigung (Kopieren) -->
            <div id="copyToast" class="toast">
                <i class="fas fa-check-circle"></i>
                <span>Link in Zwischenablage kopiert!</span>
            </div>
            
            <!-- Modal-Fenster für Dateivorschau -->
            <div id="fileViewerModal" class="modal">
                <div class="modal-content">
                    <div class="modal-header">
                        <h3 id="modalTitle" class="modal-title">Dateiname</h3>
                        <button class="modal-close" onclick="closeModal()">×</button>
                    </div>
                    <div id="modalBody" class="modal-body">
                        <!-- Hier wird der Inhalt dynamisch eingefügt -->
                    </div>
                    <div class="modal-footer">
                        <a id="modalDownloadLink" href="#" class="btn btn-accent">
                            <i class="fas fa-download"></i> Herunterladen
                        </a>
                    </div>
                </div>
            </div>
            
            <!-- Bestätigungsdialog für Löschen -->
            <div id="confirmationModal" class="modal">
                <div class="modal-content confirm-modal-content">
                    <div class="modal-header">
                        <h3 class="modal-title">Datei löschen</h3>
                        <button class="modal-close" onclick="closeConfirmModal()">×</button>
                    </div>
                    <div class="modal-body" style="display: block; text-align:left;">
                        <p>Sind Sie sicher, dass Sie die folgende Datei löschen möchten?</p>
                        <div id="fileToDelete" class="file-info-box"></div>
                        <p class="warning-text">Diese Aktion kann nicht rückgängig gemacht werden.</p>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-outline" onclick="closeConfirmModal()">Abbrechen</button>
                        <button id="confirmDeleteBtn" class="btn btn-danger">
                            <i class="fas fa-trash-alt"></i> Löschen
                        </button>
                    </div>
                </div>
            </div>
            
            <!-- Footer -->
            <footer class="footer">
                <div class="footer-content">
                    <p>&copy; {current_year} Vantastic Uploads. Alle Rechte vorbehalten.</p>
                </div>
            </footer>
            
            <script>
                // DOM-Elemente
                const loading = document.getElementById('loading');
                const filesList = document.getElementById('filesList');
                const pagination = document.getElementById('pagination');
                const searchInput = document.getElementById('searchInput');
                const refreshBtn = document.getElementById('refreshBtn');
                const confirmationModal = document.getElementById('confirmationModal');
                const fileToDeleteElem = document.getElementById('fileToDelete');
                const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
                const successAlert = document.getElementById('successAlert');
                const errorAlert = document.getElementById('errorAlert');
                const copyToast = document.getElementById('copyToast');
                const fileViewerModal = document.getElementById('fileViewerModal');
                const modalTitle = document.getElementById('modalTitle');
                const modalBody = document.getElementById('modalBody');
                const modalDownloadLink = document.getElementById('modalDownloadLink');
                
                // Status-Variablen
                let allFiles = [];
                let filteredFiles = [];
                let currentPage = 1;
                const filesPerPage = 10;
                let fileToDelete = '';
                
                // Event-Listener
                searchInput.addEventListener('input', debounce(filterFiles, 300));
                
                
                // Debounce-Funktion, um zu häufige Aufrufe zu vermeiden
                function debounce(func, delay) {{
                    let timeout;
                    return function() {{
                        const context = this;
                        const args = arguments;
                        clearTimeout(timeout);
                        timeout = setTimeout(() => func.apply(context, args), delay);
                    }};
                }}
                
                // Alert-Schließen-Buttons
                document.querySelectorAll('.alert-close').forEach(closeBtn => {{
                    closeBtn.addEventListener('click', (e) => {{
                        const alert = e.target.closest('.alert');
                        alert.classList.remove('show');
                    }});
                }});
                
                // Benachrichtigung anzeigen
                function showAlert(alert, message) {{
                    const messageEl = alert.querySelector('.alert-message');
                    messageEl.textContent = message;
                    
                    alert.classList.add('show');
                    
                    // Nach 5 Sekunden ausblenden
                    setTimeout(() => {{
                        alert.classList.remove('show');
                    }}, 5000);
                }}

                // Dateien laden
                function loadFiles() {{
                    loading.style.display = 'flex';
                    filesList.innerHTML = '';
                    pagination.innerHTML = '';
                    
                    // Cache für die API-Antwort verwenden, wenn verfügbar
                    const cachedFiles = sessionStorage.getItem('adminFileListCache');
                    const cacheTimestamp = sessionStorage.getItem('adminFileListCacheTime');
                    const now = Date.now();
                    
                    // Cache verwenden, wenn er nicht älter als 30 Sekunden ist
                    if (cachedFiles && cacheTimestamp && (now - parseInt(cacheTimestamp)) < 30000) {{
                        try {{
                            const files = JSON.parse(cachedFiles);
                            processFiles(files);
                            return;
                        }} catch (e) {{
                            console.error('Fehler beim Verarbeiten des Admin-Cache:', e);
                        }}
                    }}
                    
                    fetch('/list-files')
                        .then(response => response.json())
                        .then(files => {{
                            // Ergebnis im Cache speichern
                            sessionStorage.setItem('adminFileListCache', JSON.stringify(files));
                            sessionStorage.setItem('adminFileListCacheTime', Date.now().toString());
                            
                            processFiles(files);
                        }})
                        .catch(error => {{
                            loading.style.display = 'none';
                            
                            // Leerer Zustand anzeigen
                            filesList.innerHTML = `
                                <div class="empty-state">
                                    <div class="empty-icon">
                                        <i class="fas fa-exclamation-circle"></i>
                                    </div>
                                    <div class="empty-title">Fehler beim Laden der Dateien</div>
                                    <div class="empty-message">${{error.message}}</div>
                                    <button class="btn btn-admin" onclick="loadFiles()">
                                        <i class="fas fa-sync-alt"></i> Erneut versuchen
                                    </button>
                                </div>
                            `;
                        }});
                }}
                
                // Verarbeitet die geladenen Dateien
                function processFiles(files) {{
                    loading.style.display = 'none';
                    
                    // Dateien nach Datum sortieren (neueste zuerst)
                    files.sort((a, b) => b.timestamp - a.timestamp);
                    
                    allFiles = files;
                    filteredFiles = [...files];
                    
                    if (files.length === 0) {{
                        // Leerer Zustand anzeigen
                        filesList.innerHTML = `
                            <div class="empty-state">
                                <div class="empty-icon">
                                    <i class="fas fa-folder-open"></i>
                                </div>
                                <div class="empty-title">Keine Dateien vorhanden</div>
                                <div class="empty-message">Es wurden noch keine Dateien hochgeladen.</div>
                                <a href="/" class="btn btn-admin">
                                    <i class="fas fa-upload"></i> Zum Upload-Bereich
                                </a>
                            </div>
                        `;
                        return;
                    }}
                    
                    displayFiles();
                }}
                
                // Filtert die Dateien basierend auf dem Suchbegriff
                function filterFiles() {{
                    const searchTerm = searchInput.value.trim().toLowerCase();
                    
                    if (searchTerm === '') {{
                        filteredFiles = [...allFiles];
                    }} else {{
                        filteredFiles = allFiles.filter(file => 
                            file.name.toLowerCase().includes(searchTerm)
                        );
                    }}
                    
                    currentPage = 1;
                    displayFiles();
                }}
                
                // Zeigt die gefilterten Dateien an
                function displayFiles() {{
                    filesList.innerHTML = '';
                    
                    // Keine Dateien gefunden
                    if (filteredFiles.length === 0) {{
                        filesList.innerHTML = `
                            <div class="empty-state">
                                <div class="empty-icon">
                                    <i class="fas fa-search"></i>
                                </div>
                                <div class="empty-title">Keine Dateien gefunden</div>
                                <div class="empty-message">Keine Dateien entsprechen Ihren Suchkriterien.</div>
                                <button class="btn btn-outline" onclick="resetSearch()">
                                    <i class="fas fa-times"></i> Suche zurücksetzen
                                </button>
                            </div>
                        `;
                        pagination.innerHTML = '';
                        return;
                    }}
                    
                    // Paginierung berechnen
                    const totalPages = Math.ceil(filteredFiles.length / filesPerPage);
                    const startIndex = (currentPage - 1) * filesPerPage;
                    const endIndex = Math.min(startIndex + filesPerPage, filteredFiles.length);
                    
                    // Aktuell angezeigte Dateien
                    const currentFiles = filteredFiles.slice(startIndex, endIndex);
                    
                    // Dateien anzeigen
                    currentFiles.forEach(file => {{
                        const fileRow = document.createElement('div');
                        fileRow.className = 'file-row';
                        
                        const fileRowIcon = document.createElement('div');
                        fileRowIcon.className = 'file-row-icon';
                        fileRowIcon.innerHTML = getFileTypeIcon(file.name);
                        
                        const fileRowContent = document.createElement('div');
                        fileRowContent.className = 'file-row-content';
                        
                        const fileRowName = document.createElement('div');
                        fileRowName.className = 'file-row-name';
                        fileRowName.textContent = file.name;
                        fileRowContent.appendChild(fileRowName);
                        
                        const fileRowMeta = document.createElement('div');
                        fileRowMeta.className = 'file-row-meta';
                        fileRowMeta.textContent = `${{formatFileSize(file.size)}} • Hochgeladen am ${{formatDate(file.timestamp)}}`;
                        fileRowContent.appendChild(fileRowMeta);
                        
                        const fileRowActions = document.createElement('div');
                        fileRowActions.className = 'file-row-actions';
                        
                        // Prüfen, ob die Datei im Browser angezeigt werden kann
                        const isViewable = isViewableInBrowser(file.name);
                        
                        if (isViewable) {{
                            const viewButton = document.createElement('button');
                            viewButton.className = 'action-btn view-btn';
                            viewButton.innerHTML = '<i class="fas fa-eye"></i> Anzeigen';
                            viewButton.onclick = function() {{
                                showFileInModal(file);
                            }};
                            fileRowActions.appendChild(viewButton);
                        }}
                        
                        const downloadLink = document.createElement('a');
                        downloadLink.href = file.download_url;
                        downloadLink.className = 'action-btn';
                        downloadLink.innerHTML = '<i class="fas fa-download"></i> Download';
                        downloadLink.setAttribute('download', '');
                        fileRowActions.appendChild(downloadLink);
                        
                        const copyLinkBtn = document.createElement('button');
                        copyLinkBtn.className = 'action-btn';
                        copyLinkBtn.innerHTML = '<i class="fas fa-link"></i> Link kopieren';
                        copyLinkBtn.onclick = function() {{
                            copyToClipboard(file.full_url);
                            showCopyToast();
                        }};
                        fileRowActions.appendChild(copyLinkBtn);
                        
                        const deleteBtn = document.createElement('button');
                        deleteBtn.className = 'action-btn delete-btn';
                        deleteBtn.innerHTML = '<i class="fas fa-trash-alt"></i> Löschen';
                        deleteBtn.onclick = function() {{
                            showDeleteConfirmation(file.name);
                        }};
                        fileRowActions.appendChild(deleteBtn);
                        
                        fileRow.appendChild(fileRowIcon);
                        fileRow.appendChild(fileRowContent);
                        fileRow.appendChild(fileRowActions);
                        
                        filesList.appendChild(fileRow);
                    }});
                    
                    // Paginierung anzeigen
                    updatePagination(totalPages);
                }}
                
                // Aktualisiert die Paginierungssteuerung
                function updatePagination(totalPages) {{
                    pagination.innerHTML = '';
                    
                    if (totalPages <= 1) return;
                    
                    // Zurück-Button
                    const prevBtn = document.createElement('button');
                    prevBtn.className = 'pagination-btn' + (currentPage === 1 ? ' disabled' : '');
                    prevBtn.innerHTML = '<i class="fas fa-chevron-left"></i>';
                    prevBtn.disabled = currentPage === 1;
                    
                    if (currentPage > 1) {{
                        prevBtn.onclick = () => {{
                            currentPage--;
                            displayFiles();
                            // Nach oben scrollen
                            window.scrollTo({{ top: document.querySelector('.files-section').offsetTop - 20, behavior: 'smooth' }});
                        }};
                    }}
                    
                    pagination.appendChild(prevBtn);
                    
                    // Seitenzahlen
                    const maxVisiblePages = 5;
                    let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
                    let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);
                    
                    if (endPage - startPage + 1 < maxVisiblePages) {{
                        startPage = Math.max(1, endPage - maxVisiblePages + 1);
                    }}
                    
                    for (let i = startPage; i <= endPage; i++) {{
                        const pageBtn = document.createElement('button');
                        pageBtn.className = 'pagination-btn' + (i === currentPage ? ' active' : '');
                        pageBtn.textContent = i;
                        
                        if (i !== currentPage) {{
                            pageBtn.onclick = () => {{
                                currentPage = i;
                                displayFiles();
                                // Nach oben scrollen
                                window.scrollTo({{ top: document.querySelector('.files-section').offsetTop - 20, behavior: 'smooth' }});
                            }};
                        }}
                        
                        pagination.appendChild(pageBtn);
                    }}
                    
                    // Weiter-Button
                    const nextBtn = document.createElement('button');
                    nextBtn.className = 'pagination-btn' + (currentPage === totalPages ? ' disabled' : '');
                    nextBtn.innerHTML = '<i class="fas fa-chevron-right"></i>';
                    nextBtn.disabled = currentPage === totalPages;
                    
                    if (currentPage < totalPages) {{
                        nextBtn.onclick = () => {{
                            currentPage++;
                            displayFiles();
                            // Nach oben scrollen
                            window.scrollTo({{ top: document.querySelector('.files-section').offsetTop - 20, behavior: 'smooth' }});
                        }};
                    }}
                    
                    pagination.appendChild(nextBtn);
                }}
                
                // Prüft, ob eine Datei direkt im Browser angezeigt werden kann
                function isViewableInBrowser(filename) {{
                    const extension = filename.split('.').pop().toLowerCase();
                    const viewableExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'mp3', 'mp4', 'webm', 'ogg', 'pdf', 'txt'];
                    return viewableExtensions.includes(extension);
                }}
                
                // Modal öffnen und Datei anzeigen
                function showFileInModal(file) {{
                    // Modal-Titel setzen
                    modalTitle.textContent = file.name;
                    
                    // Download-Link setzen
                    modalDownloadLink.href = file.download_url;
                    
                    // Modal-Inhalt leeren
                    modalBody.innerHTML = '';
                    
                    // Dateityp bestimmen und entsprechenden Inhalt laden
                    const fileExtension = file.name.split('.').pop().toLowerCase();
                    
                    if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(fileExtension)) {{
                        // Bild anzeigen
                        const img = document.createElement('img');
                        img.src = file.download_url + '?view=true';
                        img.alt = file.name;
                        modalBody.appendChild(img);
                    }} else if (['mp4', 'webm', 'ogg'].includes(fileExtension)) {{
                        // Video anzeigen
                        const video = document.createElement('video');
                        video.controls = true;
                        video.autoplay = false;
                        const source = document.createElement('source');
                        source.src = file.download_url + '?view=true';
                        source.type = `video/${{fileExtension}}`;
                        video.appendChild(source);
                        modalBody.appendChild(video);
                    }} else if (['mp3', 'wav'].includes(fileExtension)) {{
                        // Audio anzeigen
                        const audio = document.createElement('audio');
                        audio.controls = true;
                        audio.autoplay = false;
                        const source = document.createElement('source');
                        source.src = file.download_url + '?view=true';
                        source.type = `audio/${{fileExtension === 'mp3' ? 'mpeg' : fileExtension}}`;
                        audio.appendChild(source);
                        modalBody.appendChild(audio);
                    }} else if (fileExtension === 'pdf') {{
                        // PDF anzeigen
                        const iframe = document.createElement('iframe');
                        iframe.src = file.download_url + '?view=true';
                        iframe.width = '100%';
                        iframe.height = '70vh';
                        iframe.style.border = 'none';
                        modalBody.appendChild(iframe);
                    }} else if (fileExtension === 'txt') {{
                        // Text anzeigen mit Ladeanimation
                        const loadingSpinner = document.createElement('div');
                        loadingSpinner.className = 'spinner';
                        modalBody.appendChild(loadingSpinner);
                        
                        fetch(file.download_url + '?view=true')
                            .then(response => response.text())
                            .then(text => {{
                                modalBody.innerHTML = '';  // Spinner entfernen
                                const pre = document.createElement('pre');
                                pre.style.textAlign = 'left';
                                pre.style.overflow = 'auto';
                                pre.style.padding = 'var(--space-md)';
                                pre.style.whiteSpace = 'pre-wrap';
                                pre.style.wordBreak = 'break-word';
                                pre.style.maxHeight = '70vh';
                                pre.style.background = '#f8f9fa';
                                pre.style.borderRadius = 'var(--border-radius-sm)';
                                pre.textContent = text;
                                modalBody.appendChild(pre);
                            }})
                            .catch(error => {{
                                modalBody.innerHTML = '';
                                modalBody.textContent = 'Fehler beim Laden der Textdatei: ' + error.message;
                            }});
                    }} else {{
                        // Nicht anzeigbarer Dateityp
                        const notViewableMessage = document.createElement('div');
                        notViewableMessage.style.textAlign = 'center';
                        notViewableMessage.style.padding = 'var(--space-2xl)';
                        
                        const icon = document.createElement('div');
                        icon.innerHTML = '<i class="fas fa-file-download"></i>';
                        icon.style.fontSize = '4rem';
                        icon.style.color = 'var(--admin-color)';
                        icon.style.marginBottom = 'var(--space-lg)';
                        
                        const message = document.createElement('p');
                        message.textContent = 'Dieser Dateityp kann nicht direkt angezeigt werden.';
                        message.style.marginBottom = 'var(--space-md)';
                        
                        const downloadHint = document.createElement('p');
                        downloadHint.textContent = 'Bitte laden Sie die Datei herunter, um sie zu öffnen.';
                        downloadHint.style.color = 'var(--text-muted)';
                        
                        notViewableMessage.appendChild(icon);
                        notViewableMessage.appendChild(message);
                        notViewableMessage.appendChild(downloadHint);
                        
                        modalBody.appendChild(notViewableMessage);
                    }}
                    
                    // Modal anzeigen mit Animation
                    fileViewerModal.style.display = 'block';
                    document.body.style.overflow = 'hidden'; // Scroll verhindern
                    
                    // Bei Klick außerhalb des Modals schließen
                    fileViewerModal.addEventListener('click', function(event) {{
                        if (event.target === fileViewerModal) {{
                            closeModal();
                        }}
                    }});
                    
                    // ESC-Taste zum Schließen
                    document.addEventListener('keydown', closeModalOnEscape);
                }}
                
                // Schließen mit ESC-Taste
                function closeModalOnEscape(e) {{
                    if (e.key === 'Escape') {{
                        closeModal();
                    }}
                }}
                
                // Modal schließen
                function closeModal() {{
                    fileViewerModal.style.display = 'none';
                    document.body.style.overflow = ''; // Scroll wiederherstellen
                    modalBody.innerHTML = '';  // Inhalte entfernen
                    document.removeEventListener('keydown', closeModalOnEscape);
                }}
                
                // Lösch-Bestätigungsdialog anzeigen
                function showDeleteConfirmation(filename) {{
                    fileToDelete = filename;
                    fileToDeleteElem.textContent = filename;
                    confirmationModal.style.display = 'block';
                    document.body.style.overflow = 'hidden'; // Scroll verhindern
                    
                    confirmDeleteBtn.onclick = function() {{
                        deleteFile(filename);
                    }};
                    
                    // ESC-Taste zum Schließen
                    document.addEventListener('keydown', closeConfirmModalOnEscape);
                    
                    // Bei Klick außerhalb des Modals schließen
                    confirmationModal.addEventListener('click', function(event) {{
                        if (event.target === confirmationModal) {{
                            closeConfirmModal();
                        }}
                    }});
                }}
                
                // Schließen mit ESC-Taste
                function closeConfirmModalOnEscape(e) {{
                    if (e.key === 'Escape') {{
                        closeConfirmModal();
                    }}
                }}
                
                // Bestätigungsmodal schließen
                function closeConfirmModal() {{
                    confirmationModal.style.display = 'none';
                    document.body.style.overflow = ''; // Scroll wiederherstellen
                    document.removeEventListener('keydown', closeConfirmModalOnEscape);
                }}
                
                // Zeigt den Copy-Toast an
                function showCopyToast() {{
                    copyToast.classList.add('show');
                    setTimeout(() => {{
                        copyToast.classList.remove('show');
                    }}, 2000);
                }}
                
                // Datei löschen
                function deleteFile(filename) {{
                    loading.style.display = 'flex';
                    
                    fetch('/delete-file', {{
                        method: 'POST',
                        headers: {{
                            'Content-Type': 'application/json'
                        }},
                        body: JSON.stringify({{ filename: filename }})
                    }})
                    .then(response => {{
                        if (!response.ok) {{
                            throw new Error('Server-Fehler: ' + response.status);
                        }}
                        return response.json();
                    }})
                    .then(data => {{
                        loading.style.display = 'none';
                        closeConfirmModal();
                        
                        if (data.success) {{
                            showAlert(successAlert, `Die Datei "${{filename}}" wurde erfolgreich gelöscht.`);
                            
                            // Cache leeren
                            sessionStorage.removeItem('adminFileListCache');
                            sessionStorage.removeItem('fileListCache');
                            
                            // Dateien neu laden
                            loadFiles();
                        }} else {{
                            showAlert(errorAlert, `Fehler: ${{data.error || 'Unbekannter Fehler'}}`);
                        }}
                    }})
                    .catch(error => {{
                        loading.style.display = 'none';
                        closeConfirmModal();
                        showAlert(errorAlert, `Fehler: ${{error.message}}`);
                    }});
                }}
                
                // Suche zurücksetzen
                function resetSearch() {{
                    searchInput.value = '';
                    filteredFiles = [...allFiles];
                    currentPage = 1;
                    displayFiles();
                }}
                
                // Hilfsfunktionen
                function formatFileSize(bytes) {{
                    if (bytes < 1024) return bytes + ' Bytes';
                    else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
                    else if (bytes < 1073741824) return (bytes / 1048576).toFixed(1) + ' MB';
                    else return (bytes / 1073741824).toFixed(1) + ' GB';
                }}
                
                function formatDate(timestamp) {{
                    const date = new Date(timestamp * 1000);
                    const options = {{ 
                        day: '2-digit', 
                        month: '2-digit', 
                        year: 'numeric',
                        hour: '2-digit',
                        minute: '2-digit'
                    }};
                    return new Intl.DateTimeFormat('de-DE', options).format(date);
                }}
                
                // Liefert ein Icon basierend auf dem Dateityp
                function getFileTypeIcon(filename) {{
                    const ext = filename.split('.').pop().toLowerCase();
                    
                    // Dateityp Icon Mapping
                    const iconMap = {{
                        // Dokumente
                        'pdf': '<i class="fas fa-file-pdf"></i>',
                        'doc': '<i class="fas fa-file-word"></i>',
                        'docx': '<i class="fas fa-file-word"></i>',
                        'xls': '<i class="fas fa-file-excel"></i>',
                        'xlsx': '<i class="fas fa-file-excel"></i>',
                        'ppt': '<i class="fas fa-file-powerpoint"></i>',
                        'pptx': '<i class="fas fa-file-powerpoint"></i>',
                        'txt': '<i class="fas fa-file-alt"></i>',
                        
                        // Bilder
                        'jpg': '<i class="fas fa-file-image"></i>',
                        'jpeg': '<i class="fas fa-file-image"></i>',
                        'png': '<i class="fas fa-file-image"></i>',
                        'gif': '<i class="fas fa-file-image"></i>',
                        'svg': '<i class="fas fa-file-image"></i>',
                        'webp': '<i class="fas fa-file-image"></i>',
                        'bmp': '<i class="fas fa-file-image"></i>',
                        
                        // Audio & Video
                        'mp3': '<i class="fas fa-file-audio"></i>',
                        'wav': '<i class="fas fa-file-audio"></i>',
                        'ogg': '<i class="fas fa-file-audio"></i>',
                        'mp4': '<i class="fas fa-file-video"></i>',
                        'webm': '<i class="fas fa-file-video"></i>',
                        'avi': '<i class="fas fa-file-video"></i>',
                        'mov': '<i class="fas fa-file-video"></i>',
                        
                        // Archive
                        'zip': '<i class="fas fa-file-archive"></i>',
                        'rar': '<i class="fas fa-file-archive"></i>',
                        '7z': '<i class="fas fa-file-archive"></i>',
                        'tar': '<i class="fas fa-file-archive"></i>',
                        'gz': '<i class="fas fa-file-archive"></i>',
                        
                        // Code
                        'html': '<i class="fas fa-file-code"></i>',
                        'css': '<i class="fas fa-file-code"></i>',
                        'js': '<i class="fas fa-file-code"></i>',
                        'php': '<i class="fas fa-file-code"></i>',
                        'py': '<i class="fas fa-file-code"></i>',
                        'json': '<i class="fas fa-file-code"></i>',
                        'xml': '<i class="fas fa-file-code"></i>',
                        
                        // Sonstige
                        'exe': '<i class="fas fa-cog"></i>',
                    }};
                    
                    return iconMap[ext] || '<i class="fas fa-file"></i>';
                }}
                
                // In die Zwischenablage kopieren
                function copyToClipboard(text) {{
                    if (navigator.clipboard && navigator.clipboard.writeText) {{
                        navigator.clipboard.writeText(text)
                            .catch(err => {{
                                console.error('Fehler beim Kopieren: ', err);
                                fallbackCopyTextToClipboard(text);
                            }});
                    }} else {{
                        fallbackCopyTextToClipboard(text);
                    }}
                }}
                
                // Fallback für ältere Browser
                function fallbackCopyTextToClipboard(text) {{
                    const textArea = document.createElement('textarea');
                    textArea.value = text;
                    textArea.style.position = 'fixed';
                    textArea.style.left = '-9999px';
                    textArea.style.top = '-9999px';
                    document.body.appendChild(textArea);
                    textArea.focus();
                    textArea.select();
                    
                    try {{
                        document.execCommand('copy');
                    }} catch (err) {{
                        console.error('Fallback Fehler beim Kopieren: ', err);
                    }}
                    
                    document.body.removeChild(textArea);
                }}
                
                // Aktualisierungsbutton
                refreshBtn.addEventListener('click', function() {{
                    // Cache leeren, um frische Daten zu bekommen
                    sessionStorage.removeItem('adminFileListCache');
                    // Animation für Refresh-Button
                    this.classList.add('rotating');
                    setTimeout(() => {{
                        this.classList.remove('rotating');
                    }}, 500);
                    // Dateien neu laden
                    loadFiles();
                }});
                
                // Initialisieren
                document.addEventListener('DOMContentLoaded', function() {{
                    // Dateien mit leichter Verzögerung für bessere Benutzererfahrung laden
                    setTimeout(loadFiles, 100);
                    
                    // Style für die Rotation des Refresh-Buttons hinzufügen
                    const style = document.createElement('style');
                    style.textContent = `
                        @keyframes rotation {{
                            from {{ transform: rotate(0deg); }}
                            to {{ transform: rotate(360deg); }}
                        }}
                        .rotating i {{
                            animation: rotation 0.5s linear;
                        }}
                    `;
                    document.head.appendChild(style);
                }});
            </script>
        </body>
        </html>
        """

    def parse_multipart(self, data, boundary):
        """Parse multipart/form-data"""
        boundary = b'--' + boundary
        parts = data.split(boundary)
        form_data = {}
        
        # Der erste Teil ist leer und der letzte Teil enthält die Grenzlinien-Endmarkierung
        parts = parts[1:-1]
        
        for part in parts:
            # Die ersten zwei Bytes entfernen (CR LF)
            part = part[2:]
            # Bei leeren Teilen überspringen
            if not part.strip():
                continue
            
            # Kopfdaten und Inhalt trennen
            header_end = part.find(b'\r\n\r\n')
            if header_end == -1:
                continue
            
            headers_raw = part[:header_end]
            content = part[header_end + 4:]
            
            # Wenn das Teil mit CRLF-- endet, dieses entfernen
            if content.endswith(b'\r\n--'):
                content = content[:-4]
            elif content.endswith(b'\r\n'):
                content = content[:-2]
            
            # Extrahieren des Content-Disposition-Headers
            headers = {}
            for header_line in headers_raw.split(b'\r\n'):
                if b':' in header_line:
                    header_name, header_value = header_line.split(b':', 1)
                    headers[header_name.strip().lower()] = header_value.strip()
            
            # Namen und Dateinamen aus Content-Disposition extrahieren
            content_disp = headers.get(b'content-disposition', b'')
            name_match = re.search(b'name="([^"]*)"', content_disp)
            filename_match = re.search(b'filename="([^"]*)"', content_disp)
            
            if name_match:
                field_name = name_match.group(1).decode('utf-8')
                
                # Bei Dateifeldern
                if filename_match:
                    field_value = content
                    filename = filename_match.group(1).decode('utf-8')
                    
                    if field_name not in form_data:
                        form_data[field_name] = []
                    
                    form_data[field_name].append(field_value)
                    
                    # Dateifeldname speichern
                    if 'filename' not in form_data:
                        form_data['filename'] = []
                    
                    form_data['filename'].append(filename)
                else:
                    # Bei normalen Formularfeldern
                    try:
                        field_value = content.decode('utf-8')
                    except UnicodeDecodeError:
                        field_value = content
                    
                    if field_name not in form_data:
                        form_data[field_name] = []
                    
                    form_data[field_name].append(field_value)
        
        return form_data
        
    def do_GET(self):
        try:
            path = urllib.parse.urlparse(self.path).path
            query_params = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
            
            # Health-Check Endpunkt für Client-Reconnect
            if path == '/health-check':
                self.send_response(200)
                self.send_header('Content-Type', 'application/json')
                self.end_headers()
                self.wfile.write(json.dumps({'status': 'ok'}).encode('utf-8'))
                return
            
            # Hauptseite
            if path == '/':
                self.send_html_response(self.generate_main_page())
                return
            
            # Admin-Bereich
            if path == '/admin':
                if not self.check_admin_auth():
                    self.request_admin_auth()
                    return
                
                self.send_html_response(self.generate_admin_page())
                return
            
            # Liste der Dateien abfragen
            if path == '/list-files':
                with file_list_lock:
                    current_time = time.time()
                    
                    # Cache verwenden, wenn noch gültig
                    if current_time - file_list_cache["timestamp"] < FILE_CACHE_TIMEOUT:
                        self.send_json_response(file_list_cache["data"])
                        return
                    
                    file_list = []
                    
                    try:
                        for filename in os.listdir(UPLOAD_DIR):
                            file_path = os.path.join(UPLOAD_DIR, filename)
                            if os.path.isfile(file_path):
                                file_size = os.path.getsize(file_path)
                                file_mtime = os.path.getmtime(file_path)
                                
                                file_info = {
                                    'name': filename,
                                    'size': file_size,
                                    'timestamp': int(file_mtime),
                                    'download_url': f'/uploads/{filename}',
                                    'full_url': f'http://{SERVER_ADDRESS}/uploads/{filename}'
                                }
                                
                                file_list.append(file_info)
                        
                        # Cache aktualisieren
                        file_list_cache["timestamp"] = current_time
                        file_list_cache["data"] = file_list
                        
                    except Exception as e:
                        log_message(f"Fehler beim Lesen des Upload-Verzeichnisses: {str(e)}", "ERROR")
                
                self.send_json_response(file_list)
                return
            
            # Datei herunterladen oder anzeigen
            if path.startswith('/uploads/'):
                filename = path.split('/')[-1]
                file_path = os.path.join(UPLOAD_DIR, filename)
                
                if os.path.exists(file_path) and os.path.isfile(file_path):
                    try:
                        # Dateigröße
                        file_size = os.path.getsize(file_path)
                        
                        # MIME-Typ bestimmen - Performance-Optimierung für große Dateien
                        if file_size > 100 * 1024 * 1024:  # 100 MB
                            content_type = 'application/octet-stream'  # Standardwert für große Dateien
                        else:
                            content_type, _ = mimetypes.guess_type(file_path)
                            if not content_type:
                                content_type = 'application/octet-stream'
                        
                        # Prüfen auf den view-Parameter
                        view_mode = 'view' in query_params and query_params['view'][0] == 'true'
                        
                        # Prüfen, ob die Datei angezeigt werden kann
                        extension = filename.split('.')[-1].lower() if '.' in filename else ''
                        viewable_extensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'mp3', 'mp4', 'webm', 'ogg', 'pdf', 'txt']
                        can_view = extension in viewable_extensions
                        
                        # Im View-Modus und bei anzeigbaren Dateien als Inline anzeigen
                        if view_mode and can_view:
                            self.send_response(200)
                            self.send_header('Content-Type', content_type)
                            self.send_header('Content-Length', str(file_size))
                            # Inline-Anzeige erzwingen
                            self.send_header('Content-Disposition', f'inline; filename="{filename}"')
                            self.end_headers()
                        else:
                            # Zum Download anbieten
                            self.send_response(200)
                            self.send_header('Content-Type', content_type)
                            self.send_header('Content-Length', str(file_size))
                            self.send_header('Content-Disposition', f'attachment; filename="{filename}"')
                            self.end_headers()
                        
                        # Datei in Chunks lesen und senden, um Speicherverbrauch zu reduzieren
                        with open(file_path, 'rb') as f:
                            chunk_size = 8192  # 8K Chunks
                            while True:
                                chunk = f.read(chunk_size)
                                if not chunk:
                                    break
                                try:
                                    self.wfile.write(chunk)
                                except (BrokenPipeError, ConnectionResetError):
                                    log_message(f"Client hat die Verbindung beim Herunterladen von {filename} abgebrochen", "WARNING")
                                    break
                        
                        log_message(f"Datei {filename} wurde {'angezeigt' if view_mode and can_view else 'heruntergeladen'}", "INFO")
                        return
                    except Exception as e:
                        log_message(f"Fehler beim Senden der Datei {filename}: {str(e)}", "ERROR")
                        self.send_error_response(f"Fehler beim Herunterladen der Datei: {str(e)}")
                        return
                else:
                    self.send_error_response('Die angeforderte Datei wurde nicht gefunden.', 404)
                    return
            
            # Standardmäßig 404
            self.send_error_response('Die angeforderte Seite wurde nicht gefunden.', 404)
        
        except Exception as e:
            log_message(f"Fehler beim Verarbeiten der GET-Anfrage: {str(e)}", "ERROR")
            traceback.print_exc()
            try:
                self.send_error_response(f"Ein Fehler ist aufgetreten: {str(e)}")
            except:
                pass
    
    def do_POST(self):
        try:
            path = urllib.parse.urlparse(self.path).path
            
            # Optimierte Verarbeitung von Post-Daten
            content_length = int(self.headers.get('Content-Length', 0))
            
            # Log für große Uploads
            if content_length > 100 * 1024 * 1024:  # Mehr als 100MB
                log_message(f"Großer Upload gestartet: {content_length / (1024*1024):.2f} MB", "INFO")
            
            # Für große Uploads optimiertes Chunking
            if content_length > 10 * 1024 * 1024:  # Nur für Uploads größer als 10MB
                total_read = 0
                chunk_size = 8192  # 8KB Chunks
                post_data = b''
                
                # Fortschrittsupdate-Intervall
                last_progress_update = time.time()
                
                while total_read < content_length:
                    remaining = content_length - total_read
                    read_size = min(chunk_size, remaining)
                    chunk = self.rfile.read(read_size)
                    if not chunk:
                        break
                    post_data += chunk
                    total_read += len(chunk)
                    
                    # Fortschrittsupdate alle 5 Sekunden für große Uploads
                    current_time = time.time()
                    if current_time - last_progress_update > 5 and content_length > 100 * 1024 * 1024:
                        progress = (total_read / content_length) * 100
                        log_message(f"Upload-Fortschritt: {progress:.1f}% ({total_read/(1024*1024):.1f} MB von {content_length/(1024*1024):.1f} MB)", "INFO")
                        last_progress_update = current_time
                    
                    # Speicher freigeben bei sehr großen Uploads
                    if total_read > 200 * 1024 * 1024:  # 200MB
                        import gc
                        gc.collect()
            else:
                # Standard-Verarbeitung für kleinere Uploads
                post_data = self.rfile.read(content_length)

            # Datei hochladen
            if path == '/upload':
                # Content-Type prüfen
                content_type = self.headers.get('Content-Type', '')
                
                if 'multipart/form-data' in content_type:
                    boundary = content_type.split('=')[1].encode()
                    
                    form_data = self.parse_multipart(post_data, boundary)
                    if 'file' in form_data and form_data['file'][0]:
                        file_data = form_data['file'][0]
                        filename = form_data.get('filename', ['untitled.dat'])[0]
                        
                        # Sicheren Dateinamen erstellen
                        safe_filename = self.get_safe_filename(filename)
                        file_path = os.path.join(UPLOAD_DIR, safe_filename)
                        
                        # Datei speichern
                        with open(file_path, 'wb') as f:
                            f.write(file_data)
                        
                        log_message(f"Datei {safe_filename} wurde hochgeladen ({len(file_data)} Bytes)", "INFO")
                        
                        # Cache invalidieren
                        with file_list_lock:
                            file_list_cache["timestamp"] = 0
                        
                        # Erfolgreiche Antwort senden
                        self.send_json_response({
                            'success': True, 
                            'filename': safe_filename,
                            'size': len(file_data),
                            'url': f'/uploads/{safe_filename}'
                        })
                    else:
                        self.send_json_response({'success': False, 'error': 'Keine Datei gefunden'}, 400)
                else:
                    self.send_json_response({'success': False, 'error': 'Unerwartetes Format'}, 400)
                
                return
                    
            # Datei löschen
            elif path == '/delete-file':
                # Admin-Berechtigungen prüfen
                if not self.check_admin_auth():
                    self.send_json_response({'success': False, 'error': 'Nicht autorisiert'}, 401)
                    return
                
                try:
                    # Daten parsen
                    data = json.loads(post_data.decode('utf-8'))
                    filename = data.get('filename')
                    
                    if not filename:
                        self.send_json_response({'success': False, 'error': 'Kein Dateiname angegeben'}, 400)
                        return
                    
                    # Pfadmanipulation verhindern
                    if '..' in filename or filename.startswith('/'):
                        self.send_json_response({'success': False, 'error': 'Ungültiger Dateiname'}, 400)
                        return
                    
                    # Datei löschen
                    file_path = os.path.join(UPLOAD_DIR, filename)
                    if os.path.exists(file_path) and os.path.isfile(file_path):
                        os.remove(file_path)
                        log_message(f"Datei {filename} wurde gelöscht", "INFO")
                        
                        # Cache invalidieren
                        with file_list_lock:
                            file_list_cache["timestamp"] = 0
                        
                        self.send_json_response({'success': True, 'message': f'Datei {filename} wurde gelöscht'})
                    else:
                        self.send_json_response({'success': False, 'error': 'Datei nicht gefunden'}, 404)
                except json.JSONDecodeError:
                    self.send_json_response({'success': False, 'error': 'Ungültiges JSON'}, 400)
                
                return
                
            # Unbekannter Endpunkt
            else:
                self.send_json_response({'success': False, 'error': 'Unbekannter Endpunkt'}, 404)
                
        except Exception as e:
            log_message(f"Fehler beim Verarbeiten der POST-Anfrage: {str(e)}", "ERROR")
            traceback.print_exc()
            try:
                self.send_json_response({'success': False, 'error': f'Ein Fehler ist aufgetreten: {str(e)}'}, 500)
            except:
                pass
    
    def get_safe_filename(self, filename):
        """Erstellt einen sicheren Dateinamen"""
        # Ersetzt ungültige Zeichen mit Unterstrichen
        safe_name = re.sub(r'[^\w\.-]', '_', filename)
        return safe_name


class ThreadedHTTPServer(HTTPServer):
    """Handle requests in a separate thread."""
    def __init__(self, server_address, RequestHandlerClass):
        HTTPServer.__init__(self, server_address, RequestHandlerClass)
        self.daemon_threads = True
        self.request_queue_size = 100  # Maximale Anzahl gleichzeitiger Anfragen
        
        # Socket-Optionen für bessere Stabilität
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

# Server starten
if __name__ == "__main__":
    log_message(f"Server startet auf http://{SERVER_ADDRESS}:{PORT}", "INFO")
    log_message(f"Upload-Verzeichnis: {os.path.abspath(UPLOAD_DIR)}", "INFO")
    log_message(f"Admin-Bereich: http://{SERVER_ADDRESS}/admin", "INFO")
    log_message(f"Admin-Benutzername: {ADMIN_USERNAME}", "INFO")
    log_message(f"Upload-Passwort: {UPLOAD_PASSWORD}", "INFO")
    log_message(f"Log-Datei: {os.path.abspath(LOG_FILE)}", "INFO")

    try:
        # Verbesserte Server-Klasse verwenden
        httpd = ThreadedHTTPServer(('0.0.0.0', PORT), FileServerHandler)
        
        # Socket-Optimierungen
        import socket
        httpd.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        httpd.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        httpd.request_queue_size = 100
        
        httpd.serve_forever()
    except KeyboardInterrupt:
        log_message("Server wird durch Benutzer beendet...", "INFO")
    except Exception as e:
        log_message(f"Kritischer Fehler beim Starten des Servers: {str(e)}", "ERROR")
        traceback.print_exc()