import os
import sys
import logging
import atexit
from datetime import datetime, timedelta
from flask import Flask, render_template, request, jsonify, redirect, url_for, flash, send_file, abort, session, make_response, Response
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from flask_wtf import CSRFProtect
from flask_wtf.csrf import CSRFError
from werkzeug.utils import secure_filename
from werkzeug.security import generate_password_hash, check_password_hash
from sqlalchemy.orm import sessionmaker, joinedload
from sqlalchemy import func, text
from functools import wraps
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import List, Dict, Tuple
import time
import subprocess
import json
import signal
from contextlib import contextmanager

# Windows-spezifische Fixes früh importieren (sichere Version)
if os.name == 'nt':
    try:
        from utils.windows_fixes import get_windows_thread_manager
        # apply_all_windows_fixes() wird automatisch beim Import ausgeführt
        print("✅ Windows-Fixes (sichere Version) geladen")
    except ImportError as e:
        # Fallback falls windows_fixes nicht verfügbar
        get_windows_thread_manager = None
        print(f"⚠️ Windows-Fixes nicht verfügbar: {str(e)}")
else:
    get_windows_thread_manager = None

# Lokale Imports
from models import init_database, create_initial_admin, User, Printer, Job, Stats, SystemLog, get_db_session, GuestRequest, UserPermission, Notification
from utils.logging_config import setup_logging, get_logger, measure_execution_time, log_startup_info, debug_request, debug_response
from utils.job_scheduler import JobScheduler, get_job_scheduler
from utils.queue_manager import start_queue_manager, stop_queue_manager, get_queue_manager
from config.settings import SECRET_KEY, UPLOAD_FOLDER, ALLOWED_EXTENSIONS, ENVIRONMENT, SESSION_LIFETIME, SCHEDULER_ENABLED, SCHEDULER_INTERVAL, TAPO_USERNAME, TAPO_PASSWORD
from utils.file_manager import file_manager, save_job_file, save_guest_file, save_avatar_file, delete_file as delete_file_safe

# Blueprints importieren
from blueprints.guest import guest_blueprint
from blueprints.calendar import calendar_blueprint
from blueprints.users import users_blueprint

# Scheduler importieren falls verfügbar
try:
    from utils.job_scheduler import scheduler
except ImportError:
    scheduler = None

# SSL-Kontext importieren falls verfügbar
try:
    from utils.ssl_config import get_ssl_context
except ImportError:
    def get_ssl_context():
        return None

# Template-Helfer importieren falls verfügbar
try:
    from utils.template_helpers import register_template_helpers
except ImportError:
    def register_template_helpers(app):
        pass

# Datenbank-Monitor und Backup-Manager importieren falls verfügbar
try:
    from utils.database_monitor import DatabaseMonitor
    database_monitor = DatabaseMonitor()
except ImportError:
    database_monitor = None

try:
    from utils.backup_manager import BackupManager
    backup_manager = BackupManager()
except ImportError:
    backup_manager = None

# Import neuer Systeme
from utils.rate_limiter import limit_requests, rate_limiter, cleanup_rate_limiter
from utils.security import init_security, require_secure_headers, security_check
from utils.permissions import init_permission_helpers, require_permission, Permission, check_permission
from utils.analytics import analytics_engine, track_event, get_dashboard_stats

# Drucker-Monitor importieren
from utils.printer_monitor import printer_monitor

# Flask-App initialisieren
app = Flask(__name__)
app.secret_key = SECRET_KEY
app.config["PERMANENT_SESSION_LIFETIME"] = SESSION_LIFETIME
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["WTF_CSRF_ENABLED"] = True

# CSRF-Schutz initialisieren
csrf = CSRFProtect(app)

# Security-System initialisieren
app = init_security(app)

# Permission Template Helpers registrieren
init_permission_helpers(app)

# Template-Helper registrieren
register_template_helpers(app)

# CSRF-Error-Handler - Korrigierte Version für Flask-WTF 1.2.1+
@app.errorhandler(CSRFError)
def csrf_error(error):
    """Behandelt CSRF-Fehler und gibt detaillierte Informationen zurück."""
    app_logger.error(f"CSRF-Fehler für {request.path}: {error}")
    
    if request.path.startswith('/api/'):
        # Für API-Anfragen: JSON-Response
        return jsonify({
            "error": "CSRF-Token fehlt oder ungültig",
            "reason": str(error),
            "help": "Fügen Sie ein gültiges CSRF-Token zu Ihrer Anfrage hinzu"
        }), 400
    else:
        # Für normale Anfragen: Weiterleitung zur Fehlerseite
        flash("Sicherheitsfehler: Anfrage wurde abgelehnt. Bitte versuchen Sie es erneut.", "error")
        return redirect(request.url)

# Blueprints registrieren
app.register_blueprint(guest_blueprint)
app.register_blueprint(calendar_blueprint)
app.register_blueprint(users_blueprint)

# Login-Manager initialisieren
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"
login_manager.login_message = "Bitte melden Sie sich an, um auf diese Seite zuzugreifen."
login_manager.login_message_category = "info"

@login_manager.user_loader
def load_user(user_id):
    """
    Robuster User-Loader mit Error-Handling für Schema-Probleme.
    """
    try:
        # user_id von Flask-Login ist immer ein String - zu Integer konvertieren
        try:
            user_id_int = int(user_id)
        except (ValueError, TypeError):
            app_logger.error(f"Ungültige User-ID: {user_id}")
            return None
            
        db_session = get_db_session()
        
        # Robuste Abfrage mit Error-Handling
        try:
            user = db_session.query(User).filter(User.id == user_id_int).first()
            db_session.close()
            return user
        except Exception as db_error:
            # Schema-Problem - versuche manuelle Abfrage
            app_logger.warning(f"Schema-Problem beim User-Load für ID {user_id_int}: {str(db_error)}")
            
            # Manuelle Abfrage nur mit Basis-Feldern
            try:
                result = db_session.execute(
                    text("SELECT id, email, password_hash, name, role, active FROM users WHERE id = :user_id"),
                    {"user_id": user_id_int}
                ).fetchone()
                
                if result:
                    # Manuell User-Objekt erstellen
                    user = User()
                    user.id = result[0]
                    user.email = result[1] if len(result) > 1 else f"user_{user_id_int}@system.local"
                    user.password_hash = result[2] if len(result) > 2 else ""
                    user.name = result[3] if len(result) > 3 else f"User {user_id_int}"
                    user.role = result[4] if len(result) > 4 else "user"
                    user.active = result[5] if len(result) > 5 else True
                    
                    # Standard-Werte für fehlende Felder
                    user.username = getattr(user, 'username', user.email.split('@')[0])
                    user.created_at = getattr(user, 'created_at', datetime.now())
                    user.last_login = getattr(user, 'last_login', None)
                    user.updated_at = getattr(user, 'updated_at', datetime.now())
                    
                    db_session.close()
                    return user
                    
            except Exception as manual_error:
                app_logger.error(f"Auch manuelle User-Abfrage fehlgeschlagen: {str(manual_error)}")
            
            db_session.close()
            return None
            
    except Exception as e:
        app_logger.error(f"Kritischer Fehler im User-Loader für ID {user_id}: {str(e)}")
        return None

# Jinja2 Context Processors
@app.context_processor
def inject_now():
    """Inject the current datetime into templates."""
    return {'now': datetime.now()}

# Custom Jinja2 filter für Datumsformatierung
@app.template_filter('format_datetime')
def format_datetime_filter(value, format='%d.%m.%Y %H:%M'):
    """Format a datetime object to a German-style date and time string"""
    if value is None:
        return ""
    if isinstance(value, str):
        try:
            value = datetime.fromisoformat(value)
        except ValueError:
            return value
    return value.strftime(format)

# Logging initialisieren
setup_logging()
log_startup_info()

# Logger für verschiedene Komponenten
app_logger = get_logger("app")
auth_logger = get_logger("auth")
jobs_logger = get_logger("jobs")
printers_logger = get_logger("printers")
user_logger = get_logger("user")
kiosk_logger = get_logger("kiosk")

# HTTP-Request/Response-Middleware für automatisches Debug-Logging
@app.before_request
def log_request_info():
    """Loggt detaillierte Informationen über eingehende HTTP-Anfragen."""
    # Nur für API-Endpunkte und wenn Debug-Level aktiviert ist
    if request.path.startswith('/api/') or app_logger.level <= logging.DEBUG:
        debug_request(app_logger, request)

@app.after_request
def log_response_info(response):
    """Loggt detaillierte Informationen über ausgehende HTTP-Antworten."""
    # Nur für API-Endpunkte und wenn Debug-Level aktiviert ist
    if request.path.startswith('/api/') or app_logger.level <= logging.DEBUG:
        # Berechne Response-Zeit aus dem g-Objekt wenn verfügbar
        duration_ms = None
        if hasattr(request, '_start_time'):
            duration_ms = (time.time() - request._start_time) * 1000
        
        debug_response(app_logger, response, duration_ms)
    
    return response

# Start-Zeit für Request-Timing setzen
@app.before_request
def start_timer():
    """Setzt einen Timer für die Request-Bearbeitung."""
    request._start_time = time.time()

# Sicheres Passwort-Hash für Kiosk-Deaktivierung
KIOSK_PASSWORD_HASH = generate_password_hash("744563017196A")

print("Alle Blueprints wurden in app.py integriert")

# Custom decorator für Job-Besitzer-Check
def job_owner_required(f):
    @wraps(f)
    def decorated_function(job_id, *args, **kwargs):
        db_session = get_db_session()
        job = db_session.query(Job).filter(Job.id == job_id).first()
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
            
        is_owner = job.user_id == int(current_user.id) or job.owner_id == int(current_user.id)
        is_admin = current_user.is_admin
        
        if not (is_owner or is_admin):
            db_session.close()
            return jsonify({"error": "Keine Berechtigung"}), 403
            
        db_session.close()
        return f(job_id, *args, **kwargs)
    return decorated_function

# Custom decorator für Admin-Check
def admin_required(f):
    @wraps(f)
    @login_required
    def decorated_function(*args, **kwargs):
        app_logger.info(f"Admin-Check für Funktion {f.__name__}: User authenticated: {current_user.is_authenticated}, User ID: {current_user.id if current_user.is_authenticated else 'None'}, Is Admin: {current_user.is_admin if current_user.is_authenticated else 'None'}")
        if not current_user.is_admin:
            app_logger.warning(f"Admin-Zugriff verweigert für User {current_user.id if current_user.is_authenticated else 'Anonymous'} auf Funktion {f.__name__}")
            return jsonify({"error": "Nur Administratoren haben Zugriff"}), 403
        return f(*args, **kwargs)
    return decorated_function

# ===== AUTHENTIFIZIERUNGS-ROUTEN (ehemals auth.py) =====

@app.route("/auth/login", methods=["GET", "POST"])
def login():
    if current_user.is_authenticated:
        return redirect(url_for("index"))
        
    error = None
    if request.method == "POST":
        # Unterscheiden zwischen JSON-Anfragen und normalen Formular-Anfragen
        is_json_request = request.is_json or request.headers.get('Content-Type') == 'application/json'
        
        # Daten je nach Anfrageart auslesen
        if is_json_request:
            data = request.get_json()
            username = data.get("username") or data.get("email")  # Fallback für email
            password = data.get("password")
            remember_me = data.get("remember_me", False)
        else:
            # Korrigierte Feldnamen - Template verwendet "email" nicht "username"
            username = request.form.get("email")  # Geändert von "username" zu "email"
            password = request.form.get("password")
            remember_me = request.form.get("remember_me") == "on"  # Geändert von "remember-me"
        
        if not username or not password:
            error = "Benutzername und Passwort müssen angegeben werden."
            if is_json_request:
                return jsonify({"error": error}), 400
        else:
            try:
                db_session = get_db_session()
                # Suche nach Benutzer mit übereinstimmendem Benutzernamen oder E-Mail
                user = db_session.query(User).filter(
                    (User.username == username) | (User.email == username)
                ).first()
                
                if user and user.check_password(password):
                    # Update last login timestamp
                    user.update_last_login()
                    db_session.commit()
                    
                    login_user(user, remember=remember_me)
                    auth_logger.info(f"Benutzer {username} hat sich angemeldet")
                    
                    next_page = request.args.get("next")
                    db_session.close()
                    
                    if is_json_request:
                        return jsonify({"success": True, "redirect_url": next_page or url_for("index")})
                    else:
                        if next_page:
                            return redirect(next_page)
                        return redirect(url_for("index"))
                else:
                    error = "Ungültiger Benutzername oder Passwort."
                    auth_logger.warning(f"Fehlgeschlagener Login-Versuch für Benutzer {username}")
                    db_session.close()
                    
                    if is_json_request:
                        return jsonify({"error": error}), 401
            except Exception as e:
                # Fehlerbehandlung für Datenbankprobleme
                error = "Anmeldefehler. Bitte versuchen Sie es später erneut."
                auth_logger.error(f"Fehler bei der Anmeldung: {str(e)}")
                if is_json_request:
                    return jsonify({"error": error}), 500
    
    return render_template("login.html", error=error)

@app.route("/auth/logout", methods=["GET", "POST"])
@login_required
def auth_logout():
    """Meldet den Benutzer ab."""
    app_logger.info(f"Benutzer {current_user.email} hat sich abgemeldet")
    logout_user()
    flash("Sie wurden erfolgreich abgemeldet.", "info")
    return redirect(url_for("login"))

@app.route("/auth/reset-password-request", methods=["GET", "POST"])
def reset_password_request():
    """Passwort-Reset anfordern (Placeholder)."""
    # TODO: Implement password reset functionality
    flash("Passwort-Reset-Funktionalität ist noch nicht implementiert.", "info")
    return redirect(url_for("login"))

@app.route("/auth/api/login", methods=["POST"])
def api_login():
    """API-Login-Endpunkt für Frontend"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({"error": "Keine Daten erhalten"}), 400
        
        username = data.get("username")
        password = data.get("password")
        remember_me = data.get("remember_me", False)
        
        if not username or not password:
            return jsonify({"error": "Benutzername und Passwort müssen angegeben werden"}), 400
        
        db_session = get_db_session()
        user = db_session.query(User).filter(
            (User.username == username) | (User.email == username)
        ).first()
        
        if user and user.check_password(password):
            # Update last login timestamp
            user.update_last_login()
            db_session.commit()
            
            login_user(user, remember=remember_me)
            auth_logger.info(f"API-Login erfolgreich für Benutzer {username}")
            
            user_data = {
                "id": user.id,
                "username": user.username,
                "name": user.name,
                "email": user.email,
                "is_admin": user.is_admin
            }
            
            db_session.close()
            return jsonify({
                "success": True,
                "user": user_data,
                "redirect_url": url_for("index")
            })
        else:
            auth_logger.warning(f"Fehlgeschlagener API-Login für Benutzer {username}")
            db_session.close()
            return jsonify({"error": "Ungültiger Benutzername oder Passwort"}), 401
            
    except Exception as e:
        auth_logger.error(f"Fehler beim API-Login: {str(e)}")
        return jsonify({"error": "Anmeldefehler. Bitte versuchen Sie es später erneut"}), 500

@app.route("/auth/api/callback", methods=["GET", "POST"])
def api_callback():
    """OAuth-Callback-Endpunkt für externe Authentifizierung"""
    try:
        # OAuth-Provider bestimmen
        provider = request.args.get('provider', 'github')
        
        if request.method == "GET":
            # Authorization Code aus URL-Parameter extrahieren
            code = request.args.get('code')
            state = request.args.get('state')
            error = request.args.get('error')
            
            if error:
                auth_logger.warning(f"OAuth-Fehler von {provider}: {error}")
                return jsonify({
                    "error": f"OAuth-Authentifizierung fehlgeschlagen: {error}",
                    "redirect_url": url_for("login")
                }), 400
            
            if not code:
                auth_logger.warning(f"Kein Authorization Code von {provider} erhalten")
                return jsonify({
                    "error": "Kein Authorization Code erhalten",
                    "redirect_url": url_for("login")
                }), 400
            
            # State-Parameter validieren (CSRF-Schutz)
            session_state = session.get('oauth_state')
            if not state or state != session_state:
                auth_logger.warning(f"Ungültiger State-Parameter von {provider}")
                return jsonify({
                    "error": "Ungültiger State-Parameter",
                    "redirect_url": url_for("login")
                }), 400
            
            # OAuth-Token austauschen
            if provider == 'github':
                user_data = handle_github_callback(code)
            else:
                auth_logger.error(f"Unbekannter OAuth-Provider: {provider}")
                return jsonify({
                    "error": "Unbekannter OAuth-Provider",
                    "redirect_url": url_for("login")
                }), 400
            
            if not user_data:
                return jsonify({
                    "error": "Fehler beim Abrufen der Benutzerdaten",
                    "redirect_url": url_for("login")
                }), 400
            
            # Benutzer in Datenbank suchen oder erstellen
            db_session = get_db_session()
            try:
                user = db_session.query(User).filter(
                    User.email == user_data['email']
                ).first()
                
                if not user:
                    # Neuen Benutzer erstellen
                    user = User(
                        username=user_data['username'],
                        email=user_data['email'],
                        name=user_data['name'],
                        is_admin=False,
                        oauth_provider=provider,
                        oauth_id=str(user_data['id'])
                    )
                    # Zufälliges Passwort setzen (wird nicht verwendet)
                    import secrets
                    user.set_password(secrets.token_urlsafe(32))
                    db_session.add(user)
                    db_session.commit()
                    auth_logger.info(f"Neuer OAuth-Benutzer erstellt: {user.username} via {provider}")
                else:
                    # Bestehenden Benutzer aktualisieren
                    user.oauth_provider = provider
                    user.oauth_id = str(user_data['id'])
                    user.name = user_data['name']
                    user.updated_at = datetime.now()
                    db_session.commit()
                    auth_logger.info(f"OAuth-Benutzer aktualisiert: {user.username} via {provider}")
                
                # Update last login timestamp
                user.update_last_login()
                db_session.commit()
                
                login_user(user, remember=True)
                
                # Session-State löschen
                session.pop('oauth_state', None)
                
                response_data = {
                    "success": True,
                    "user": {
                        "id": user.id,
                        "username": user.username,
                        "name": user.name,
                        "email": user.email,
                        "is_admin": user.is_admin
                    },
                    "redirect_url": url_for("index")
                }
                
                db_session.close()
                return jsonify(response_data)
                
            except Exception as e:
                db_session.rollback()
                db_session.close()
                auth_logger.error(f"Datenbankfehler bei OAuth-Callback: {str(e)}")
                return jsonify({
                    "error": "Datenbankfehler bei der Benutzeranmeldung",
                    "redirect_url": url_for("login")
                }), 500
        
        elif request.method == "POST":
            # POST-Anfragen für manuelle Token-Übermittlung
            data = request.get_json()
            if not data:
                return jsonify({"error": "Keine Daten erhalten"}), 400
            
            access_token = data.get('access_token')
            provider = data.get('provider', 'github')
            
            if not access_token:
                return jsonify({"error": "Kein Access Token erhalten"}), 400
            
            # Benutzerdaten mit Access Token abrufen
            if provider == 'github':
                user_data = get_github_user_data(access_token)
            else:
                return jsonify({"error": "Unbekannter OAuth-Provider"}), 400
            
            if not user_data:
                return jsonify({"error": "Fehler beim Abrufen der Benutzerdaten"}), 400
            
            # Benutzer verarbeiten (gleiche Logik wie bei GET)
            db_session = get_db_session()
            try:
                user = db_session.query(User).filter(
                    User.email == user_data['email']
                ).first()
                
                if not user:
                    user = User(
                        username=user_data['username'],
                        email=user_data['email'],
                        name=user_data['name'],
                        is_admin=False,
                        oauth_provider=provider,
                        oauth_id=str(user_data['id'])
                    )
                    import secrets
                    user.set_password(secrets.token_urlsafe(32))
                    db_session.add(user)
                    db_session.commit()
                    auth_logger.info(f"Neuer OAuth-Benutzer erstellt: {user.username} via {provider}")
                else:
                    user.oauth_provider = provider
                    user.oauth_id = str(user_data['id'])
                    user.name = user_data['name']
                    user.updated_at = datetime.now()
                    db_session.commit()
                    auth_logger.info(f"OAuth-Benutzer aktualisiert: {user.username} via {provider}")
                
                # Update last login timestamp
                user.update_last_login()
                db_session.commit()
                
                login_user(user, remember=True)
                
                response_data = {
                    "success": True,
                    "user": {
                        "id": user.id,
                        "username": user.username,
                        "name": user.name,
                        "email": user.email,
                        "is_admin": user.is_admin
                    },
                    "redirect_url": url_for("index")
                }
                
                db_session.close()
                return jsonify(response_data)
                
            except Exception as e:
                db_session.rollback()
                db_session.close()
                auth_logger.error(f"Datenbankfehler bei OAuth-Callback: {str(e)}")
                return jsonify({
                    "error": "Datenbankfehler bei der Benutzeranmeldung",
                    "redirect_url": url_for("login")
                }), 500
        
    except Exception as e:
        auth_logger.error(f"Fehler im OAuth-Callback: {str(e)}")
        return jsonify({
            "error": "OAuth-Callback-Fehler",
            "redirect_url": url_for("login")
        }), 500

def handle_github_callback(code):
    """GitHub OAuth-Callback verarbeiten"""
    try:
        import requests
        
        # GitHub OAuth-Konfiguration (sollte aus Umgebungsvariablen kommen)
        client_id = "7c5d8bef1a5519ec1fdc"
        client_secret = "5f1e586204358fbd53cf5fb7d418b3f06ccab8fd"
        
        if not client_id or not client_secret:
            auth_logger.error("GitHub OAuth-Konfiguration fehlt")
            return None
        
        # Access Token anfordern
        token_url = "https://github.com/login/oauth/access_token"
        token_data = {
            'client_id': client_id,
            'client_secret': client_secret,
            'code': code
        }
        
        token_response = requests.post(
            token_url,
            data=token_data,
            headers={'Accept': 'application/json'},
            timeout=10
        )
        
        if token_response.status_code != 200:
            auth_logger.error(f"GitHub Token-Anfrage fehlgeschlagen: {token_response.status_code}")
            return None
        
        token_json = token_response.json()
        access_token = token_json.get('access_token')
        
        if not access_token:
            auth_logger.error("Kein Access Token von GitHub erhalten")
            return None
        
        return get_github_user_data(access_token)
        
    except Exception as e:
        auth_logger.error(f"Fehler bei GitHub OAuth-Callback: {str(e)}")
        return None

def get_github_user_data(access_token):
    """GitHub-Benutzerdaten mit Access Token abrufen"""
    try:
        import requests
        
        # Benutzerdaten von GitHub API abrufen
        user_url = "https://api.github.com/user"
        headers = {
            'Authorization': f'token {access_token}',
            'Accept': 'application/vnd.github.v3+json'
        }
        
        user_response = requests.get(user_url, headers=headers, timeout=10)
        
        if user_response.status_code != 200:
            auth_logger.error(f"GitHub User-API-Anfrage fehlgeschlagen: {user_response.status_code}")
            return None
        
        user_data = user_response.json()
        
        # E-Mail-Adresse separat abrufen (falls nicht öffentlich)
        email = user_data.get('email')
        if not email:
            email_url = "https://api.github.com/user/emails"
            email_response = requests.get(email_url, headers=headers, timeout=10)
            
            if email_response.status_code == 200:
                emails = email_response.json()
                # Primäre E-Mail-Adresse finden
                for email_obj in emails:
                    if email_obj.get('primary', False):
                        email = email_obj.get('email')
                        break
                
                # Fallback: Erste E-Mail-Adresse verwenden
                if not email and emails:
                    email = emails[0].get('email')
        
        if not email:
            auth_logger.error("Keine E-Mail-Adresse von GitHub erhalten")
            return None
        
        return {
            'id': user_data.get('id'),
            'username': user_data.get('login'),
            'name': user_data.get('name') or user_data.get('login'),
            'email': email
        }
        
    except Exception as e:
        auth_logger.error(f"Fehler beim Abrufen der GitHub-Benutzerdaten: {str(e)}")
        return None

# ===== BENUTZER-ROUTEN (ehemals user.py) =====

@app.route("/user/profile", methods=["GET"])
@login_required
def user_profile():
    """Profil-Seite anzeigen"""
    user_logger.info(f"Benutzer {current_user.username} hat seine Profilseite aufgerufen")
    return render_template("profile.html", user=current_user)

@app.route("/user/settings", methods=["GET"])
@login_required
def user_settings():
    """Einstellungen-Seite anzeigen"""
    user_logger.info(f"Benutzer {current_user.username} hat seine Einstellungsseite aufgerufen")
    return render_template("settings.html", user=current_user)

@app.route("/user/update-profile", methods=["POST"])
@login_required
def user_update_profile():
    """Benutzerprofilinformationen aktualisieren"""
    try:
        # Überprüfen, ob es sich um eine JSON-Anfrage handelt
        is_json_request = request.is_json or request.headers.get('Content-Type') == 'application/json'
        
        if is_json_request:
            data = request.get_json()
            name = data.get("name")
            email = data.get("email")
            department = data.get("department")
            position = data.get("position")
            phone = data.get("phone")
        else:
            name = request.form.get("name")
            email = request.form.get("email")
            department = request.form.get("department")
            position = request.form.get("position")
            phone = request.form.get("phone")
        
        db_session = get_db_session()
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if user:
            # Aktualisiere die Benutzerinformationen
            if name:
                user.name = name
            if email:
                user.email = email
            if department:
                user.department = department
            if position:
                user.position = position
            if phone:
                user.phone = phone
            
            user.updated_at = datetime.now()
            db_session.commit()
            user_logger.info(f"Benutzer {current_user.username} hat sein Profil aktualisiert")
            
            if is_json_request:
                return jsonify({
                    "success": True,
                    "message": "Profil erfolgreich aktualisiert"
                })
            else:
                flash("Profil erfolgreich aktualisiert", "success")
                return redirect(url_for("user_profile"))
        else:
            error = "Benutzer nicht gefunden."
            if is_json_request:
                return jsonify({"error": error}), 404
            else:
                flash(error, "error")
                return redirect(url_for("user_profile"))
                
    except Exception as e:
        error = f"Fehler beim Aktualisieren des Profils: {str(e)}"
        user_logger.error(error)
        if request.is_json:
            return jsonify({"error": error}), 500
        else:
            flash(error, "error")
            return redirect(url_for("user_profile"))
    finally:
        db_session.close()

@app.route("/user/api/update-settings", methods=["POST"])
@login_required
def user_api_update_settings():
    """API-Endpunkt für Einstellungen-Updates (JSON)"""
    return user_update_profile()

@app.route("/user/update-settings", methods=["POST"])
@login_required
def user_update_settings():
    """Benutzereinstellungen aktualisieren"""
    db_session = get_db_session()
    try:
        # Überprüfen, ob es sich um eine JSON-Anfrage handelt
        is_json_request = request.is_json or request.headers.get('Content-Type') == 'application/json'
        
        # Einstellungen aus der Anfrage extrahieren
        if is_json_request:
            data = request.get_json()
            if not data:
                return jsonify({"error": "Keine Daten empfangen"}), 400
            
            theme = data.get("theme", "system")
            reduced_motion = bool(data.get("reduced_motion", False))
            contrast = data.get("contrast", "normal")
            notifications = data.get("notifications", {})
            privacy = data.get("privacy", {})
        else:
            theme = request.form.get("theme", "system")
            reduced_motion = request.form.get("reduced_motion") == "on"
            contrast = request.form.get("contrast", "normal")
            notifications = {
                "new_jobs": request.form.get("notify_new_jobs") == "on",
                "job_updates": request.form.get("notify_job_updates") == "on",
                "system": request.form.get("notify_system") == "on",
                "email": request.form.get("notify_email") == "on"
            }
            privacy = {
                "activity_logs": request.form.get("activity_logs") == "on",
                "two_factor": request.form.get("two_factor") == "on",
                "auto_logout": int(request.form.get("auto_logout", "60"))
            }
        
        # Validierung der Eingaben
        valid_themes = ["light", "dark", "system"]
        if theme not in valid_themes:
            theme = "system"
        
        valid_contrasts = ["normal", "high"]
        if contrast not in valid_contrasts:
            contrast = "normal"
        
        # Benutzer aus der Datenbank laden
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if not user:
            error = "Benutzer nicht gefunden."
            if is_json_request:
                return jsonify({"error": error}), 404
            else:
                flash(error, "error")
                return redirect(url_for("user_settings"))
        
        # Einstellungen-Dictionary erstellen
        settings = {
            "theme": theme,
            "reduced_motion": reduced_motion,
            "contrast": contrast,
            "notifications": {
                "new_jobs": bool(notifications.get("new_jobs", True)),
                "job_updates": bool(notifications.get("job_updates", True)),
                "system": bool(notifications.get("system", True)),
                "email": bool(notifications.get("email", False))
            },
            "privacy": {
                "activity_logs": bool(privacy.get("activity_logs", True)),
                "two_factor": bool(privacy.get("two_factor", False)),
                "auto_logout": max(5, min(480, int(privacy.get("auto_logout", 60))))  # 5-480 Minuten
            },
            "last_updated": datetime.now().isoformat()
        }
        
        # Prüfen, ob User-Tabelle eine settings-Spalte hat
        if hasattr(user, 'settings'):
            # Einstellungen in der Datenbank speichern
            import json
            user.settings = json.dumps(settings)
        else:
            # Fallback: In Session speichern (temporär)
            session['user_settings'] = settings
        
        user.updated_at = datetime.now()
        db_session.commit()
        
        user_logger.info(f"Benutzer {current_user.username} hat seine Einstellungen aktualisiert")
        
        if is_json_request:
            return jsonify({
                "success": True,
                "message": "Einstellungen erfolgreich aktualisiert",
                "settings": settings
            })
        else:
            flash("Einstellungen erfolgreich aktualisiert", "success")
            return redirect(url_for("user_settings"))
                
    except ValueError as e:
        error = f"Ungültige Eingabedaten: {str(e)}"
        user_logger.warning(f"Ungültige Einstellungsdaten von Benutzer {current_user.username}: {str(e)}")
        if is_json_request:
            return jsonify({"error": error}), 400
        else:
            flash(error, "error")
            return redirect(url_for("user_settings"))
    except Exception as e:
        db_session.rollback()
        error = f"Fehler beim Aktualisieren der Einstellungen: {str(e)}"
        user_logger.error(f"Fehler beim Aktualisieren der Einstellungen für Benutzer {current_user.username}: {str(e)}")
        if is_json_request:
            return jsonify({"error": "Interner Serverfehler"}), 500
        else:
            flash("Fehler beim Speichern der Einstellungen", "error")
            return redirect(url_for("user_settings"))
    finally:
        db_session.close()

@app.route("/api/user/settings", methods=["GET"])
@login_required
def get_user_settings():
    """Holt die aktuellen Benutzereinstellungen"""
    try:
        # Einstellungen aus Session oder Datenbank laden
        user_settings = session.get('user_settings', {})
        
        # Standard-Einstellungen falls keine vorhanden
        default_settings = {
            "theme": "system",
            "reduced_motion": False,
            "contrast": "normal",
            "notifications": {
                "new_jobs": True,
                "job_updates": True,
                "system": True,
                "email": False
            },
            "privacy": {
                "activity_logs": True,
                "two_factor": False,
                "auto_logout": 60
            }
        }
        
        # Merge mit Standard-Einstellungen
        settings = {**default_settings, **user_settings}
        
        return jsonify({
            "success": True,
            "settings": settings
        })
        
    except Exception as e:
        user_logger.error(f"Fehler beim Laden der Benutzereinstellungen: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden der Einstellungen"
        }), 500

@app.route("/user/change-password", methods=["POST"])
@login_required
def user_change_password():
    """Benutzerpasswort ändern"""
    try:
        # Überprüfen, ob es sich um eine JSON-Anfrage handelt
        is_json_request = request.is_json or request.headers.get('Content-Type') == 'application/json'
        
        if is_json_request:
            data = request.get_json()
            current_password = data.get("current_password")
            new_password = data.get("new_password")
            confirm_password = data.get("confirm_password")
        else:
            current_password = request.form.get("current_password")
            new_password = request.form.get("new_password")
            confirm_password = request.form.get("confirm_password")
        
        # Prüfen, ob alle Felder ausgefüllt sind
        if not current_password or not new_password or not confirm_password:
            error = "Alle Passwortfelder müssen ausgefüllt sein."
            if is_json_request:
                return jsonify({"error": error}), 400
            else:
                flash(error, "error")
                return redirect(url_for("user_profile"))
        
        # Prüfen, ob das neue Passwort und die Bestätigung übereinstimmen
        if new_password != confirm_password:
            error = "Das neue Passwort und die Bestätigung stimmen nicht überein."
            if is_json_request:
                return jsonify({"error": error}), 400
            else:
                flash(error, "error")
                return redirect(url_for("user_profile"))
        
        db_session = get_db_session()
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if user and user.check_password(current_password):
            # Passwort aktualisieren
            user.set_password(new_password)
            user.updated_at = datetime.now()
            db_session.commit()
            
            user_logger.info(f"Benutzer {current_user.username} hat sein Passwort geändert")
            
            if is_json_request:
                return jsonify({
                    "success": True,
                    "message": "Passwort erfolgreich geändert"
                })
            else:
                flash("Passwort erfolgreich geändert", "success")
                return redirect(url_for("user_profile"))
        else:
            error = "Das aktuelle Passwort ist nicht korrekt."
            if is_json_request:
                return jsonify({"error": error}), 401
            else:
                flash(error, "error")
                return redirect(url_for("user_profile"))
                
    except Exception as e:
        error = f"Fehler beim Ändern des Passworts: {str(e)}"
        user_logger.error(error)
        if request.is_json:
            return jsonify({"error": error}), 500
        else:
            flash(error, "error")
            return redirect(url_for("user_profile"))
    finally:
        db_session.close()

@app.route("/user/export", methods=["GET"])
@login_required
def user_export_data():
    """Exportiert alle Benutzerdaten als JSON für DSGVO-Konformität"""
    try:
        db_session = get_db_session()
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if not user:
            db_session.close()
            return jsonify({"error": "Benutzer nicht gefunden"}), 404
        
        # Benutzerdaten abrufen
        user_data = user.to_dict()
        
        # Jobs des Benutzers abrufen
        jobs = db_session.query(Job).filter(Job.user_id == user.id).all()
        user_data["jobs"] = [job.to_dict() for job in jobs]
        
        # Aktivitäten und Einstellungen hinzufügen
        user_data["settings"] = session.get('user_settings', {})
        
        # Persönliche Statistiken
        user_data["statistics"] = {
            "total_jobs": len(jobs),
            "completed_jobs": len([j for j in jobs if j.status == "finished"]),
            "failed_jobs": len([j for j in jobs if j.status == "failed"]),
            "account_created": user.created_at.isoformat() if user.created_at else None,
            "last_login": user.last_login.isoformat() if user.last_login else None
        }
        
        db_session.close()
        
        # Daten als JSON-Datei zum Download anbieten
        response = make_response(json.dumps(user_data, indent=4))
        response.headers["Content-Disposition"] = f"attachment; filename=user_data_{user.username}.json"
        response.headers["Content-Type"] = "application/json"
        
        user_logger.info(f"Benutzer {current_user.username} hat seine Daten exportiert")
        return response
        
    except Exception as e:
        error = f"Fehler beim Exportieren der Benutzerdaten: {str(e)}"
        user_logger.error(error)
        return jsonify({"error": error}), 500

@app.route("/user/profile", methods=["PUT"])
@login_required
def user_update_profile_api():
    """API-Endpunkt zum Aktualisieren des Benutzerprofils"""
    try:
        if not request.is_json:
            return jsonify({"error": "Anfrage muss im JSON-Format sein"}), 400
            
        data = request.get_json()
        db_session = get_db_session()
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if not user:
            db_session.close()
            return jsonify({"error": "Benutzer nicht gefunden"}), 404
        
        # Aktualisiere nur die bereitgestellten Felder
        if "name" in data:
            user.name = data["name"]
        if "email" in data:
            user.email = data["email"]
        if "department" in data:
            user.department = data["department"]
        if "position" in data:
            user.position = data["position"]
        if "phone" in data:
            user.phone = data["phone"]
        if "bio" in data:
            user.bio = data["bio"]
        
        user.updated_at = datetime.now()
        db_session.commit()
        
        # Aktualisierte Benutzerdaten zurückgeben
        user_data = user.to_dict()
        db_session.close()
        
        user_logger.info(f"Benutzer {current_user.username} hat sein Profil über die API aktualisiert")
        return jsonify({
            "success": True, 
            "message": "Profil erfolgreich aktualisiert",
            "user": user_data
        })
        
    except Exception as e:
        error = f"Fehler beim Aktualisieren des Profils: {str(e)}"
        user_logger.error(error)
        return jsonify({"error": error}), 500

# ===== KIOSK-KONTROLL-ROUTEN (ehemals kiosk_control.py) =====

@app.route('/api/kiosk/status', methods=['GET'])
def kiosk_get_status():
    """Kiosk-Status abrufen."""
    try:
        # Prüfen ob Kiosk-Modus aktiv ist
        kiosk_active = os.path.exists('/tmp/kiosk_active')
        
        return jsonify({
            "active": kiosk_active,
            "message": "Kiosk-Status erfolgreich abgerufen"
        })
    except Exception as e:
        kiosk_logger.error(f"Fehler beim Abrufen des Kiosk-Status: {str(e)}")
        return jsonify({"error": "Fehler beim Abrufen des Status"}), 500

@app.route('/api/kiosk/deactivate', methods=['POST'])
def kiosk_deactivate():
    """Kiosk-Modus mit Passwort deaktivieren."""
    try:
        data = request.get_json()
        if not data or 'password' not in data:
            return jsonify({"error": "Passwort erforderlich"}), 400
        
        password = data['password']
        
        # Passwort überprüfen
        if not check_password_hash(KIOSK_PASSWORD_HASH, password):
            kiosk_logger.warning(f"Fehlgeschlagener Kiosk-Deaktivierungsversuch von IP: {request.remote_addr}")
            return jsonify({"error": "Ungültiges Passwort"}), 401
        
        # Kiosk deaktivieren
        try:
            # Kiosk-Service stoppen
            subprocess.run(['sudo', 'systemctl', 'stop', 'myp-kiosk'], check=True)
            subprocess.run(['sudo', 'systemctl', 'disable', 'myp-kiosk'], check=True)
            
            # Kiosk-Marker entfernen
            if os.path.exists('/tmp/kiosk_active'):
                os.remove('/tmp/kiosk_active')
            
            # Normale Desktop-Umgebung wiederherstellen
            subprocess.run(['sudo', 'systemctl', 'set-default', 'graphical.target'], check=True)
            
            kiosk_logger.info(f"Kiosk-Modus erfolgreich deaktiviert von IP: {request.remote_addr}")
            
            return jsonify({
                "success": True,
                "message": "Kiosk-Modus erfolgreich deaktiviert. System wird neu gestartet."
            })
            
        except subprocess.CalledProcessError as e:
            kiosk_logger.error(f"Fehler beim Deaktivieren des Kiosk-Modus: {str(e)}")
            return jsonify({"error": "Fehler beim Deaktivieren des Kiosk-Modus"}), 500
            
    except Exception as e:
        kiosk_logger.error(f"Unerwarteter Fehler bei Kiosk-Deaktivierung: {str(e)}")
        return jsonify({"error": "Unerwarteter Fehler"}), 500
@app.route('/api/kiosk/activate', methods=['POST'])
@login_required
def kiosk_activate():
    """Kiosk-Modus aktivieren (nur für Admins)."""
    try:
        # Admin-Authentifizierung prüfen
        if not current_user.is_admin:
            kiosk_logger.warning(f"Nicht-Admin-Benutzer {current_user.username} versuchte Kiosk-Aktivierung")
            return jsonify({"error": "Nur Administratoren können den Kiosk-Modus aktivieren"}), 403
        
        # Kiosk aktivieren
        try:
            # Kiosk-Marker setzen
            with open('/tmp/kiosk_active', 'w') as f:
                f.write('1')
            
            # Kiosk-Service aktivieren
            subprocess.run(['sudo', 'systemctl', 'enable', 'myp-kiosk'], check=True)
            subprocess.run(['sudo', 'systemctl', 'start', 'myp-kiosk'], check=True)
            
            kiosk_logger.info(f"Kiosk-Modus erfolgreich aktiviert von Admin {current_user.username} (IP: {request.remote_addr})")
            
            return jsonify({
                "success": True,
                "message": "Kiosk-Modus erfolgreich aktiviert"
            })
            
        except subprocess.CalledProcessError as e:
            kiosk_logger.error(f"Fehler beim Aktivieren des Kiosk-Modus: {str(e)}")
            return jsonify({"error": "Fehler beim Aktivieren des Kiosk-Modus"}), 500
            
    except Exception as e:
        kiosk_logger.error(f"Unerwarteter Fehler bei Kiosk-Aktivierung: {str(e)}")
        return jsonify({"error": "Unerwarteter Fehler"}), 500

@app.route('/api/kiosk/restart', methods=['POST'])
def kiosk_restart_system():
    """System neu starten (nur nach Kiosk-Deaktivierung)."""
    try:
        data = request.get_json()
        if not data or 'password' not in data:
            return jsonify({"error": "Passwort erforderlich"}), 400
        
        password = data['password']
        
        # Passwort überprüfen
        if not check_password_hash(KIOSK_PASSWORD_HASH, password):
            kiosk_logger.warning(f"Fehlgeschlagener Neustart-Versuch von IP: {request.remote_addr}")
            return jsonify({"error": "Ungültiges Passwort"}), 401
        
        kiosk_logger.info(f"System-Neustart initiiert von IP: {request.remote_addr}")
        
        # System nach kurzer Verzögerung neu starten
        subprocess.Popen(['sudo', 'shutdown', '-r', '+1'])
        
        return jsonify({
            "success": True,
            "message": "System wird in 1 Minute neu gestartet"
        })
        
    except Exception as e:
        kiosk_logger.error(f"Fehler beim System-Neustart: {str(e)}")
        return jsonify({"error": "Fehler beim Neustart"}), 500

# ===== HILFSFUNKTIONEN =====

@measure_execution_time(logger=printers_logger, task_name="Drucker-Status-Prüfung")
def check_printer_status(ip_address: str, timeout: int = 7) -> Tuple[str, bool]:
    """
    Überprüft den Status eines Druckers über TP-Link Tapo P110-Steckdosenabfrage.
    
    Args:
        ip_address: IP-Adresse der Drucker-Steckdose
        timeout: Timeout in Sekunden (Standard: 7)
        
    Returns:
        Tuple[str, bool]: (Status, Aktiv) - Status ist "online" oder "offline", Aktiv ist True/False
    """
    if not ip_address or ip_address.strip() == "":
        printers_logger.debug(f"Keine IP-Adresse angegeben")
        return "offline", False
    
    try:
        # IP-Adresse validieren
        import ipaddress
        try:
            ipaddress.ip_address(ip_address.strip())
        except ValueError:
            printers_logger.debug(f"Ungültige IP-Adresse: {ip_address}")
            return "offline", False
        
        # Importiere PyP100 für Tapo-Unterstützung
        try:
            from PyP100 import PyP110
        except ImportError:
            printers_logger.error("⚠️ PyP100-Modul nicht verfügbar - kann Tapo-Steckdosen nicht abfragen")
            return "offline", False
        
        # Verwende IMMER die globalen hardkodierten Tapo-Anmeldedaten
        username = TAPO_USERNAME
        password = TAPO_PASSWORD
        
        printers_logger.debug(f"🔌 Teste Tapo-Steckdose {ip_address} mit hardkodierten Anmeldedaten")
        
        # TP-Link Tapo P110 Verbindung herstellen
        p110 = PyP110.P110(ip_address.strip(), username, password)
        p110.handshake()  # Authentifizierung
        p110.login()      # Login
        
        # Geräteinformationen abrufen
        device_info = p110.getDeviceInfo()
        device_on = device_info.get('device_on', False)
        
        if device_on:
            printers_logger.debug(f"✅ Drucker {ip_address}: ONLINE (Steckdose eingeschaltet)")
            return "online", True
        else:
            printers_logger.debug(f"🔄 Drucker {ip_address}: STANDBY (Steckdose ausgeschaltet)")
            return "standby", False
            
    except Exception as e:
        printers_logger.debug(f"❌ Fehler beim Tapo-Status-Check für {ip_address}: {str(e)}")
        return "offline", False

@measure_execution_time(logger=printers_logger, task_name="Mehrere-Drucker-Status-Prüfung")
def check_multiple_printers_status(printers: List[Dict], timeout: int = 7) -> Dict[int, Tuple[str, bool]]:
    """
    Überprüft den Status mehrerer Drucker parallel.
    
    Args:
        printers: Liste der zu prüfenden Drucker
        timeout: Timeout für jeden einzelnen Drucker
    
    Returns:
        Dict[int, Tuple[str, bool]]: Dictionary mit Drucker-ID als Key und (Status, Aktiv) als Value
    """
    results = {}
    
    # Wenn keine Drucker vorhanden sind, gebe leeres Dict zurück
    if not printers:
        printers_logger.info("ℹ️ Keine Drucker zum Status-Check gefunden")
        return results
    
    printers_logger.info(f"🔍 Prüfe Status von {len(printers)} Druckern parallel...")
    
    # Parallel-Ausführung mit ThreadPoolExecutor
    # Sicherstellen, dass max_workers mindestens 1 ist
    max_workers = min(max(len(printers), 1), 10)
    
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        # Futures für alle Drucker erstellen
        future_to_printer = {
            executor.submit(check_printer_status, printer.get('ip_address'), timeout): printer
            for printer in printers
        }
        
        # Ergebnisse sammeln
        for future in as_completed(future_to_printer, timeout=timeout + 2):
            printer = future_to_printer[future]
            try:
                status, active = future.result()
                results[printer['id']] = (status, active)
                printers_logger.info(f"Drucker {printer['name']} ({printer.get('ip_address')}): {status}")
            except Exception as e:
                printers_logger.error(f"Fehler bei Status-Check für Drucker {printer['name']}: {str(e)}")
                results[printer['id']] = ("offline", False)
    
    printers_logger.info(f"✅ Status-Check abgeschlossen für {len(results)} Drucker")
    
    return results

# ===== UI-ROUTEN =====

@app.route("/")
def index():
    if current_user.is_authenticated:
        return render_template("index.html")
    return redirect(url_for("login"))

@app.route("/dashboard")
@login_required
def dashboard():
    return render_template("dashboard.html")

@app.route("/profile")
@login_required
def profile_redirect():
    """Leitet zur neuen Profilseite im User-Blueprint weiter."""
    return redirect(url_for("user_profile"))

@app.route("/profil")
@login_required
def profil_redirect():
    """Leitet zur neuen Profilseite im User-Blueprint weiter (deutsche URL)."""
    return redirect(url_for("user_profile"))

@app.route("/settings")
@login_required
def settings_redirect():
    """Leitet zur neuen Einstellungsseite im User-Blueprint weiter."""
    return redirect(url_for("user_settings"))

@app.route("/einstellungen")
@login_required
def einstellungen_redirect():
    """Leitet zur neuen Einstellungsseite im User-Blueprint weiter (deutsche URL)."""
    return redirect(url_for("user_settings"))

@app.route("/admin")
@login_required
def admin():
    """Leitet zur neuen Admin-Dashboard-Route weiter."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    return redirect(url_for("admin_page"))

@app.route("/demo")
@login_required
def components_demo():
    """Demo-Seite für UI-Komponenten"""
    return render_template("components_demo.html")

@app.route("/printers")
@login_required
def printers_page():
    """Zeigt die Übersichtsseite für Drucker an."""
    return render_template("printers.html")

@app.route("/jobs")
@login_required
def jobs_page():
    """Zeigt die Übersichtsseite für Druckaufträge an."""
    return render_template("jobs.html")

@app.route("/jobs/new")
@login_required
def new_job_page():
    """Zeigt die Seite zum Erstellen neuer Druckaufträge an."""
    return render_template("jobs.html")

@app.route("/stats")
@login_required
def stats_page():
    """Zeigt die Statistik-Seite an."""
    return render_template("stats.html")

@app.route("/admin-dashboard")
@login_required
def admin_page():
    """Zeigt die Administrationsseite an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    # Aktives Tab aus der URL auslesen oder Default-Wert verwenden
    active_tab = request.args.get('tab', 'users')
    
    # Daten für das Admin-Panel direkt beim Laden vorbereiten
    stats = {}
    users = []
    printers = []
    scheduler_status = {"running": False, "message": "Nicht verfügbar"}
    system_info = {"cpu": 0, "memory": 0, "disk": 0}
    logs = []
    
    db_session = get_db_session()
    
    try:
        # Statistiken laden
        from sqlalchemy.orm import joinedload
        
        # Benutzeranzahl
        stats["total_users"] = db_session.query(User).count()
        
        # Druckeranzahl und Online-Status
        all_printers = db_session.query(Printer).all()
        stats["total_printers"] = len(all_printers)
        stats["online_printers"] = len([p for p in all_printers if p.status == "online"])
        
        # Aktive Jobs und Warteschlange
        stats["active_jobs"] = db_session.query(Job).filter(
            Job.status.in_(["printing", "running"])
        ).count()
        
        stats["queued_jobs"] = db_session.query(Job).filter(
            Job.status == "scheduled"
        ).count()
        
        # Erfolgsrate
        total_jobs = db_session.query(Job).filter(
            Job.status.in_(["completed", "failed", "cancelled"])
        ).count()
        
        successful_jobs = db_session.query(Job).filter(
            Job.status == "completed"
        ).count()
        
        if total_jobs > 0:
            stats["success_rate"] = int((successful_jobs / total_jobs) * 100)
        else:
            stats["success_rate"] = 0
        
        # Benutzer laden
        if active_tab == 'users':
            users = db_session.query(User).all()
            users = [user.to_dict() for user in users]
        
        # Drucker laden
        if active_tab == 'printers':
            printers = db_session.query(Printer).all()
            printers = [printer.to_dict() for printer in printers]
        
        # Scheduler-Status laden
        if active_tab == 'scheduler':
            try:
                from utils.scheduler import scheduler_is_running
                is_running = scheduler_is_running()
                scheduler_status = {
                    "running": is_running,
                    "message": "Der Scheduler läuft" if is_running else "Der Scheduler ist gestoppt"
                }
            except (ImportError, AttributeError):
                scheduler_status = {
                    "running": False,
                    "message": "Scheduler-Status nicht verfügbar"
                }
        
        # System-Informationen laden
        if active_tab == 'system':
            import os
            import psutil
            
            # CPU und Memory
            cpu_percent = psutil.cpu_percent(interval=1)
            memory = psutil.virtual_memory()
            disk = psutil.disk_usage('/')
            
            # Uptime
            boot_time = psutil.boot_time()
            uptime_seconds = time.time() - boot_time
            uptime_days = int(uptime_seconds // 86400)
            uptime_hours = int((uptime_seconds % 86400) // 3600)
            uptime_minutes = int((uptime_seconds % 3600) // 60)
            
            # Datenbank-Status
            db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'database', 'myp.db')
            db_size = 0
            if os.path.exists(db_path):
                db_size = os.path.getsize(db_path) / (1024 * 1024)  # MB
            
            # Scheduler-Status
            scheduler_running = False
            scheduler_jobs = 0
            try:
                from utils.job_scheduler import scheduler
                scheduler_running = scheduler.running
                if hasattr(scheduler, 'get_jobs'):
                    scheduler_jobs = len(scheduler.get_jobs())
            except:
                pass
            
            # Nächster Job
            next_job = db_session.query(Job).filter(
                Job.status == "scheduled"
            ).order_by(Job.created_at.asc()).first()
            
            next_job_time = "Keine geplanten Jobs"
            if next_job:
                next_job_time = next_job.created_at.strftime("%d.%m.%Y %H:%M")
            
            system_info = {
                "cpu_usage": round(cpu_percent, 1),
                "memory_usage": round(memory.percent, 1),
                "disk_usage": round((disk.used / disk.total) * 100, 1),
                "uptime": f"{uptime_days}d {uptime_hours}h {uptime_minutes}m",
                "db_size": f"{db_size:.1f} MB",
                "db_connections": "Aktiv",
                "scheduler_running": scheduler_running,
                "scheduler_jobs": scheduler_jobs,
                "next_job": next_job_time
            }
        
        # Logs laden
        if active_tab == 'logs':
            import os
            log_level = request.args.get('log_level', 'all')
            log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logs')
            
            # Logeinträge sammeln
            app_logs = []
            for category in ['app', 'auth', 'jobs', 'printers', 'scheduler', 'errors']:
                log_file = os.path.join(log_dir, category, f'{category}.log')
                if os.path.exists(log_file):
                    with open(log_file, 'r') as f:
                        for line in f.readlines()[-100:]:  # Nur die letzten 100 Zeilen pro Datei
                            if log_level != 'all':
                                if log_level.upper() not in line:
                                    continue
                            app_logs.append({
                                'timestamp': line.split(' - ')[0] if ' - ' in line else '',
                                'level': line.split(' - ')[1].split(' - ')[0] if ' - ' in line and len(line.split(' - ')) > 2 else 'INFO',
                                'category': category,
                                'message': ' - '.join(line.split(' - ')[2:]) if ' - ' in line and len(line.split(' - ')) > 2 else line
                            })
            
            # Nach Zeitstempel sortieren (neueste zuerst)
            logs = sorted(app_logs, key=lambda x: x['timestamp'] if x['timestamp'] else '', reverse=True)[:100]

    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Daten: {str(e)}")
    finally:
        db_session.close()
        
    return render_template(
        "admin.html",
        active_tab=active_tab,
        stats=stats,
        users=users,
        printers=printers,
        scheduler_status=scheduler_status,
        system_info=system_info,
        logs=logs
    )

# ===== ERROR MONITORING SYSTEM =====

@app.route("/api/admin/system-health", methods=['GET'])
@login_required
def api_admin_system_health():
    """API-Endpunkt für System-Gesundheitscheck."""
    if not current_user.is_admin:
        return jsonify({"error": "Berechtigung verweigert"}), 403
    
    db_session = get_db_session()
    critical_errors = []
    warnings = []
    
    try:
        # 1. Datenbank-Schema-Integrität prüfen
        try:
            # Test verschiedene kritische Tabellen und Spalten
            db_session.execute(text("SELECT COUNT(*) FROM guest_requests WHERE duration_minutes IS NOT NULL"))
            schema_integrity = "OK"
        except Exception as e:
            critical_errors.append({
                "type": "database_schema",
                "message": f"Datenbank-Schema-Fehler: {str(e)}",
                "severity": "critical",
                "suggested_fix": "Datenbank-Migration ausführen",
                "timestamp": datetime.now().isoformat()
            })
            schema_integrity = "FEHLER"
        
        # 2. Prüfe kritische Spalten in wichtigen Tabellen
        schema_checks = [
            ("guest_requests", "duration_minutes"),
            ("guest_requests", "file_name"),
            ("guest_requests", "processed_by"),
            ("users", "updated_at"),
            ("jobs", "duration_minutes")
        ]
        
        missing_columns = []
        for table, column in schema_checks:
            try:
                db_session.execute(text(f"SELECT {column} FROM {table} LIMIT 1"))
            except Exception:
                missing_columns.append(f"{table}.{column}")
        
        if missing_columns:
            critical_errors.append({
                "type": "missing_columns",
                "message": f"Fehlende Datenbank-Spalten: {', '.join(missing_columns)}",
                "severity": "critical",
                "suggested_fix": "python utils/database_schema_migration.py ausführen",
                "timestamp": datetime.now().isoformat(),
                "details": missing_columns
            })
        
        # 3. Prüfe auf wiederkehrende Datenbankfehler in den Logs
        import os
        log_file = os.path.join("logs", "app", f"myp_app_{datetime.now().strftime('%Y_%m_%d')}.log")
        recent_db_errors = 0
        
        if os.path.exists(log_file):
            try:
                with open(log_file, 'r', encoding='utf-8') as f:
                    last_lines = f.readlines()[-100:]  # Letzte 100 Zeilen
                    for line in last_lines:
                        if "OperationalError" in line or "no such column" in line:
                            recent_db_errors += 1
            except Exception:
                pass
        
        if recent_db_errors > 5:
            critical_errors.append({
                "type": "frequent_db_errors",
                "message": f"{recent_db_errors} Datenbankfehler in letzter Zeit erkannt",
                "severity": "high",
                "suggested_fix": "System-Logs überprüfen und Migration ausführen",
                "timestamp": datetime.now().isoformat()
            })
        
        # 4. Prüfe Drucker-Konnektivität
        offline_printers = db_session.query(Printer).filter(
            Printer.status == "offline",
            Printer.active == True
        ).count()
        
        if offline_printers > 0:
            warnings.append({
                "type": "printer_offline",
                "message": f"{offline_printers} aktive Drucker sind offline",
                "severity": "warning",
                "suggested_fix": "Drucker-Status überprüfen",
                "timestamp": datetime.now().isoformat()
            })
        
        # 5. System-Performance Metriken
        import psutil
        cpu_usage = psutil.cpu_percent(interval=1)
        memory_usage = psutil.virtual_memory().percent
        disk_usage = psutil.disk_usage('/').percent
        
        if cpu_usage > 90:
            warnings.append({
                "type": "high_cpu",
                "message": f"Hohe CPU-Auslastung: {cpu_usage:.1f}%",
                "severity": "warning",
                "suggested_fix": "System-Ressourcen überprüfen",
                "timestamp": datetime.now().isoformat()
            })
        
        if memory_usage > 85:
            warnings.append({
                "type": "high_memory",
                "message": f"Hohe Speicher-Auslastung: {memory_usage:.1f}%",
                "severity": "warning",
                "suggested_fix": "Speicher-Verbrauch optimieren",
                "timestamp": datetime.now().isoformat()
            })
        
        # 6. Letzte Migration info
        try:
            backup_dir = os.path.join("database", "backups")
            if os.path.exists(backup_dir):
                backup_files = [f for f in os.listdir(backup_dir) if f.endswith('.backup')]
                if backup_files:
                    latest_backup = max(backup_files, key=lambda x: os.path.getctime(os.path.join(backup_dir, x)))
                    last_migration = latest_backup.replace('.backup', '').replace('myp.db.backup_', '')
                else:
                    last_migration = "Keine Backups gefunden"
            else:
                last_migration = "Backup-Verzeichnis nicht gefunden"
        except Exception:
            last_migration = "Unbekannt"
        
        return jsonify({
            "success": True,
            "health_status": "critical" if critical_errors else ("warning" if warnings else "healthy"),
            "critical_errors": critical_errors,
            "warnings": warnings,
            "schema_integrity": schema_integrity,
            "last_migration": last_migration,
            "recent_errors_count": recent_db_errors,
            "system_metrics": {
                "cpu_usage": cpu_usage,
                "memory_usage": memory_usage,
                "disk_usage": disk_usage
            },
            "timestamp": datetime.now().isoformat()
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim System-Gesundheitscheck: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim System-Gesundheitscheck",
            "critical_errors": [{
                "type": "system_check_failed",
                "message": f"System-Check fehlgeschlagen: {str(e)}",
                "severity": "critical",
                "suggested_fix": "System-Logs überprüfen",
                "timestamp": datetime.now().isoformat()
            }]
        }), 500
    finally:
        db_session.close()

@app.route("/api/admin/fix-errors", methods=['POST'])
@login_required 
@csrf.exempt
def api_admin_fix_errors():
    """API-Endpunkt um automatische Fehler-Reparatur auszuführen."""
    if not current_user.is_admin:
        return jsonify({"error": "Berechtigung verweigert"}), 403
    
    try:
        # Automatische Migration ausführen
        import subprocess
        import sys
        
        # Migration in separatem Prozess ausführen
        result = subprocess.run(
            [sys.executable, "utils/database_schema_migration.py"],
            cwd=os.path.dirname(os.path.abspath(__file__)),
            capture_output=True,
            text=True,
            timeout=60
        )
        
        if result.returncode == 0:
            app_logger.info(f"Automatische Migration erfolgreich ausgeführt von Admin {current_user.email}")
            return jsonify({
                "success": True,
                "message": "Automatische Reparatur erfolgreich durchgeführt",
                "details": result.stdout
            })
        else:
            app_logger.error(f"Automatische Migration fehlgeschlagen: {result.stderr}")
            return jsonify({
                "success": False,
                "error": "Automatische Reparatur fehlgeschlagen",
                "details": result.stderr
            }), 500
            
    except subprocess.TimeoutExpired:
        return jsonify({
            "success": False,
            "error": "Migration-Timeout - Vorgang dauerte zu lange"
        }), 500
    except Exception as e:
        app_logger.error(f"Fehler bei automatischer Reparatur: {str(e)}")
        return jsonify({
            "success": False,
            "error": f"Fehler bei automatischer Reparatur: {str(e)}"
        }), 500

# Direkter Zugriff auf Logout-Route (für Fallback)
@app.route("/logout", methods=["GET", "POST"])
def logout_redirect():
    """Leitet zur Blueprint-Logout-Route weiter."""
    return redirect(url_for("auth_logout"))

# ===== JOB-ROUTEN =====

@app.route("/api/jobs", methods=["GET"])
@login_required
def get_jobs():
    db_session = get_db_session()
    
    try:
        # Import joinedload for eager loading
        from sqlalchemy.orm import joinedload
        
        # Admin sieht alle Jobs, User nur eigene
        if current_user.is_admin:
            # Eagerly load the user and printer relationships to avoid detached instance errors
            jobs = db_session.query(Job).options(joinedload(Job.user), joinedload(Job.printer)).all()
        else:
            jobs = db_session.query(Job).options(joinedload(Job.user), joinedload(Job.printer)).filter(Job.user_id == int(current_user.id)).all()
        
        # Convert jobs to dictionaries before closing the session
        job_dicts = [job.to_dict() for job in jobs]
        
        db_session.close()
        
        return jsonify({
            "jobs": job_dicts
        })
    except Exception as e:
        jobs_logger.error(f"Fehler beim Abrufen von Jobs: {str(e)}")
        db_session.close()
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/jobs/<int:job_id>", methods=["GET"])
@login_required
@job_owner_required
def get_job(job_id):
    db_session = get_db_session()
    
    try:
        from sqlalchemy.orm import joinedload
        # Eagerly load the user and printer relationships
        job = db_session.query(Job).options(joinedload(Job.user), joinedload(Job.printer)).filter(Job.id == job_id).first()
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
            
        # Convert to dict before closing session
        job_dict = job.to_dict()
        db_session.close()
        
        return jsonify(job_dict)
    except Exception as e:
        jobs_logger.error(f"Fehler beim Abrufen des Jobs {job_id}: {str(e)}")
        db_session.close()
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/jobs/check-waiting', methods=['POST'])
@login_required
def check_waiting_jobs():
    """Überprüft wartende Jobs und startet sie, wenn Drucker online gehen."""
    try:
        db_session = get_db_session()
        
        # Alle wartenden Jobs finden
        waiting_jobs = db_session.query(Job).filter(
            Job.status == "waiting_for_printer"
        ).all()
        
        if not waiting_jobs:
            db_session.close()
            return jsonify({
                "message": "Keine wartenden Jobs gefunden",
                "updated_jobs": []
            })
        
        updated_jobs = []
        
        for job in waiting_jobs:
            # Drucker-Status prüfen
            printer = db_session.query(Printer).get(job.printer_id)
            if printer and printer.plug_ip:
                status, active = check_printer_status(printer.plug_ip)
                
                if status == "online" and active:
                    # Drucker ist jetzt online - Job kann geplant werden
                    job.status = "scheduled"
                    updated_jobs.append({
                        "id": job.id,
                        "name": job.name,
                        "printer_name": printer.name,
                        "status": "scheduled"
                    })
                    
                    jobs_logger.info(f"Job {job.id} von 'waiting_for_printer' zu 'scheduled' geändert - Drucker {printer.name} ist online")
        
        if updated_jobs:
            db_session.commit()
            
        db_session.close()
        
        return jsonify({
            "message": f"{len(updated_jobs)} Jobs aktualisiert",
            "updated_jobs": updated_jobs
        })
        
    except Exception as e:
        jobs_logger.error(f"Fehler beim Überprüfen wartender Jobs: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/jobs/active', methods=['GET'])
@login_required
def get_active_jobs():
    """
    Gibt alle aktiven Jobs zurück.
    """
    try:
        db_session = get_db_session()
        from sqlalchemy.orm import joinedload
        
        active_jobs = db_session.query(Job).options(
            joinedload(Job.user), 
            joinedload(Job.printer)
        ).filter(
            Job.status.in_(["scheduled", "running"])
        ).all()
        
        result = []
        for job in active_jobs:
            job_dict = job.to_dict()
            # Aktuelle Restzeit berechnen
            if job.status == "running" and job.end_at:
                remaining_time = job.end_at - datetime.now()
                if remaining_time.total_seconds() > 0:
                    job_dict["remaining_minutes"] = int(remaining_time.total_seconds() / 60)
                else:
                    job_dict["remaining_minutes"] = 0
            
            result.append(job_dict)
        
        db_session.close()
        return jsonify({"jobs": result})
    except Exception as e:
        jobs_logger.error(f"Fehler beim Abrufen aktiver Jobs: {str(e)}")
        return jsonify({"error": "Interner Serverfehler", "details": str(e)}), 500

@app.route('/api/jobs', methods=['POST'])
@login_required
@measure_execution_time(logger=jobs_logger, task_name="API-Job-Erstellung")
def create_job():
    """
    Erstellt einen neuen Job mit dem Status "scheduled".
    
    Body: {
        "printer_id": int,
        "start_iso": str,  # ISO-Datum-String
        "duration_minutes": int
    }
    """
    try:
        data = request.json
        
        # Pflichtfelder prüfen
        required_fields = ["printer_id", "start_iso", "duration_minutes"]
        for field in required_fields:
            if field not in data:
                return jsonify({"error": f"Feld '{field}' fehlt"}), 400
        
        # Daten extrahieren und validieren
        printer_id = int(data["printer_id"])
        start_iso = data["start_iso"]
        duration_minutes = int(data["duration_minutes"])
        
        # Optional: Jobtitel und Dateipfad
        name = data.get("name", f"Druckjob vom {datetime.now().strftime('%d.%m.%Y')}")
        file_path = data.get("file_path")
        
        # Start-Zeit parsen
        try:
            start_at = datetime.fromisoformat(start_iso)
        except ValueError:
            return jsonify({"error": "Ungültiges Startdatum"}), 400
        
        # Dauer validieren
        if duration_minutes <= 0:
            return jsonify({"error": "Dauer muss größer als 0 sein"}), 400
        
        # End-Zeit berechnen
        end_at = start_at + timedelta(minutes=duration_minutes)
        
        db_session = get_db_session()
        
        # Prüfen, ob der Drucker existiert
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Prüfen, ob der Drucker online ist
        printer_status, printer_active = check_printer_status(printer.plug_ip if printer.plug_ip else "")
        
        # Status basierend auf Drucker-Verfügbarkeit setzen
        if printer_status == "online" and printer_active:
            job_status = "scheduled"
        else:
            job_status = "waiting_for_printer"
        
        # Neuen Job erstellen
        new_job = Job(
            name=name,
            printer_id=printer_id,
            user_id=current_user.id,
            owner_id=current_user.id,
            start_at=start_at,
            end_at=end_at,
            status=job_status,
            file_path=file_path,
            duration_minutes=duration_minutes
        )
        
        db_session.add(new_job)
        db_session.commit()
        
        # Job-Objekt für die Antwort serialisieren
        job_dict = new_job.to_dict()
        db_session.close()
        
        jobs_logger.info(f"Neuer Job {new_job.id} erstellt für Drucker {printer_id}, Start: {start_at}, Dauer: {duration_minutes} Minuten")
        return jsonify({"job": job_dict}), 201
    
    except Exception as e:
        jobs_logger.error(f"Fehler beim Erstellen eines Jobs: {str(e)}")
        return jsonify({"error": "Interner Serverfehler", "details": str(e)}), 500

@app.route('/api/jobs/<int:job_id>/extend', methods=['POST'])
@login_required
@job_owner_required
def extend_job(job_id):
    """
    Verlängert die Endzeit eines Jobs.
    
    Body: {
        "extra_minutes": int
    }
    """
    try:
        data = request.json
        
        # Prüfen, ob die erforderlichen Daten vorhanden sind
        if "extra_minutes" not in data:
            return jsonify({"error": "Feld 'extra_minutes' fehlt"}), 400
        
        extra_minutes = int(data["extra_minutes"])
        
        # Validieren
        if extra_minutes <= 0:
            return jsonify({"error": "Zusätzliche Minuten müssen größer als 0 sein"}), 400
        
        db_session = get_db_session()
        job = db_session.query(Job).get(job_id)
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
        
        # Prüfen, ob der Job verlängert werden kann
        if job.status not in ["scheduled", "running"]:
            db_session.close()
            return jsonify({"error": f"Job kann im Status '{job.status}' nicht verlängert werden"}), 400
        
        # Endzeit aktualisieren
        job.end_at = job.end_at + timedelta(minutes=extra_minutes)
        job.duration_minutes += extra_minutes
        
        db_session.commit()
        
        # Job-Objekt für die Antwort serialisieren
        job_dict = job.to_dict()
        db_session.close()
        
        jobs_logger.info(f"Job {job_id} um {extra_minutes} Minuten verlängert, neue Endzeit: {job.end_at}")
        return jsonify({"job": job_dict})
    
    except Exception as e:
        jobs_logger.error(f"Fehler beim Verlängern von Job {job_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler", "details": str(e)}), 500

@app.route('/api/jobs/<int:job_id>/finish', methods=['POST'])
@login_required
def finish_job(job_id):
    """
    Beendet einen Job manuell und schaltet die Steckdose aus.
    Nur für Administratoren erlaubt.
    """
    try:
        # Prüfen, ob der Benutzer Administrator ist
        if not current_user.is_admin:
            return jsonify({"error": "Nur Administratoren können Jobs manuell beenden"}), 403
        
        db_session = get_db_session()
        job = db_session.query(Job).options(joinedload(Job.printer)).get(job_id)
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
        
        # Prüfen, ob der Job beendet werden kann
        if job.status not in ["scheduled", "running"]:
            db_session.close()
            return jsonify({"error": f"Job kann im Status '{job.status}' nicht beendet werden"}), 400
        
        # Steckdose ausschalten
        from utils.job_scheduler import toggle_plug
        if not toggle_plug(job.printer_id, False):
            # Trotzdem weitermachen, aber Warnung loggen
            jobs_logger.warning(f"Steckdose für Job {job_id} konnte nicht ausgeschaltet werden")
        
        # Job als beendet markieren
        job.status = "finished"
        job.actual_end_time = datetime.now()
        
        db_session.commit()
        
        # Job-Objekt für die Antwort serialisieren
        job_dict = job.to_dict()
        db_session.close()
        
        jobs_logger.info(f"Job {job_id} manuell beendet durch Admin {current_user.id}")
        return jsonify({"job": job_dict})
    
    except Exception as e:
        jobs_logger.error(f"Fehler beim manuellen Beenden von Job {job_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler", "details": str(e)}), 500

# ===== DRUCKER-ROUTEN =====

@app.route("/api/printers", methods=["GET"])
@login_required
def get_printers():
    """Gibt alle Drucker zurück - OHNE Status-Check für schnelleres Laden."""
    db_session = get_db_session()
    
    try:
        # Windows-kompatible Timeout-Implementierung
        import threading
        import time
        
        printers = None
        timeout_occurred = False
        
        def fetch_printers():
            nonlocal printers, timeout_occurred
            try:
                printers = db_session.query(Printer).all()
            except Exception as e:
                printers_logger.error(f"Datenbankfehler beim Laden der Drucker: {str(e)}")
                timeout_occurred = True
        
        # Starte Datenbankabfrage in separatem Thread
        thread = threading.Thread(target=fetch_printers)
        thread.daemon = True
        thread.start()
        thread.join(timeout=5)  # 5 Sekunden Timeout
        
        if thread.is_alive() or timeout_occurred or printers is None:
            printers_logger.warning("Database timeout when fetching printers for basic loading")
            return jsonify({
                'error': 'Database timeout beim Laden der Drucker',
                'timeout': True,
                'printers': []
            }), 408
        
        # Drucker-Daten OHNE Status-Check zusammenstellen für schnelles Laden
        printer_data = []
        current_time = datetime.now()
        
        for printer in printers:
            printer_data.append({
                "id": printer.id,
                "name": printer.name,
                "model": printer.model or 'Unbekanntes Modell',
                "location": printer.location or 'Unbekannter Standort',
                "mac_address": printer.mac_address,
                "plug_ip": printer.plug_ip,
                "status": printer.status or "offline",  # Letzter bekannter Status
                "active": printer.active if hasattr(printer, 'active') else True,
                "ip_address": printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None),
                "created_at": printer.created_at.isoformat() if printer.created_at else current_time.isoformat(),
                "last_checked": printer.last_checked.isoformat() if hasattr(printer, 'last_checked') and printer.last_checked else None
            })
        
        db_session.close()
        
        printers_logger.info(f"Schnelles Laden abgeschlossen: {len(printer_data)} Drucker geladen (ohne Status-Check)")
        
        return jsonify({
            "printers": printer_data,
            "count": len(printer_data),
            "message": "Drucker erfolgreich geladen"
        })
        
    except Exception as e:
        db_session.rollback()
        db_session.close()
        printers_logger.error(f"Fehler beim Abrufen der Drucker: {str(e)}")
        return jsonify({
            "error": f"Fehler beim Laden der Drucker: {str(e)}",
            "printers": []
        }), 500

@app.route("/api/printers/status", methods=["GET"])
@login_required
@measure_execution_time(logger=printers_logger, task_name="API-Drucker-Status-Abfrage")
def get_printers_with_status():
    """Gibt alle Drucker MIT aktuellem Status-Check zurück - für Aktualisierung."""
    db_session = get_db_session()
    
    try:
        # Windows-kompatible Timeout-Implementierung
        import threading
        import time
        
        printers = None
        timeout_occurred = False
        
        def fetch_printers():
            nonlocal printers, timeout_occurred
            try:
                printers = db_session.query(Printer).all()
            except Exception as e:
                printers_logger.error(f"Datenbankfehler beim Status-Check: {str(e)}")
                timeout_occurred = True
        
        # Starte Datenbankabfrage in separatem Thread
        thread = threading.Thread(target=fetch_printers)
        thread.daemon = True
        thread.start()
        thread.join(timeout=8)  # 8 Sekunden Timeout für Status-Check
        
        if thread.is_alive() or timeout_occurred or printers is None:
            printers_logger.warning("Database timeout when fetching printers for status check")
            return jsonify({
                'error': 'Database timeout beim Status-Check der Drucker',
                'timeout': True
            }), 408
        
        # Drucker-Daten für Status-Check vorbereiten
        printer_data = []
        for printer in printers:
            # Verwende plug_ip als primäre IP-Adresse, fallback auf ip_address
            ip_to_check = printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None)
            printer_data.append({
                'id': printer.id,
                'name': printer.name,
                'ip_address': ip_to_check,
                'location': printer.location,
                'model': printer.model
            })
        
        # Status aller Drucker parallel überprüfen mit 7-Sekunden-Timeout
        printers_logger.info(f"Starte Status-Check für {len(printer_data)} Drucker mit 7-Sekunden-Timeout")
        
        # Fallback: Wenn keine IP-Adressen vorhanden sind, alle als offline markieren
        if not any(p['ip_address'] for p in printer_data):
            printers_logger.warning("Keine IP-Adressen für Drucker gefunden - alle als offline markiert")
            status_results = {p['id']: ("offline", False) for p in printer_data}
        else:
            try:
                status_results = check_multiple_printers_status(printer_data, timeout=7)
            except Exception as e:
                printers_logger.error(f"Fehler beim Status-Check: {str(e)}")
                # Fallback: alle als offline markieren
                status_results = {p['id']: ("offline", False) for p in printer_data}
        
        # Ergebnisse zusammenstellen und Datenbank aktualisieren
        status_data = []
        current_time = datetime.now()
        
        for printer in printers:
            if printer.id in status_results:
                status, active = status_results[printer.id]
                # Mapping für Frontend-Kompatibilität
                if status == "online":
                    frontend_status = "available"
                else:
                    frontend_status = "offline"
            else:
                # Fallback falls kein Ergebnis vorliegt
                frontend_status = "offline"
                active = False
            
            # Status in der Datenbank aktualisieren
            printer.status = frontend_status
            printer.active = active
            
            # Setze last_checked falls das Feld existiert
            if hasattr(printer, 'last_checked'):
                printer.last_checked = current_time
            
            status_data.append({
                "id": printer.id,
                "name": printer.name,
                "model": printer.model or 'Unbekanntes Modell',
                "location": printer.location or 'Unbekannter Standort',
                "mac_address": printer.mac_address,
                "plug_ip": printer.plug_ip,
                "status": frontend_status,
                "active": active,
                "ip_address": printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None),
                "created_at": printer.created_at.isoformat() if printer.created_at else current_time.isoformat(),
                "last_checked": current_time.isoformat()
            })
        
        # Speichere die aktualisierten Status
        try:
            db_session.commit()
            printers_logger.info("Drucker-Status erfolgreich in Datenbank aktualisiert")
        except Exception as e:
            printers_logger.warning(f"Fehler beim Speichern der Status-Updates: {str(e)}")
            # Nicht kritisch, Status-Check kann trotzdem zurückgegeben werden
        
        db_session.close()
        
        online_count = len([s for s in status_data if s['status'] == 'available'])
        printers_logger.info(f"Status-Check abgeschlossen: {online_count} von {len(status_data)} Drucker online")
        
        return jsonify(status_data)
        
    except Exception as e:
        db_session.rollback()
        db_session.close()
        printers_logger.error(f"Fehler beim Status-Check der Drucker: {str(e)}")
        return jsonify({
            "error": f"Fehler beim Status-Check: {str(e)}",
            "printers": []
        }), 500

@app.route("/api/jobs/current", methods=["GET"])
@login_required
def get_current_job():
    """Gibt den aktuellen Job des Benutzers zurück."""
    db_session = get_db_session()
    try:
        current_job = db_session.query(Job).filter(
            Job.user_id == int(current_user.id),
            Job.status.in_(["scheduled", "running"])
        ).order_by(Job.start_at).first()
        
        if current_job:
            job_data = current_job.to_dict()
        else:
            job_data = None
            
        db_session.close()
        return jsonify(job_data)
    except Exception as e:
        db_session.close()
        return jsonify({"error": str(e)}), 500

# ===== WEITERE API-ROUTEN =====

@app.route("/api/printers/<int:printer_id>", methods=["GET"])
@login_required
def get_printer(printer_id):
    """Gibt einen spezifischen Drucker zurück."""
    db_session = get_db_session()
    
    try:
        printer = db_session.query(Printer).get(printer_id)
        
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Status-Check für diesen Drucker
        ip_to_check = printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None)
        if ip_to_check:
            status, active = check_printer_status(ip_to_check)
            printer.status = "available" if status == "online" else "offline"
            printer.active = active
            db_session.commit()
        
        printer_data = {
            "id": printer.id,
            "name": printer.name,
            "model": printer.model or 'Unbekanntes Modell',
            "location": printer.location or 'Unbekannter Standort',
            "mac_address": printer.mac_address,
            "plug_ip": printer.plug_ip,
            "status": printer.status or "offline",
            "active": printer.active if hasattr(printer, 'active') else True,
            "ip_address": ip_to_check,
            "created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        return jsonify(printer_data)
        
    except Exception as e:
        db_session.close()
        printers_logger.error(f"Fehler beim Abrufen des Druckers {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/printers", methods=["POST"])
@login_required
def create_printer():
    """Erstellt einen neuen Drucker (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Drucker erstellen"}), 403
    
    try:
        data = request.json
        
        # Pflichtfelder prüfen
        required_fields = ["name", "plug_ip"]
        for field in required_fields:
            if field not in data:
                return jsonify({"error": f"Feld '{field}' fehlt"}), 400
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Drucker mit diesem Namen existiert
        existing_printer = db_session.query(Printer).filter(Printer.name == data["name"]).first()
        if existing_printer:
            db_session.close()
            return jsonify({"error": "Ein Drucker mit diesem Namen existiert bereits"}), 400
        
        # Neuen Drucker erstellen
        new_printer = Printer(
            name=data["name"],
            model=data.get("model", ""),
            location=data.get("location", ""),
            mac_address=data.get("mac_address", ""),
            plug_ip=data["plug_ip"],
            status="offline",
            active=True,  # Neue Drucker sind standardmäßig aktiv
            created_at=datetime.now()
        )
        
        db_session.add(new_printer)
        db_session.commit()
        
        # Sofortiger Status-Check für den neuen Drucker
        ip_to_check = new_printer.plug_ip
        if ip_to_check:
            status, active = check_printer_status(ip_to_check)
            new_printer.status = "available" if status == "online" else "offline"
            new_printer.active = active
            db_session.commit()
        
        printer_data = {
            "id": new_printer.id,
            "name": new_printer.name,
            "model": new_printer.model,
            "location": new_printer.location,
            "mac_address": new_printer.mac_address,
            "plug_ip": new_printer.plug_ip,
            "status": new_printer.status,
            "active": new_printer.active,
            "created_at": new_printer.created_at.isoformat()
        }
        
        db_session.close()
        
        printers_logger.info(f"Neuer Drucker '{new_printer.name}' erstellt von Admin {current_user.id}")
        return jsonify({"printer": printer_data, "message": "Drucker erfolgreich erstellt"}), 201
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Erstellen eines Druckers: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/printers/add", methods=["POST"])
@login_required
def add_printer():
    """Alternativer Endpunkt zum Hinzufügen von Druckern (für Frontend-Kompatibilität)."""
    return create_printer()

@app.route("/api/printers/<int:printer_id>", methods=["PUT"])
@login_required
def update_printer(printer_id):
    """Aktualisiert einen Drucker (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Drucker bearbeiten"}), 403
    
    try:
        data = request.json
        db_session = get_db_session()
        
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Aktualisierbare Felder
        updatable_fields = ["name", "model", "location", "mac_address", "plug_ip"]
        for field in updatable_fields:
            if field in data:
                setattr(printer, field, data[field])
        
        db_session.commit()
        
        printer_data = {
            "id": printer.id,
            "name": printer.name,
            "model": printer.model,
            "location": printer.location,
            "mac_address": printer.mac_address,
            "plug_ip": printer.plug_ip,
            "status": printer.status,
            "created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        
        printers_logger.info(f"Drucker {printer_id} aktualisiert von Admin {current_user.id}")
        return jsonify({"printer": printer_data})
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Aktualisieren des Druckers {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/printers/<int:printer_id>", methods=["DELETE"])
@login_required
def delete_printer(printer_id):
    """Löscht einen Drucker (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Drucker löschen"}), 403
    
    try:
        db_session = get_db_session()
        
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Prüfen, ob noch aktive Jobs für diesen Drucker existieren
        active_jobs = db_session.query(Job).filter(
            Job.printer_id == printer_id,
            Job.status.in_(["scheduled", "running"])
        ).count()
        
        if active_jobs > 0:
            db_session.close()
            return jsonify({"error": f"Drucker kann nicht gelöscht werden: {active_jobs} aktive Jobs vorhanden"}), 400
        
        printer_name = printer.name
        db_session.delete(printer)
        db_session.commit()
        db_session.close()
        
        printers_logger.info(f"Drucker '{printer_name}' (ID: {printer_id}) gelöscht von Admin {current_user.id}")
        return jsonify({"message": "Drucker erfolgreich gelöscht"})
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Löschen des Druckers {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/jobs/<int:job_id>", methods=["DELETE"])
@login_required
@job_owner_required
def delete_job(job_id):
    """Löscht einen Job."""
    try:
        db_session = get_db_session()
        job = db_session.query(Job).get(job_id)
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
        
        # Prüfen, ob der Job gelöscht werden kann
        if job.status == "running":
            db_session.close()
            return jsonify({"error": "Laufende Jobs können nicht gelöscht werden"}), 400
        
        job_name = job.name
        db_session.delete(job)
        db_session.commit()
        db_session.close()
        
        jobs_logger.info(f"Job '{job_name}' (ID: {job_id}) gelöscht von Benutzer {current_user.id}")
        return jsonify({"message": "Job erfolgreich gelöscht"})
        
    except Exception as e:
        jobs_logger.error(f"Fehler beim Löschen des Jobs {job_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/jobs/<int:job_id>/cancel", methods=["POST"])
@login_required
@job_owner_required
def cancel_job(job_id):
    """Bricht einen Job ab."""
    try:
        db_session = get_db_session()
        job = db_session.query(Job).get(job_id)
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
        
        # Prüfen, ob der Job abgebrochen werden kann
        if job.status not in ["scheduled", "running"]:
            db_session.close()
            return jsonify({"error": f"Job kann im Status '{job.status}' nicht abgebrochen werden"}), 400
        
        # Job als abgebrochen markieren
        job.status = "cancelled"
        job.actual_end_time = datetime.now()
        
        # Wenn der Job läuft, Steckdose ausschalten
        if job.status == "running":
            from utils.job_scheduler import toggle_plug
            toggle_plug(job.printer_id, False)
        
        db_session.commit()
        
        job_dict = job.to_dict()
        db_session.close()
        
        jobs_logger.info(f"Job {job_id} abgebrochen von Benutzer {current_user.id}")
        return jsonify({"job": job_dict})
        
    except Exception as e:
        jobs_logger.error(f"Fehler beim Abbrechen des Jobs {job_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats", methods=["GET"])
@login_required
def get_stats():
    """Gibt Statistiken zurück."""
    try:
        db_session = get_db_session()
        
        # Grundlegende Statistiken
        total_users = db_session.query(User).count()
        total_printers = db_session.query(Printer).count()
        total_jobs = db_session.query(Job).count()
        
        # Jobs nach Status
        completed_jobs = db_session.query(Job).filter(Job.status == "completed").count()
        failed_jobs = db_session.query(Job).filter(Job.status == "failed").count()
        cancelled_jobs = db_session.query(Job).filter(Job.status == "cancelled").count()
        active_jobs = db_session.query(Job).filter(Job.status.in_(["scheduled", "running"])).count()
        
        # Online-Drucker
        online_printers = db_session.query(Printer).filter(Printer.status == "available").count()
        
        # Erfolgsrate
        finished_jobs = completed_jobs + failed_jobs + cancelled_jobs
        success_rate = (completed_jobs / finished_jobs * 100) if finished_jobs > 0 else 0
        
        # Benutzer-spezifische Statistiken (falls nicht Admin)
        user_stats = {}
        if not current_user.is_admin:
            user_jobs = db_session.query(Job).filter(Job.user_id == int(current_user.id)).count()
            user_completed = db_session.query(Job).filter(
                Job.user_id == int(current_user.id),
                Job.status == "completed"
            ).count()
            user_stats = {
                "total_jobs": user_jobs,
                "completed_jobs": user_completed,
                "success_rate": (user_completed / user_jobs * 100) if user_jobs > 0 else 0
            }
        
        db_session.close()
        
        stats = {
            "total_users": total_users,
            "total_printers": total_printers,
            "online_printers": online_printers,
            "total_jobs": total_jobs,
            "completed_jobs": completed_jobs,
            "failed_jobs": failed_jobs,
            "cancelled_jobs": cancelled_jobs,
            "active_jobs": active_jobs,
            "success_rate": round(success_rate, 1),
            "user_stats": user_stats
        }
        
        return jsonify(stats)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Statistiken: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/charts/job-status", methods=["GET"])
@login_required
def get_job_status_chart_data():
    """Gibt Diagrammdaten für Job-Status-Verteilung zurück."""
    try:
        db_session = get_db_session()
        
        # Job-Status zählen
        job_status_counts = {
            'completed': db_session.query(Job).filter(Job.status == 'completed').count(),
            'failed': db_session.query(Job).filter(Job.status == 'failed').count(),
            'cancelled': db_session.query(Job).filter(Job.status == 'cancelled').count(),
            'running': db_session.query(Job).filter(Job.status == 'running').count(),
            'scheduled': db_session.query(Job).filter(Job.status == 'scheduled').count()
        }
        
        db_session.close()
        
        chart_data = {
            'labels': ['Abgeschlossen', 'Fehlgeschlagen', 'Abgebrochen', 'Läuft', 'Geplant'],
            'datasets': [{
                'label': 'Anzahl Jobs',
                'data': [
                    job_status_counts['completed'],
                    job_status_counts['failed'], 
                    job_status_counts['cancelled'],
                    job_status_counts['running'],
                    job_status_counts['scheduled']
                ],
                'backgroundColor': [
                    '#10b981',  # Grün für abgeschlossen
                    '#ef4444',  # Rot für fehlgeschlagen
                    '#6b7280',  # Grau für abgebrochen
                    '#3b82f6',  # Blau für läuft
                    '#f59e0b'   # Orange für geplant
                ]
            }]
        }
        
        return jsonify(chart_data)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Job-Status-Diagrammdaten: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/charts/printer-usage", methods=["GET"])
@login_required
def get_printer_usage_chart_data():
    """Gibt Diagrammdaten für Drucker-Nutzung zurück."""
    try:
        db_session = get_db_session()
        
        # Drucker mit Job-Anzahl
        printer_usage = db_session.query(
            Printer.name,
            func.count(Job.id).label('job_count')
        ).outerjoin(Job).group_by(Printer.id, Printer.name).all()
        
        db_session.close()
        
        chart_data = {
            'labels': [usage[0] for usage in printer_usage],
            'datasets': [{
                'label': 'Anzahl Jobs',
                'data': [usage[1] for usage in printer_usage],
                'backgroundColor': '#3b82f6',
                'borderColor': '#1d4ed8',
                'borderWidth': 1
            }]
        }
        
        return jsonify(chart_data)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Drucker-Nutzung-Diagrammdaten: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/charts/jobs-timeline", methods=["GET"])
@login_required
def get_jobs_timeline_chart_data():
    """Gibt Diagrammdaten für Jobs-Timeline der letzten 30 Tage zurück."""
    try:
        db_session = get_db_session()
        
        # Letzte 30 Tage
        end_date = datetime.now().date()
        start_date = end_date - timedelta(days=30)
        
        # Jobs pro Tag der letzten 30 Tage
        daily_jobs = db_session.query(
            func.date(Job.created_at).label('date'),
            func.count(Job.id).label('count')
        ).filter(
            func.date(Job.created_at) >= start_date,
            func.date(Job.created_at) <= end_date
        ).group_by(func.date(Job.created_at)).all()
        
        # Alle Tage füllen (auch ohne Jobs)
        date_dict = {job_date: count for job_date, count in daily_jobs}
        
        labels = []
        data = []
        current_date = start_date
        
        while current_date <= end_date:
            labels.append(current_date.strftime('%d.%m'))
            data.append(date_dict.get(current_date, 0))
            current_date += timedelta(days=1)
        
        db_session.close()
        
        chart_data = {
            'labels': labels,
            'datasets': [{
                'label': 'Jobs pro Tag',
                'data': data,
                'fill': True,
                'backgroundColor': 'rgba(59, 130, 246, 0.1)',
                'borderColor': '#3b82f6',
                'tension': 0.4
            }]
        }
        
        return jsonify(chart_data)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Jobs-Timeline-Diagrammdaten: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/charts/user-activity", methods=["GET"])
@login_required
def get_user_activity_chart_data():
    """Gibt Diagrammdaten für Top-Benutzer-Aktivität zurück."""
    try:
        db_session = get_db_session()
        
        # Top 10 Benutzer nach Job-Anzahl
        top_users = db_session.query(
            User.username,
            func.count(Job.id).label('job_count')
        ).join(Job).group_by(
            User.id, User.username
        ).order_by(
            func.count(Job.id).desc()
        ).limit(10).all()
        
        db_session.close()
        
        chart_data = {
            'labels': [user[0] for user in top_users],
            'datasets': [{
                'label': 'Anzahl Jobs',
                'data': [user[1] for user in top_users],
                'backgroundColor': '#8b5cf6',
                'borderColor': '#7c3aed',
                'borderWidth': 1
            }]
        }
        
        return jsonify(chart_data)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Benutzer-Aktivität-Diagrammdaten: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/export", methods=["GET"])
@login_required
def export_stats():
    """Exportiert Statistiken als CSV."""
    try:
        db_session = get_db_session()
        
        # Basis-Statistiken sammeln
        total_users = db_session.query(User).count()
        total_printers = db_session.query(Printer).count()
        total_jobs = db_session.query(Job).count()
        completed_jobs = db_session.query(Job).filter(Job.status == "completed").count()
        failed_jobs = db_session.query(Job).filter(Job.status == "failed").count()
        
        # CSV-Inhalt erstellen
        import io
        import csv
        
        output = io.StringIO()
        writer = csv.writer(output)
        
        # Header
        writer.writerow(['Metrik', 'Wert'])
        
        # Daten
        writer.writerow(['Gesamte Benutzer', total_users])
        writer.writerow(['Gesamte Drucker', total_printers])
        writer.writerow(['Gesamte Jobs', total_jobs])
        writer.writerow(['Abgeschlossene Jobs', completed_jobs])
        writer.writerow(['Fehlgeschlagene Jobs', failed_jobs])
        writer.writerow(['Erfolgsrate (%)', round((completed_jobs / total_jobs * 100), 2) if total_jobs > 0 else 0])
        writer.writerow(['Exportiert am', datetime.now().strftime('%d.%m.%Y %H:%M:%S')])
        
        db_session.close()
        
        # Response vorbereiten
        output.seek(0)
        
        response = Response(
            output.getvalue(),
            mimetype='text/csv',
            headers={
                'Content-Disposition': f'attachment; filename=statistiken_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv'
            }
        )
        
        return response
        
    except Exception as e:
        app_logger.error(f"Fehler beim Exportieren der Statistiken: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/admin/users", methods=["GET"])
@login_required
def get_users():
    """Gibt alle Benutzer zurück (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Benutzer anzeigen"}), 403
    
    try:
        db_session = get_db_session()
        users = db_session.query(User).all()
        
        user_data = []
        for user in users:
            user_data.append({
                "id": user.id,
                "username": user.username,
                "email": user.email,
                "first_name": user.first_name,
                "last_name": user.last_name,
                "is_admin": user.is_admin,
                "created_at": user.created_at.isoformat() if user.created_at else None,
                "last_login": user.last_login.isoformat() if hasattr(user, 'last_login') and user.last_login else None
            })
        
        db_session.close()
        return jsonify({"users": user_data})
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Benutzer: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/admin/users/<int:user_id>", methods=["PUT"])
@login_required
def update_user(user_id):
    """Aktualisiert einen Benutzer (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Benutzer bearbeiten"}), 403
    
    try:
        data = request.json
        db_session = get_db_session()
        
        user = db_session.get(User, user_id)
        if not user:
            db_session.close()
            return jsonify({"error": "Benutzer nicht gefunden"}), 404
        
        # Aktualisierbare Felder
        updatable_fields = ["username", "email", "first_name", "last_name", "is_admin"]
        for field in updatable_fields:
            if field in data:
                setattr(user, field, data[field])
        
        # Passwort separat behandeln
        if "password" in data and data["password"]:
            user.set_password(data["password"])
        
        db_session.commit()
        
        user_data = {
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "first_name": user.first_name,
            "last_name": user.last_name,
            "is_admin": user.is_admin,
            "created_at": user.created_at.isoformat() if user.created_at else None
        }
        
        db_session.close()
        
        user_logger.info(f"Benutzer {user_id} aktualisiert von Admin {current_user.id}")
        return jsonify({"user": user_data})
        
    except Exception as e:
        user_logger.error(f"Fehler beim Aktualisieren des Benutzers {user_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/admin/users/<int:user_id>", methods=["DELETE"])
@login_required
def delete_user(user_id):
    """Löscht einen Benutzer (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Benutzer löschen"}), 403
    
    # Verhindern, dass sich der Admin selbst löscht
    if user_id == current_user.id:
        return jsonify({"error": "Sie können sich nicht selbst löschen"}), 400
    
    try:
        db_session = get_db_session()
        
        user = db_session.get(User, user_id)
        if not user:
            db_session.close()
            return jsonify({"error": "Benutzer nicht gefunden"}), 404
        
        # Prüfen, ob noch aktive Jobs für diesen Benutzer existieren
        active_jobs = db_session.query(Job).filter(
            Job.user_id == user_id,
            Job.status.in_(["scheduled", "running"])
        ).count()
        
        if active_jobs > 0:
            db_session.close()
            return jsonify({"error": f"Benutzer kann nicht gelöscht werden: {active_jobs} aktive Jobs vorhanden"}), 400
        
        username = user.username
        db_session.delete(user)
        db_session.commit()
        db_session.close()
        
        user_logger.info(f"Benutzer '{username}' (ID: {user_id}) gelöscht von Admin {current_user.id}")
        return jsonify({"message": "Benutzer erfolgreich gelöscht"})
        
    except Exception as e:
        user_logger.error(f"Fehler beim Löschen des Benutzers {user_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

# ===== FEHLERBEHANDLUNG =====

@app.errorhandler(404)
def not_found_error(error):
    return render_template('errors/404.html'), 404

@app.errorhandler(500)
def internal_error(error):
    return render_template('errors/500.html'), 500

@app.errorhandler(403)
def forbidden_error(error):
    return render_template('errors/403.html'), 403

# ===== ADMIN - DATENBANK-VERWALTUNG =====

@app.route('/api/admin/database/stats', methods=['GET'])
@admin_required
def get_database_stats():
    """Gibt Datenbank-Statistiken zurück."""
    try:
        if database_monitor is None:
            return jsonify({
                "success": False,
                "error": "Database Monitor nicht verfügbar"
            }), 503
            
        stats = database_monitor.get_database_stats()
        return jsonify({
            "success": True,
            "stats": stats
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Datenbank-Statistiken: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/health', methods=['GET'])
@admin_required
def check_database_health():
    """Führt eine Datenbank-Gesundheitsprüfung durch."""
    try:
        if database_monitor is None:
            return jsonify({
                "success": False,
                "error": "Database Monitor nicht verfügbar"
            }), 503
            
        health = database_monitor.check_database_health()
        return jsonify({
            "success": True,
            "health": health
        })
    except Exception as e:
        app_logger.error(f"Fehler bei Datenbank-Gesundheitsprüfung: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/optimize', methods=['POST'])
@admin_required
def optimize_database():
    """Führt Datenbank-Optimierung durch."""
    try:
        if database_monitor is None:
            return jsonify({
                "success": False,
                "error": "Database Monitor nicht verfügbar"
            }), 503
            
        result = database_monitor.optimize_database()
        return jsonify({
            "success": result["success"],
            "result": result
        })
    except Exception as e:
        app_logger.error(f"Fehler bei Datenbank-Optimierung: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/backup', methods=['POST'])
@admin_required
def create_database_backup():
    """Erstellt ein manuelles Datenbank-Backup."""
    try:
        if backup_manager is None:
            return jsonify({
                "success": False,
                "error": "Backup Manager nicht verfügbar"
            }), 503
            
        data = request.get_json() or {}
        compress = data.get('compress', True)
        
        backup_path = backup_manager.create_backup(compress=compress)
        
        return jsonify({
            "success": True,
            "backup_path": backup_path,
            "message": "Backup erfolgreich erstellt"
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Erstellen des Backups: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/backups', methods=['GET'])
@admin_required
def list_database_backups():
    """Listet alle verfügbaren Datenbank-Backups auf."""
    try:
        if backup_manager is None:
            return jsonify({
                "success": False,
                "error": "Backup Manager nicht verfügbar"
            }), 503
            
        backups = backup_manager.get_backup_list()
        
        # Konvertiere datetime-Objekte zu Strings für JSON
        for backup in backups:
            backup['created'] = backup['created'].isoformat()
        
        return jsonify({
            "success": True,
            "backups": backups
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Backup-Liste: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/backup/restore', methods=['POST'])
@admin_required
def restore_database_backup():
    """Stellt ein Datenbank-Backup wieder her."""
    try:
        if backup_manager is None:
            return jsonify({
                "success": False,
                "error": "Backup Manager nicht verfügbar"
            }), 503
            
        data = request.get_json()
        if not data or 'backup_path' not in data:
            return jsonify({
                "success": False,
                "error": "Backup-Pfad erforderlich"
            }), 400
        
        backup_path = data['backup_path']
        
        # Sicherheitsprüfung: Nur Backups aus dem Backup-Verzeichnis erlauben
        if not backup_path.startswith(backup_manager.backup_dir):
            return jsonify({
                "success": False,
                "error": "Ungültiger Backup-Pfad"
            }), 400
        
        success = backup_manager.restore_backup(backup_path)
        
        if success:
            return jsonify({
                "success": True,
                "message": "Backup erfolgreich wiederhergestellt"
            })
        else:
            return jsonify({
                "success": False,
                "error": "Fehler beim Wiederherstellen des Backups"
            }), 500
            
    except Exception as e:
        app_logger.error(f"Fehler beim Wiederherstellen des Backups: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/backup/cleanup', methods=['POST'])
@admin_required
def cleanup_old_backups():
    """Löscht alte Datenbank-Backups."""
    try:
        backup_dir = os.path.join(os.path.dirname(__file__), 'database', 'backups')
        if not os.path.exists(backup_dir):
            return jsonify({"error": "Backup-Verzeichnis nicht gefunden"}), 404
        
        # Backups älter als 30 Tage löschen
        cutoff_date = datetime.now() - timedelta(days=30)
        deleted_count = 0
        
        for filename in os.listdir(backup_dir):
            if filename.endswith('.sql'):
                file_path = os.path.join(backup_dir, filename)
                file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
                
                if file_mtime < cutoff_date:
                    os.remove(file_path)
                    deleted_count += 1
        
        return jsonify({
            "message": f"{deleted_count} alte Backups gelöscht",
            "deleted_count": deleted_count
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Löschen alter Backups: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/admin/stats/live', methods=['GET'])
@admin_required
def get_admin_live_stats():
    """Liefert Live-Statistiken für das Admin-Dashboard."""
    try:
        db_session = get_db_session()
        
        # Aktuelle Statistiken sammeln
        total_users = db_session.query(User).count()
        total_printers = db_session.query(Printer).count()
        total_jobs = db_session.query(Job).count()
        active_jobs = db_session.query(Job).filter(Job.status.in_(["scheduled", "running"])).count()
        
        # Printer-Status
        available_printers = db_session.query(Printer).filter(Printer.status == "available").count()
        offline_printers = db_session.query(Printer).filter(Printer.status == "offline").count()
        maintenance_printers = db_session.query(Printer).filter(Printer.status == "maintenance").count()
        
        # Jobs heute
        today = datetime.now().date()
        jobs_today = db_session.query(Job).filter(
            func.date(Job.created_at) == today
        ).count()
        
        # Erfolgreiche Jobs heute
        completed_jobs_today = db_session.query(Job).filter(
            func.date(Job.created_at) == today,
            Job.status == "completed"
        ).count()
        
        db_session.close()
        
        stats = {
            "users": {
                "total": total_users
            },
            "printers": {
                "total": total_printers,
                "available": available_printers,
                "offline": offline_printers,
                "maintenance": maintenance_printers
            },
            "jobs": {
                "total": total_jobs,
                "active": active_jobs,
                "today": jobs_today,
                "completed_today": completed_jobs_today
            },
            "timestamp": datetime.now().isoformat()
        }
        
        return jsonify(stats)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Live-Statistiken: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/admin/system/status', methods=['GET'])
@admin_required
def get_system_status():
    """Liefert System-Status-Informationen."""
    try:
        import psutil
        import platform
        
        # CPU und Memory
        cpu_percent = psutil.cpu_percent(interval=1)
        memory = psutil.virtual_memory()
        disk = psutil.disk_usage('/')
        
        # Netzwerk (vereinfacht)
        network = psutil.net_io_counters()
        
        system_info = {
            "platform": platform.system(),
            "platform_release": platform.release(),
            "platform_version": platform.version(),
            "machine": platform.machine(),
            "processor": platform.processor(),
            "cpu": {
                "percent": cpu_percent,
                "count": psutil.cpu_count()
            },
            "memory": {
                "total": memory.total,
                "available": memory.available,
                "percent": memory.percent,
                "used": memory.used
            },
            "disk": {
                "total": disk.total,
                "used": disk.used,
                "free": disk.free,
                "percent": (disk.used / disk.total) * 100
            },
            "network": {
                "bytes_sent": network.bytes_sent,
                "bytes_recv": network.bytes_recv
            },
            "timestamp": datetime.now().isoformat()
        }
        
        return jsonify(system_info)
        
    except ImportError:
        return jsonify({
            "error": "psutil nicht installiert",
            "message": "Systemstatus kann nicht abgerufen werden"
        }), 500
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen des Systemstatus: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/admin/database/status', methods=['GET'])
@admin_required  
def get_database_status():
    """Liefert Datenbank-Status-Informationen."""
    try:
        db_session = get_db_session()
        
        # Tabellen-Informationen sammeln
        table_stats = {}
        
        # User-Tabelle
        user_count = db_session.query(User).count()
        latest_user = db_session.query(User).order_by(User.created_at.desc()).first()
        
        # Printer-Tabelle  
        printer_count = db_session.query(Printer).count()
        latest_printer = db_session.query(Printer).order_by(Printer.created_at.desc()).first()
        
        # Job-Tabelle
        job_count = db_session.query(Job).count()
        latest_job = db_session.query(Job).order_by(Job.created_at.desc()).first()
        
        table_stats = {
            "users": {
                "count": user_count,
                "latest": latest_user.created_at.isoformat() if latest_user else None
            },
            "printers": {
                "count": printer_count,
                "latest": latest_printer.created_at.isoformat() if latest_printer else None
            },
            "jobs": {
                "count": job_count,
                "latest": latest_job.created_at.isoformat() if latest_job else None
            }
        }
        
        db_session.close()
        
        # Datenbank-Dateigröße (falls SQLite)
        db_file_size = None
        try:
            db_path = os.path.join(os.path.dirname(__file__), 'database', 'app.db')
            if os.path.exists(db_path):
                db_file_size = os.path.getsize(db_path)
        except:
            pass
        
        status = {
            "tables": table_stats,
            "database_size": db_file_size,
            "timestamp": datetime.now().isoformat(),
            "connection_status": "connected"
        }
        
        return jsonify(status)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen des Datenbankstatus: {str(e)}")
        return jsonify({
            "error": "Datenbankfehler",
            "connection_status": "error",
            "timestamp": datetime.now().isoformat()
        }), 500

# ===== WEITERE UI-ROUTEN =====

@app.route("/terms")
def terms():
    """Zeigt die Nutzungsbedingungen an."""
    return render_template("terms.html")

@app.route("/privacy")
def privacy():
    """Zeigt die Datenschutzerklärung an."""
    return render_template("privacy.html")

@app.route("/admin/users/add")
@login_required
def admin_add_user_page():
    """Zeigt die Seite zum Hinzufügen eines neuen Benutzers an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    return render_template("admin_add_user.html")

@app.route("/admin/printers/add")
@login_required
def admin_add_printer_page():
    """Zeigt die Seite zum Hinzufügen eines neuen Druckers an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    return render_template("admin_add_printer.html")

@app.route("/admin/printers/<int:printer_id>/manage")
@login_required
def admin_manage_printer_page(printer_id):
    """Zeigt die Drucker-Verwaltungsseite an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    db_session = get_db_session()
    try:
        printer = db_session.get(Printer, printer_id)
        if not printer:
            flash("Drucker nicht gefunden.", "error")
            return redirect(url_for("admin_page"))
        
        printer_data = {
            "id": printer.id,
            "name": printer.name,
            "model": printer.model or 'Unbekanntes Modell',
            "location": printer.location or 'Unbekannter Standort',
            "mac_address": printer.mac_address,
            "plug_ip": printer.plug_ip,
            "status": printer.status or "offline",
            "active": printer.active if hasattr(printer, 'active') else True,
            "created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        return render_template("admin_manage_printer.html", printer=printer_data)
        
    except Exception as e:
        db_session.close()
        app_logger.error(f"Fehler beim Laden der Drucker-Verwaltung: {str(e)}")
        flash("Fehler beim Laden der Drucker-Daten.", "error")
        return redirect(url_for("admin_page"))

@app.route("/admin/printers/<int:printer_id>/settings")
@login_required
def admin_printer_settings_page(printer_id):
    """Zeigt die Drucker-Einstellungsseite an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    db_session = get_db_session()
    try:
        printer = db_session.get(Printer, printer_id)
        if not printer:
            flash("Drucker nicht gefunden.", "error")
            return redirect(url_for("admin_page"))
        
        printer_data = {
            "id": printer.id,
            "name": printer.name,
            "model": printer.model or 'Unbekanntes Modell',
            "location": printer.location or 'Unbekannter Standort',
            "mac_address": printer.mac_address,
            "plug_ip": printer.plug_ip,
            "status": printer.status or "offline",
            "active": printer.active if hasattr(printer, 'active') else True,
            "created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        return render_template("admin_printer_settings.html", printer=printer_data)
        
    except Exception as e:
        db_session.close()
        app_logger.error(f"Fehler beim Laden der Drucker-Einstellungen: {str(e)}")
        flash("Fehler beim Laden der Drucker-Daten.", "error")
        return redirect(url_for("admin_page"))

@app.route("/admin/guest-requests")
@login_required
@admin_required
def admin_guest_requests():
    """Admin-Seite für Gastanfragen Verwaltung"""
    try:
        app_logger.info(f"Admin-Gastanfragen Seite aufgerufen von User {current_user.id}")
        return render_template("admin_guest_requests.html")
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Gastanfragen Seite: {str(e)}")
        flash("Fehler beim Laden der Gastanfragen-Verwaltung.", "danger")
        return redirect(url_for("admin"))

@app.route("/requests/overview")
@login_required
@admin_required
def admin_guest_requests_overview():
    """Admin-Oberfläche für die Verwaltung von Gastanfragen mit direkten Aktionen."""
    try:
        app_logger.info(f"Admin-Gastanträge Übersicht aufgerufen von User {current_user.id}")
        return render_template("admin_guest_requests_overview.html")
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Gastanträge Übersicht: {str(e)}")
        flash("Fehler beim Laden der Gastanträge-Übersicht.", "danger")
        return redirect(url_for("admin"))

# ===== ADMIN API-ROUTEN FÜR BENUTZER UND DRUCKER =====

@app.route("/api/admin/users", methods=["POST"])
@login_required
def create_user_api():
    """Erstellt einen neuen Benutzer (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Benutzer erstellen"}), 403
    
    try:
        data = request.json
        
        # Pflichtfelder prüfen
        required_fields = ["username", "email", "password"]
        for field in required_fields:
            if field not in data or not data[field]:
                return jsonify({"error": f"Feld '{field}' ist erforderlich"}), 400
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Benutzer mit diesem Benutzernamen oder E-Mail existiert
        existing_user = db_session.query(User).filter(
            (User.username == data["username"]) | (User.email == data["email"])
        ).first()
        
        if existing_user:
            db_session.close()
            return jsonify({"error": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert bereits"}), 400
        
        # Neuen Benutzer erstellen
        new_user = User(
            username=data["username"],
            email=data["email"],
            first_name=data.get("first_name", ""),
            last_name=data.get("last_name", ""),
            is_admin=data.get("is_admin", False),
            created_at=datetime.now()
        )
        
        # Passwort setzen
        new_user.set_password(data["password"])
        
        db_session.add(new_user)
        db_session.commit()
        
        user_data = {
            "id": new_user.id,
            "username": new_user.username,
            "email": new_user.email,
            "first_name": new_user.first_name,
            "last_name": new_user.last_name,
            "is_admin": new_user.is_admin,
            "created_at": new_user.created_at.isoformat()
        }
        
        db_session.close()
        
        user_logger.info(f"Neuer Benutzer '{new_user.username}' erstellt von Admin {current_user.id}")
        return jsonify({"user": user_data}), 201
        
    except Exception as e:
        user_logger.error(f"Fehler beim Erstellen eines Benutzers: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/admin/printers/<int:printer_id>/toggle", methods=["POST"])
@login_required
def toggle_printer_power(printer_id):
    """
    Schaltet einen Drucker über die zugehörige Steckdose ein/aus.
    """
    if not current_user.is_admin:
        return jsonify({"error": "Administratorrechte erforderlich"}), 403
    
    try:
        # Robuste JSON-Datenverarbeitung
        data = {}
        try:
            if request.is_json and request.get_json():
                data = request.get_json()
            elif request.form:
                # Fallback für Form-Daten
                data = request.form.to_dict()
        except Exception as json_error:
            printers_logger.warning(f"Fehler beim Parsen der JSON-Daten für Drucker {printer_id}: {str(json_error)}")
            # Verwende Standard-Werte wenn JSON-Parsing fehlschlägt
            data = {}
        
        # Standard-Zustand ermitteln (Toggle-Verhalten)
        db_session = get_db_session()
        printer = db_session.query(Printer).get(printer_id)
        
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Aktuellen Status ermitteln für Toggle-Verhalten
        current_status = getattr(printer, 'status', 'offline')
        current_active = getattr(printer, 'active', False)
        
        # Zielzustand bestimmen
        if 'state' in data:
            # Expliziter Zustand angegeben
            state = bool(data.get("state", True))
        else:
            # Toggle-Verhalten: Umschalten basierend auf aktuellem Status
            state = not (current_status == "available" and current_active)
        
        db_session.close()
        
        # Steckdose schalten
        from utils.job_scheduler import toggle_plug
        success = toggle_plug(printer_id, state)
        
        if success:
            action = "eingeschaltet" if state else "ausgeschaltet"
            printers_logger.info(f"Drucker {printer.name} (ID: {printer_id}) erfolgreich {action} von Admin {current_user.name}")
            
            return jsonify({
                "success": True,
                "message": f"Drucker erfolgreich {action}",
                "printer_id": printer_id,
                "printer_name": printer.name,
                "state": state,
                "action": action
            })
        else:
            printers_logger.error(f"Fehler beim Schalten der Steckdose für Drucker {printer_id}")
            return jsonify({
                "success": False,
                "error": "Fehler beim Schalten der Steckdose",
                "printer_id": printer_id
            }), 500
            
    except Exception as e:
        printers_logger.error(f"Fehler beim Schalten von Drucker {printer_id}: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Interner Serverfehler",
            "details": str(e)
        }), 500

@app.route("/api/admin/printers/<int:printer_id>/test-tapo", methods=["POST"])
@login_required
@admin_required
def test_printer_tapo_connection(printer_id):
    """
    Testet die Tapo-Steckdosen-Verbindung für einen Drucker.
    """
    try:
        db_session = get_db_session()
        printer = db_session.query(Printer).get(printer_id)
        
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        if not printer.plug_ip or not printer.plug_username or not printer.plug_password:
            db_session.close()
            return jsonify({
                "error": "Unvollständige Tapo-Konfiguration",
                "missing": [
                    key for key, value in {
                        "plug_ip": printer.plug_ip,
                        "plug_username": printer.plug_username,
                        "plug_password": printer.plug_password
                    }.items() if not value
                ]
            }), 400
        
        db_session.close()
        
        # Tapo-Verbindung testen
        from utils.job_scheduler import test_tapo_connection
        test_result = test_tapo_connection(
            printer.plug_ip,
            printer.plug_username,
            printer.plug_password
        )
        
        return jsonify({
            "printer_id": printer_id,
            "printer_name": printer.name,
            "tapo_test": test_result
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Testen der Tapo-Verbindung für Drucker {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler beim Verbindungstest"}), 500

@app.route("/api/admin/printers/test-all-tapo", methods=["POST"])
@login_required
@admin_required
def test_all_printers_tapo_connection():
    """
    Testet die Tapo-Steckdosen-Verbindung für alle Drucker.
    Nützlich für Diagnose und Setup-Validierung.
    """
    try:
        db_session = get_db_session()
        printers = db_session.query(Printer).filter(Printer.active == True).all()
        db_session.close()
        
        if not printers:
            return jsonify({
                "message": "Keine aktiven Drucker gefunden",
                "results": []
            })
        
        # Alle Drucker testen
        from utils.job_scheduler import test_tapo_connection
        results = []
        
        for printer in printers:
            result = {
                "printer_id": printer.id,
                "printer_name": printer.name,
                "plug_ip": printer.plug_ip,
                "has_config": bool(printer.plug_ip and printer.plug_username and printer.plug_password)
            }
            
            if result["has_config"]:
                # Tapo-Verbindung testen
                test_result = test_tapo_connection(
                    printer.plug_ip,
                    printer.plug_username,
                    printer.plug_password
                )
                result["tapo_test"] = test_result
            else:
                result["tapo_test"] = {
                    "success": False,
                    "error": "Unvollständige Tapo-Konfiguration",
                    "device_info": None,
                    "status": "unconfigured"
                }
                result["missing_config"] = [
                    key for key, value in {
                        "plug_ip": printer.plug_ip,
                        "plug_username": printer.plug_username,
                        "plug_password": printer.plug_password
                    }.items() if not value
                ]
            
            results.append(result)
        
        # Zusammenfassung erstellen
        total_printers = len(results)
        successful_connections = sum(1 for r in results if r["tapo_test"]["success"])
        configured_printers = sum(1 for r in results if r["has_config"])
        
        return jsonify({
            "summary": {
                "total_printers": total_printers,
                "configured_printers": configured_printers,
                "successful_connections": successful_connections,
                "success_rate": round(successful_connections / total_printers * 100, 1) if total_printers > 0 else 0
            },
            "results": results
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Testen aller Tapo-Verbindungen: {str(e)}")
        return jsonify({"error": "Interner Serverfehler beim Massentest"}), 500

# ===== ADMIN FORM ENDPOINTS =====

@app.route("/admin/users/create", methods=["POST"])
@login_required
def admin_create_user_form():
    """Erstellt einen neuen Benutzer über HTML-Form (nur für Admins)."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    try:
        # Form-Daten lesen
        email = request.form.get("email", "").strip()
        name = request.form.get("name", "").strip()
        password = request.form.get("password", "").strip()
        role = request.form.get("role", "user").strip()
        
        # Pflichtfelder prüfen
        if not email or not password:
            flash("E-Mail und Passwort sind erforderlich.", "error")
            return redirect(url_for("admin_add_user_page"))
        
        # E-Mail validieren
        import re
        email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        if not re.match(email_pattern, email):
            flash("Ungültige E-Mail-Adresse.", "error")
            return redirect(url_for("admin_add_user_page"))
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Benutzer mit dieser E-Mail existiert
        existing_user = db_session.query(User).filter(User.email == email).first()
        if existing_user:
            db_session.close()
            flash("Ein Benutzer mit dieser E-Mail existiert bereits.", "error")
            return redirect(url_for("admin_add_user_page"))
        
        # E-Mail als Username verwenden (falls kein separates Username-Feld)
        username = email.split('@')[0]
        counter = 1
        original_username = username
        while db_session.query(User).filter(User.username == username).first():
            username = f"{original_username}{counter}"
            counter += 1
        
        # Neuen Benutzer erstellen
        new_user = User(
            username=username,
            email=email,
            first_name=name.split(' ')[0] if name else "",
            last_name=" ".join(name.split(' ')[1:]) if name and ' ' in name else "",
            is_admin=(role == "admin"),
            created_at=datetime.now()
        )
        
        # Passwort setzen
        new_user.set_password(password)
        
        db_session.add(new_user)
        db_session.commit()
        db_session.close()
        
        user_logger.info(f"Neuer Benutzer '{new_user.username}' erstellt von Admin {current_user.id}")
        flash(f"Benutzer '{new_user.email}' erfolgreich erstellt.", "success")
        return redirect(url_for("admin_page", tab="users"))
        
    except Exception as e:
        user_logger.error(f"Fehler beim Erstellen eines Benutzers über Form: {str(e)}")
        flash("Fehler beim Erstellen des Benutzers.", "error")
        return redirect(url_for("admin_add_user_page"))

@app.route("/admin/printers/create", methods=["POST"])
@login_required
def admin_create_printer_form():
    """Erstellt einen neuen Drucker über HTML-Form (nur für Admins)."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    try:
        # Form-Daten lesen
        name = request.form.get("name", "").strip()
        ip_address = request.form.get("ip_address", "").strip()
        model = request.form.get("model", "").strip()
        location = request.form.get("location", "").strip()
        description = request.form.get("description", "").strip()
        status = request.form.get("status", "available").strip()
        
        # Pflichtfelder prüfen
        if not name or not ip_address:
            flash("Name und IP-Adresse sind erforderlich.", "error")
            return redirect(url_for("admin_add_printer_page"))
        
        # IP-Adresse validieren
        import re
        ip_pattern = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
        if not re.match(ip_pattern, ip_address):
            flash("Ungültige IP-Adresse.", "error")
            return redirect(url_for("admin_add_printer_page"))
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Drucker mit diesem Namen existiert
        existing_printer = db_session.query(Printer).filter(Printer.name == name).first()
        if existing_printer:
            db_session.close()
            flash("Ein Drucker mit diesem Namen existiert bereits.", "error")
            return redirect(url_for("admin_add_printer_page"))
        
        # Neuen Drucker erstellen
        new_printer = Printer(
            name=name,
            model=model,
            location=location,
            description=description,
            mac_address="",  # Wird später ausgefüllt
            plug_ip=ip_address,
            status=status,
            created_at=datetime.now()
        )
        
        db_session.add(new_printer)
        db_session.commit()
        db_session.close()
        
        printers_logger.info(f"Neuer Drucker '{new_printer.name}' erstellt von Admin {current_user.id}")
        flash(f"Drucker '{new_printer.name}' erfolgreich erstellt.", "success")
        return redirect(url_for("admin_page", tab="printers"))
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Erstellen eines Druckers über Form: {str(e)}")
        flash("Fehler beim Erstellen des Druckers.", "error")
        return redirect(url_for("admin_add_printer_page"))

@app.route("/admin/users/<int:user_id>/edit", methods=["GET"])
@login_required
def admin_edit_user_page(user_id):
    """Zeigt die Benutzer-Bearbeitungsseite an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    db_session = get_db_session()
    try:
        user = db_session.get(User, user_id)
        if not user:
            flash("Benutzer nicht gefunden.", "error")
            return redirect(url_for("admin_page", tab="users"))
        
        user_data = {
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "name": user.name or "",
            "is_admin": user.is_admin,
            "active": user.active,
            "created_at": user.created_at.isoformat() if user.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        return render_template("admin_edit_user.html", user=user_data)
        
    except Exception as e:
        db_session.close()
        app_logger.error(f"Fehler beim Laden der Benutzer-Daten: {str(e)}")
        flash("Fehler beim Laden der Benutzer-Daten.", "error")
        return redirect(url_for("admin_page", tab="users"))

@app.route("/admin/users/<int:user_id>/update", methods=["POST"])
@login_required
def admin_update_user_form(user_id):
    """Aktualisiert einen Benutzer über HTML-Form (nur für Admins)."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    try:
        # Form-Daten lesen
        email = request.form.get("email", "").strip()
        name = request.form.get("name", "").strip()
        password = request.form.get("password", "").strip()
        role = request.form.get("role", "user").strip()
        is_active = request.form.get("is_active", "true").strip() == "true"
        
        # Pflichtfelder prüfen
        if not email:
            flash("E-Mail-Adresse ist erforderlich.", "error")
            return redirect(url_for("admin_edit_user_page", user_id=user_id))
        
        # E-Mail validieren
        import re
        email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        if not re.match(email_pattern, email):
            flash("Ungültige E-Mail-Adresse.", "error")
            return redirect(url_for("admin_edit_user_page", user_id=user_id))
        
        db_session = get_db_session()
        
        user = db_session.query(User).get(user_id)
        if not user:
            db_session.close()
            flash("Benutzer nicht gefunden.", "error")
            return redirect(url_for("admin_page", tab="users"))
        
        # Prüfen, ob bereits ein anderer Benutzer mit dieser E-Mail existiert
        existing_user = db_session.query(User).filter(
            User.email == email, 
            User.id != user_id
        ).first()
        if existing_user:
            db_session.close()
            flash("Ein Benutzer mit dieser E-Mail-Adresse existiert bereits.", "error")
            return redirect(url_for("admin_edit_user_page", user_id=user_id))
        
        # Benutzer aktualisieren
        user.email = email
        if name:
            user.name = name
        
        # Passwort nur ändern, wenn eines angegeben wurde
        if password:
            user.password_hash = generate_password_hash(password)
        
        user.role = "admin" if role == "admin" else "user"
        user.active = is_active
        
        db_session.commit()
        db_session.close()
        
        auth_logger.info(f"Benutzer '{user.email}' (ID: {user_id}) aktualisiert von Admin {current_user.id}")
        flash(f"Benutzer '{user.email}' erfolgreich aktualisiert.", "success")
        return redirect(url_for("admin_page", tab="users"))
        
    except Exception as e:
        auth_logger.error(f"Fehler beim Aktualisieren eines Benutzers über Form: {str(e)}")
        flash("Fehler beim Aktualisieren des Benutzers.", "error")
        return redirect(url_for("admin_edit_user_page", user_id=user_id))

@app.route("/admin/printers/<int:printer_id>/update", methods=["POST"])
@login_required
def admin_update_printer_form(printer_id):
    """Aktualisiert einen Drucker über HTML-Form (nur für Admins)."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    try:
        # Form-Daten lesen
        name = request.form.get("name", "").strip()
        ip_address = request.form.get("ip_address", "").strip()
        model = request.form.get("model", "").strip()
        location = request.form.get("location", "").strip()
        description = request.form.get("description", "").strip()
        status = request.form.get("status", "available").strip()
        
        # Pflichtfelder prüfen
        if not name or not ip_address:
            flash("Name und IP-Adresse sind erforderlich.", "error")
            return redirect(url_for("admin_edit_printer_page", printer_id=printer_id))
        
        # IP-Adresse validieren
        import re
        ip_pattern = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
        if not re.match(ip_pattern, ip_address):
            flash("Ungültige IP-Adresse.", "error")
            return redirect(url_for("admin_edit_printer_page", printer_id=printer_id))
        
        db_session = get_db_session()
        
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            flash("Drucker nicht gefunden.", "error")
            return redirect(url_for("admin_page", tab="printers"))
        
        # Drucker aktualisieren
        printer.name = name
        printer.model = model
        printer.location = location
        printer.description = description
        printer.plug_ip = ip_address
        printer.status = status
        
        db_session.commit()
        db_session.close()
        
        printers_logger.info(f"Drucker '{printer.name}' (ID: {printer_id}) aktualisiert von Admin {current_user.id}")
        flash(f"Drucker '{printer.name}' erfolgreich aktualisiert.", "success")
        return redirect(url_for("admin_page", tab="printers"))
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Aktualisieren eines Druckers über Form: {str(e)}")
        flash("Fehler beim Aktualisieren des Druckers.", "error")
        return redirect(url_for("admin_edit_printer_page", printer_id=printer_id))

# Login-Manager initialisieren
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"
login_manager.login_message = "Bitte melden Sie sich an, um auf diese Seite zuzugreifen."
login_manager.login_message_category = "info"

@login_manager.user_loader
def load_user(user_id):
    """
    Robuster User-Loader mit Error-Handling für Schema-Probleme.
    """
    try:
        # user_id von Flask-Login ist immer ein String - zu Integer konvertieren
        try:
            user_id_int = int(user_id)
        except (ValueError, TypeError):
            app_logger.error(f"Ungültige User-ID: {user_id}")
            return None
            
        db_session = get_db_session()
        
        # Robuste Abfrage mit Error-Handling
        try:
            user = db_session.query(User).filter(User.id == user_id_int).first()
            db_session.close()
            return user
        except Exception as db_error:
            # Schema-Problem - versuche manuelle Abfrage
            app_logger.warning(f"Schema-Problem beim User-Load für ID {user_id_int}: {str(db_error)}")
            
            # Manuelle Abfrage nur mit Basis-Feldern
            try:
                result = db_session.execute(
                    text("SELECT id, email, password_hash, name, role, active FROM users WHERE id = :user_id"),
                    {"user_id": user_id_int}
                ).fetchone()
                
                if result:
                    # Manuell User-Objekt erstellen
                    user = User()
                    user.id = result[0]
                    user.email = result[1] if len(result) > 1 else f"user_{user_id_int}@system.local"
                    user.password_hash = result[2] if len(result) > 2 else ""
                    user.name = result[3] if len(result) > 3 else f"User {user_id_int}"
                    user.role = result[4] if len(result) > 4 else "user"
                    user.active = result[5] if len(result) > 5 else True
                    
                    # Standard-Werte für fehlende Felder
                    user.username = getattr(user, 'username', user.email.split('@')[0])
                    user.created_at = getattr(user, 'created_at', datetime.now())
                    user.last_login = getattr(user, 'last_login', None)
                    user.updated_at = getattr(user, 'updated_at', datetime.now())
                    
                    db_session.close()
                    return user
                    
            except Exception as manual_error:
                app_logger.error(f"Auch manuelle User-Abfrage fehlgeschlagen: {str(manual_error)}")
            
            db_session.close()
            return None
            
    except Exception as e:
        app_logger.error(f"Kritischer Fehler im User-Loader für ID {user_id}: {str(e)}")
        return None

# Jinja2 Context Processors
@app.context_processor
def inject_now():
    """Inject the current datetime into templates."""
    return {'now': datetime.now()}

# Custom Jinja2 filter für Datumsformatierung
@app.template_filter('format_datetime')
def format_datetime_filter(value, format='%d.%m.%Y %H:%M'):
    """Format a datetime object to a German-style date and time string"""
    if value is None:
        return ""
    if isinstance(value, str):
        try:
            value = datetime.fromisoformat(value)
        except ValueError:
            return value
    return value.strftime(format)

# Logging initialisieren
setup_logging()
log_startup_info()

# Logger für verschiedene Komponenten
app_logger = get_logger("app")
auth_logger = get_logger("auth")
jobs_logger = get_logger("jobs")
printers_logger = get_logger("printers")
user_logger = get_logger("user")
kiosk_logger = get_logger("kiosk")

# HTTP-Request/Response-Middleware für automatisches Debug-Logging
@app.before_request
def log_request_info():
    """Loggt detaillierte Informationen über eingehende HTTP-Anfragen."""
    # Nur für API-Endpunkte und wenn Debug-Level aktiviert ist
    if request.path.startswith('/api/') or app_logger.level <= logging.DEBUG:
        debug_request(app_logger, request)

@app.after_request
def log_response_info(response):
    """Loggt detaillierte Informationen über ausgehende HTTP-Antworten."""
    # Nur für API-Endpunkte und wenn Debug-Level aktiviert ist
    if request.path.startswith('/api/') or app_logger.level <= logging.DEBUG:
        # Berechne Response-Zeit aus dem g-Objekt wenn verfügbar
        duration_ms = None
        if hasattr(request, '_start_time'):
            duration_ms = (time.time() - request._start_time) * 1000
        
        debug_response(app_logger, response, duration_ms)
    
    return response

# Start-Zeit für Request-Timing setzen
@app.before_request
def start_timer():
    """Setzt einen Timer für die Request-Bearbeitung."""
    request._start_time = time.time()

# Sicheres Passwort-Hash für Kiosk-Deaktivierung
KIOSK_PASSWORD_HASH = generate_password_hash("744563017196A")

print("Alle Blueprints wurden in app.py integriert")

# Custom decorator für Job-Besitzer-Check
def job_owner_required(f):
    @wraps(f)
    def decorated_function(job_id, *args, **kwargs):
        db_session = get_db_session()
        job = db_session.query(Job).filter(Job.id == job_id).first()
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
            
        is_owner = job.user_id == int(current_user.id) or job.owner_id == int(current_user.id)
        is_admin = current_user.is_admin
        
        if not (is_owner or is_admin):
            db_session.close()
            return jsonify({"error": "Keine Berechtigung"}), 403
            
        db_session.close()
        return f(job_id, *args, **kwargs)
    return decorated_function

# Custom decorator für Admin-Check
def admin_required(f):
    @wraps(f)
    @login_required
    def decorated_function(*args, **kwargs):
        app_logger.info(f"Admin-Check für Funktion {f.__name__}: User authenticated: {current_user.is_authenticated}, User ID: {current_user.id if current_user.is_authenticated else 'None'}, Is Admin: {current_user.is_admin if current_user.is_authenticated else 'None'}")
        if not current_user.is_admin:
            app_logger.warning(f"Admin-Zugriff verweigert für User {current_user.id if current_user.is_authenticated else 'Anonymous'} auf Funktion {f.__name__}")
            return jsonify({"error": "Nur Administratoren haben Zugriff"}), 403
        return f(*args, **kwargs)
    return decorated_function

# ===== AUTHENTIFIZIERUNGS-ROUTEN (ehemals auth.py) =====

@app.route("/auth/login", methods=["GET", "POST"])
def login():
    if current_user.is_authenticated:
        return redirect(url_for("index"))
        
    error = None
    if request.method == "POST":
        # Unterscheiden zwischen JSON-Anfragen und normalen Formular-Anfragen
        is_json_request = request.is_json or request.headers.get('Content-Type') == 'application/json'
        
        # Daten je nach Anfrageart auslesen
        if is_json_request:
            data = request.get_json()
            username = data.get("username") or data.get("email")  # Fallback für email
            password = data.get("password")
            remember_me = data.get("remember_me", False)
        else:
            # Korrigierte Feldnamen - Template verwendet "email" nicht "username"
            username = request.form.get("email")  # Geändert von "username" zu "email"
            password = request.form.get("password")
            remember_me = request.form.get("remember_me") == "on"  # Geändert von "remember-me"
        
        if not username or not password:
            error = "Benutzername und Passwort müssen angegeben werden."
            if is_json_request:
                return jsonify({"error": error}), 400
        else:
            try:
                db_session = get_db_session()
                # Suche nach Benutzer mit übereinstimmendem Benutzernamen oder E-Mail
                user = db_session.query(User).filter(
                    (User.username == username) | (User.email == username)
                ).first()
                
                if user and user.check_password(password):
                    # Update last login timestamp
                    user.update_last_login()
                    db_session.commit()
                    
                    login_user(user, remember=remember_me)
                    auth_logger.info(f"Benutzer {username} hat sich angemeldet")
                    
                    next_page = request.args.get("next")
                    db_session.close()
                    
                    if is_json_request:
                        return jsonify({"success": True, "redirect_url": next_page or url_for("index")})
                    else:
                        if next_page:
                            return redirect(next_page)
                        return redirect(url_for("index"))
                else:
                    error = "Ungültiger Benutzername oder Passwort."
                    auth_logger.warning(f"Fehlgeschlagener Login-Versuch für Benutzer {username}")
                    db_session.close()
                    
                    if is_json_request:
                        return jsonify({"error": error}), 401
            except Exception as e:
                # Fehlerbehandlung für Datenbankprobleme
                error = "Anmeldefehler. Bitte versuchen Sie es später erneut."
                auth_logger.error(f"Fehler bei der Anmeldung: {str(e)}")
                if is_json_request:
                    return jsonify({"error": error}), 500
    
    return render_template("login.html", error=error)

@app.route("/auth/logout", methods=["GET", "POST"])
@login_required
def auth_logout():
    """Meldet den Benutzer ab."""
    app_logger.info(f"Benutzer {current_user.email} hat sich abgemeldet")
    logout_user()
    flash("Sie wurden erfolgreich abgemeldet.", "info")
    return redirect(url_for("login"))

@app.route("/auth/reset-password-request", methods=["GET", "POST"])
def reset_password_request():
    """Passwort-Reset anfordern (Placeholder)."""
    # TODO: Implement password reset functionality
    flash("Passwort-Reset-Funktionalität ist noch nicht implementiert.", "info")
    return redirect(url_for("login"))

@app.route("/auth/api/login", methods=["POST"])
def api_login():
    """API-Login-Endpunkt für Frontend"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({"error": "Keine Daten erhalten"}), 400
        
        username = data.get("username")
        password = data.get("password")
        remember_me = data.get("remember_me", False)
        
        if not username or not password:
            return jsonify({"error": "Benutzername und Passwort müssen angegeben werden"}), 400
        
        db_session = get_db_session()
        user = db_session.query(User).filter(
            (User.username == username) | (User.email == username)
        ).first()
        
        if user and user.check_password(password):
            # Update last login timestamp
            user.update_last_login()
            db_session.commit()
            
            login_user(user, remember=remember_me)
            auth_logger.info(f"API-Login erfolgreich für Benutzer {username}")
            
            user_data = {
                "id": user.id,
                "username": user.username,
                "name": user.name,
                "email": user.email,
                "is_admin": user.is_admin
            }
            
            db_session.close()
            return jsonify({
                "success": True,
                "user": user_data,
                "redirect_url": url_for("index")
            })
        else:
            auth_logger.warning(f"Fehlgeschlagener API-Login für Benutzer {username}")
            db_session.close()
            return jsonify({"error": "Ungültiger Benutzername oder Passwort"}), 401
            
    except Exception as e:
        auth_logger.error(f"Fehler beim API-Login: {str(e)}")
        return jsonify({"error": "Anmeldefehler. Bitte versuchen Sie es später erneut"}), 500

@app.route("/auth/api/callback", methods=["GET", "POST"])
def api_callback():
    """OAuth-Callback-Endpunkt für externe Authentifizierung"""
    try:
        # OAuth-Provider bestimmen
        provider = request.args.get('provider', 'github')
        
        if request.method == "GET":
            # Authorization Code aus URL-Parameter extrahieren
            code = request.args.get('code')
            state = request.args.get('state')
            error = request.args.get('error')
            
            if error:
                auth_logger.warning(f"OAuth-Fehler von {provider}: {error}")
                return jsonify({
                    "error": f"OAuth-Authentifizierung fehlgeschlagen: {error}",
                    "redirect_url": url_for("login")
                }), 400
            
            if not code:
                auth_logger.warning(f"Kein Authorization Code von {provider} erhalten")
                return jsonify({
                    "error": "Kein Authorization Code erhalten",
                    "redirect_url": url_for("login")
                }), 400
            
            # State-Parameter validieren (CSRF-Schutz)
            session_state = session.get('oauth_state')
            if not state or state != session_state:
                auth_logger.warning(f"Ungültiger State-Parameter von {provider}")
                return jsonify({
                    "error": "Ungültiger State-Parameter",
                    "redirect_url": url_for("login")
                }), 400
            
            # OAuth-Token austauschen
            if provider == 'github':
                user_data = handle_github_callback(code)
            else:
                auth_logger.error(f"Unbekannter OAuth-Provider: {provider}")
                return jsonify({
                    "error": "Unbekannter OAuth-Provider",
                    "redirect_url": url_for("login")
                }), 400
            
            if not user_data:
                return jsonify({
                    "error": "Fehler beim Abrufen der Benutzerdaten",
                    "redirect_url": url_for("login")
                }), 400
            
            # Benutzer in Datenbank suchen oder erstellen
            db_session = get_db_session()
            try:
                user = db_session.query(User).filter(
                    User.email == user_data['email']
                ).first()
                
                if not user:
                    # Neuen Benutzer erstellen
                    user = User(
                        username=user_data['username'],
                        email=user_data['email'],
                        name=user_data['name'],
                        is_admin=False,
                        oauth_provider=provider,
                        oauth_id=str(user_data['id'])
                    )
                    # Zufälliges Passwort setzen (wird nicht verwendet)
                    import secrets
                    user.set_password(secrets.token_urlsafe(32))
                    db_session.add(user)
                    db_session.commit()
                    auth_logger.info(f"Neuer OAuth-Benutzer erstellt: {user.username} via {provider}")
                else:
                    # Bestehenden Benutzer aktualisieren
                    user.oauth_provider = provider
                    user.oauth_id = str(user_data['id'])
                    user.name = user_data['name']
                    user.updated_at = datetime.now()
                    db_session.commit()
                    auth_logger.info(f"OAuth-Benutzer aktualisiert: {user.username} via {provider}")
                
                # Update last login timestamp
                user.update_last_login()
                db_session.commit()
                
                login_user(user, remember=True)
                
                # Session-State löschen
                session.pop('oauth_state', None)
                
                response_data = {
                    "success": True,
                    "user": {
                        "id": user.id,
                        "username": user.username,
                        "name": user.name,
                        "email": user.email,
                        "is_admin": user.is_admin
                    },
                    "redirect_url": url_for("index")
                }
                
                db_session.close()
                return jsonify(response_data)
                
            except Exception as e:
                db_session.rollback()
                db_session.close()
                auth_logger.error(f"Datenbankfehler bei OAuth-Callback: {str(e)}")
                return jsonify({
                    "error": "Datenbankfehler bei der Benutzeranmeldung",
                    "redirect_url": url_for("login")
                }), 500
        
        elif request.method == "POST":
            # POST-Anfragen für manuelle Token-Übermittlung
            data = request.get_json()
            if not data:
                return jsonify({"error": "Keine Daten erhalten"}), 400
            
            access_token = data.get('access_token')
            provider = data.get('provider', 'github')
            
            if not access_token:
                return jsonify({"error": "Kein Access Token erhalten"}), 400
            
            # Benutzerdaten mit Access Token abrufen
            if provider == 'github':
                user_data = get_github_user_data(access_token)
            else:
                return jsonify({"error": "Unbekannter OAuth-Provider"}), 400
            
            if not user_data:
                return jsonify({"error": "Fehler beim Abrufen der Benutzerdaten"}), 400
            
            # Benutzer verarbeiten (gleiche Logik wie bei GET)
            db_session = get_db_session()
            try:
                user = db_session.query(User).filter(
                    User.email == user_data['email']
                ).first()
                
                if not user:
                    user = User(
                        username=user_data['username'],
                        email=user_data['email'],
                        name=user_data['name'],
                        is_admin=False,
                        oauth_provider=provider,
                        oauth_id=str(user_data['id'])
                    )
                    import secrets
                    user.set_password(secrets.token_urlsafe(32))
                    db_session.add(user)
                    db_session.commit()
                    auth_logger.info(f"Neuer OAuth-Benutzer erstellt: {user.username} via {provider}")
                else:
                    user.oauth_provider = provider
                    user.oauth_id = str(user_data['id'])
                    user.name = user_data['name']
                    user.updated_at = datetime.now()
                    db_session.commit()
                    auth_logger.info(f"OAuth-Benutzer aktualisiert: {user.username} via {provider}")
                
                # Update last login timestamp
                user.update_last_login()
                db_session.commit()
                
                login_user(user, remember=True)
                
                response_data = {
                    "success": True,
                    "user": {
                        "id": user.id,
                        "username": user.username,
                        "name": user.name,
                        "email": user.email,
                        "is_admin": user.is_admin
                    },
                    "redirect_url": url_for("index")
                }
                
                db_session.close()
                return jsonify(response_data)
                
            except Exception as e:
                db_session.rollback()
                db_session.close()
                auth_logger.error(f"Datenbankfehler bei OAuth-Callback: {str(e)}")
                return jsonify({
                    "error": "Datenbankfehler bei der Benutzeranmeldung",
                    "redirect_url": url_for("login")
                }), 500
        
    except Exception as e:
        auth_logger.error(f"Fehler im OAuth-Callback: {str(e)}")
        return jsonify({
            "error": "OAuth-Callback-Fehler",
            "redirect_url": url_for("login")
        }), 500

def handle_github_callback(code):
    """GitHub OAuth-Callback verarbeiten"""
    try:
        import requests
        
        # GitHub OAuth-Konfiguration (sollte aus Umgebungsvariablen kommen)
        client_id = "7c5d8bef1a5519ec1fdc"
        client_secret = "5f1e586204358fbd53cf5fb7d418b3f06ccab8fd"
        
        if not client_id or not client_secret:
            auth_logger.error("GitHub OAuth-Konfiguration fehlt")
            return None
        
        # Access Token anfordern
        token_url = "https://github.com/login/oauth/access_token"
        token_data = {
            'client_id': client_id,
            'client_secret': client_secret,
            'code': code
        }
        
        token_response = requests.post(
            token_url,
            data=token_data,
            headers={'Accept': 'application/json'},
            timeout=10
        )
        
        if token_response.status_code != 200:
            auth_logger.error(f"GitHub Token-Anfrage fehlgeschlagen: {token_response.status_code}")
            return None
        
        token_json = token_response.json()
        access_token = token_json.get('access_token')
        
        if not access_token:
            auth_logger.error("Kein Access Token von GitHub erhalten")
            return None
        
        return get_github_user_data(access_token)
        
    except Exception as e:
        auth_logger.error(f"Fehler bei GitHub OAuth-Callback: {str(e)}")
        return None

def get_github_user_data(access_token):
    """GitHub-Benutzerdaten mit Access Token abrufen"""
    try:
        import requests
        
        # Benutzerdaten von GitHub API abrufen
        user_url = "https://api.github.com/user"
        headers = {
            'Authorization': f'token {access_token}',
            'Accept': 'application/vnd.github.v3+json'
        }
        
        user_response = requests.get(user_url, headers=headers, timeout=10)
        
        if user_response.status_code != 200:
            auth_logger.error(f"GitHub User-API-Anfrage fehlgeschlagen: {user_response.status_code}")
            return None
        
        user_data = user_response.json()
        
        # E-Mail-Adresse separat abrufen (falls nicht öffentlich)
        email = user_data.get('email')
        if not email:
            email_url = "https://api.github.com/user/emails"
            email_response = requests.get(email_url, headers=headers, timeout=10)
            
            if email_response.status_code == 200:
                emails = email_response.json()
                # Primäre E-Mail-Adresse finden
                for email_obj in emails:
                    if email_obj.get('primary', False):
                        email = email_obj.get('email')
                        break
                
                # Fallback: Erste E-Mail-Adresse verwenden
                if not email and emails:
                    email = emails[0].get('email')
        
        if not email:
            auth_logger.error("Keine E-Mail-Adresse von GitHub erhalten")
            return None
        
        return {
            'id': user_data.get('id'),
            'username': user_data.get('login'),
            'name': user_data.get('name') or user_data.get('login'),
            'email': email
        }
        
    except Exception as e:
        auth_logger.error(f"Fehler beim Abrufen der GitHub-Benutzerdaten: {str(e)}")
        return None

# ===== BENUTZER-ROUTEN (ehemals user.py) =====

@app.route("/user/profile", methods=["GET"])
@login_required
def user_profile():
    """Profil-Seite anzeigen"""
    user_logger.info(f"Benutzer {current_user.username} hat seine Profilseite aufgerufen")
    return render_template("profile.html", user=current_user)

@app.route("/user/settings", methods=["GET"])
@login_required
def user_settings():
    """Einstellungen-Seite anzeigen"""
    user_logger.info(f"Benutzer {current_user.username} hat seine Einstellungsseite aufgerufen")
    return render_template("settings.html", user=current_user)

@app.route("/user/update-profile", methods=["POST"])
@login_required
def user_update_profile():
    """Benutzerprofilinformationen aktualisieren"""
    try:
        # Überprüfen, ob es sich um eine JSON-Anfrage handelt
        is_json_request = request.is_json or request.headers.get('Content-Type') == 'application/json'
        
        if is_json_request:
            data = request.get_json()
            name = data.get("name")
            email = data.get("email")
            department = data.get("department")
            position = data.get("position")
            phone = data.get("phone")
        else:
            name = request.form.get("name")
            email = request.form.get("email")
            department = request.form.get("department")
            position = request.form.get("position")
            phone = request.form.get("phone")
        
        db_session = get_db_session()
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if user:
            # Aktualisiere die Benutzerinformationen
            if name:
                user.name = name
            if email:
                user.email = email
            if department:
                user.department = department
            if position:
                user.position = position
            if phone:
                user.phone = phone
            
            user.updated_at = datetime.now()
            db_session.commit()
            user_logger.info(f"Benutzer {current_user.username} hat sein Profil aktualisiert")
            
            if is_json_request:
                return jsonify({
                    "success": True,
                    "message": "Profil erfolgreich aktualisiert"
                })
            else:
                flash("Profil erfolgreich aktualisiert", "success")
                return redirect(url_for("user_profile"))
        else:
            error = "Benutzer nicht gefunden."
            if is_json_request:
                return jsonify({"error": error}), 404
            else:
                flash(error, "error")
                return redirect(url_for("user_profile"))
                
    except Exception as e:
        error = f"Fehler beim Aktualisieren des Profils: {str(e)}"
        user_logger.error(error)
        if request.is_json:
            return jsonify({"error": error}), 500
        else:
            flash(error, "error")
            return redirect(url_for("user_profile"))
    finally:
        db_session.close()

@app.route("/user/api/update-settings", methods=["POST"])
@login_required
def user_api_update_settings():
    """API-Endpunkt für Einstellungen-Updates (JSON)"""
    return user_update_profile()

@app.route("/user/update-settings", methods=["POST"])
@login_required
def user_update_settings():
    """Benutzereinstellungen aktualisieren"""
    db_session = get_db_session()
    try:
        # Überprüfen, ob es sich um eine JSON-Anfrage handelt
        is_json_request = request.is_json or request.headers.get('Content-Type') == 'application/json'
        
        # Einstellungen aus der Anfrage extrahieren
        if is_json_request:
            data = request.get_json()
            if not data:
                return jsonify({"error": "Keine Daten empfangen"}), 400
            
            theme = data.get("theme", "system")
            reduced_motion = bool(data.get("reduced_motion", False))
            contrast = data.get("contrast", "normal")
            notifications = data.get("notifications", {})
            privacy = data.get("privacy", {})
        else:
            theme = request.form.get("theme", "system")
            reduced_motion = request.form.get("reduced_motion") == "on"
            contrast = request.form.get("contrast", "normal")
            notifications = {
                "new_jobs": request.form.get("notify_new_jobs") == "on",
                "job_updates": request.form.get("notify_job_updates") == "on",
                "system": request.form.get("notify_system") == "on",
                "email": request.form.get("notify_email") == "on"
            }
            privacy = {
                "activity_logs": request.form.get("activity_logs") == "on",
                "two_factor": request.form.get("two_factor") == "on",
                "auto_logout": int(request.form.get("auto_logout", "60"))
            }
        
        # Validierung der Eingaben
        valid_themes = ["light", "dark", "system"]
        if theme not in valid_themes:
            theme = "system"
        
        valid_contrasts = ["normal", "high"]
        if contrast not in valid_contrasts:
            contrast = "normal"
        
        # Benutzer aus der Datenbank laden
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if not user:
            error = "Benutzer nicht gefunden."
            if is_json_request:
                return jsonify({"error": error}), 404
            else:
                flash(error, "error")
                return redirect(url_for("user_settings"))
        
        # Einstellungen-Dictionary erstellen
        settings = {
            "theme": theme,
            "reduced_motion": reduced_motion,
            "contrast": contrast,
            "notifications": {
                "new_jobs": bool(notifications.get("new_jobs", True)),
                "job_updates": bool(notifications.get("job_updates", True)),
                "system": bool(notifications.get("system", True)),
                "email": bool(notifications.get("email", False))
            },
            "privacy": {
                "activity_logs": bool(privacy.get("activity_logs", True)),
                "two_factor": bool(privacy.get("two_factor", False)),
                "auto_logout": max(5, min(480, int(privacy.get("auto_logout", 60))))  # 5-480 Minuten
            },
            "last_updated": datetime.now().isoformat()
        }
        
        # Prüfen, ob User-Tabelle eine settings-Spalte hat
        if hasattr(user, 'settings'):
            # Einstellungen in der Datenbank speichern
            import json
            user.settings = json.dumps(settings)
        else:
            # Fallback: In Session speichern (temporär)
            session['user_settings'] = settings
        
        user.updated_at = datetime.now()
        db_session.commit()
        
        user_logger.info(f"Benutzer {current_user.username} hat seine Einstellungen aktualisiert")
        
        if is_json_request:
            return jsonify({
                "success": True,
                "message": "Einstellungen erfolgreich aktualisiert",
                "settings": settings
            })
        else:
            flash("Einstellungen erfolgreich aktualisiert", "success")
            return redirect(url_for("user_settings"))
                
    except ValueError as e:
        error = f"Ungültige Eingabedaten: {str(e)}"
        user_logger.warning(f"Ungültige Einstellungsdaten von Benutzer {current_user.username}: {str(e)}")
        if is_json_request:
            return jsonify({"error": error}), 400
        else:
            flash(error, "error")
            return redirect(url_for("user_settings"))
    except Exception as e:
        db_session.rollback()
        error = f"Fehler beim Aktualisieren der Einstellungen: {str(e)}"
        user_logger.error(f"Fehler beim Aktualisieren der Einstellungen für Benutzer {current_user.username}: {str(e)}")
        if is_json_request:
            return jsonify({"error": "Interner Serverfehler"}), 500
        else:
            flash("Fehler beim Speichern der Einstellungen", "error")
            return redirect(url_for("user_settings"))
    finally:
        db_session.close()

@app.route("/api/user/settings", methods=["GET"])
@login_required
def get_user_settings():
    """Holt die aktuellen Benutzereinstellungen"""
    try:
        # Einstellungen aus Session oder Datenbank laden
        user_settings = session.get('user_settings', {})
        
        # Standard-Einstellungen falls keine vorhanden
        default_settings = {
            "theme": "system",
            "reduced_motion": False,
            "contrast": "normal",
            "notifications": {
                "new_jobs": True,
                "job_updates": True,
                "system": True,
                "email": False
            },
            "privacy": {
                "activity_logs": True,
                "two_factor": False,
                "auto_logout": 60
            }
        }
        
        # Merge mit Standard-Einstellungen
        settings = {**default_settings, **user_settings}
        
        return jsonify({
            "success": True,
            "settings": settings
        })
        
    except Exception as e:
        user_logger.error(f"Fehler beim Laden der Benutzereinstellungen: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden der Einstellungen"
        }), 500

@app.route("/user/change-password", methods=["POST"])
@login_required
def user_change_password():
    """Benutzerpasswort ändern"""
    try:
        # Überprüfen, ob es sich um eine JSON-Anfrage handelt
        is_json_request = request.is_json or request.headers.get('Content-Type') == 'application/json'
        
        if is_json_request:
            data = request.get_json()
            current_password = data.get("current_password")
            new_password = data.get("new_password")
            confirm_password = data.get("confirm_password")
        else:
            current_password = request.form.get("current_password")
            new_password = request.form.get("new_password")
            confirm_password = request.form.get("confirm_password")
        
        # Prüfen, ob alle Felder ausgefüllt sind
        if not current_password or not new_password or not confirm_password:
            error = "Alle Passwortfelder müssen ausgefüllt sein."
            if is_json_request:
                return jsonify({"error": error}), 400
            else:
                flash(error, "error")
                return redirect(url_for("user_profile"))
        
        # Prüfen, ob das neue Passwort und die Bestätigung übereinstimmen
        if new_password != confirm_password:
            error = "Das neue Passwort und die Bestätigung stimmen nicht überein."
            if is_json_request:
                return jsonify({"error": error}), 400
            else:
                flash(error, "error")
                return redirect(url_for("user_profile"))
        
        db_session = get_db_session()
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if user and user.check_password(current_password):
            # Passwort aktualisieren
            user.set_password(new_password)
            user.updated_at = datetime.now()
            db_session.commit()
            
            user_logger.info(f"Benutzer {current_user.username} hat sein Passwort geändert")
            
            if is_json_request:
                return jsonify({
                    "success": True,
                    "message": "Passwort erfolgreich geändert"
                })
            else:
                flash("Passwort erfolgreich geändert", "success")
                return redirect(url_for("user_profile"))
        else:
            error = "Das aktuelle Passwort ist nicht korrekt."
            if is_json_request:
                return jsonify({"error": error}), 401
            else:
                flash(error, "error")
                return redirect(url_for("user_profile"))
                
    except Exception as e:
        error = f"Fehler beim Ändern des Passworts: {str(e)}"
        user_logger.error(error)
        if request.is_json:
            return jsonify({"error": error}), 500
        else:
            flash(error, "error")
            return redirect(url_for("user_profile"))
    finally:
        db_session.close()

@app.route("/user/export", methods=["GET"])
@login_required
def user_export_data():
    """Exportiert alle Benutzerdaten als JSON für DSGVO-Konformität"""
    try:
        db_session = get_db_session()
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if not user:
            db_session.close()
            return jsonify({"error": "Benutzer nicht gefunden"}), 404
        
        # Benutzerdaten abrufen
        user_data = user.to_dict()
        
        # Jobs des Benutzers abrufen
        jobs = db_session.query(Job).filter(Job.user_id == user.id).all()
        user_data["jobs"] = [job.to_dict() for job in jobs]
        
        # Aktivitäten und Einstellungen hinzufügen
        user_data["settings"] = session.get('user_settings', {})
        
        # Persönliche Statistiken
        user_data["statistics"] = {
            "total_jobs": len(jobs),
            "completed_jobs": len([j for j in jobs if j.status == "finished"]),
            "failed_jobs": len([j for j in jobs if j.status == "failed"]),
            "account_created": user.created_at.isoformat() if user.created_at else None,
            "last_login": user.last_login.isoformat() if user.last_login else None
        }
        
        db_session.close()
        
        # Daten als JSON-Datei zum Download anbieten
        response = make_response(json.dumps(user_data, indent=4))
        response.headers["Content-Disposition"] = f"attachment; filename=user_data_{user.username}.json"
        response.headers["Content-Type"] = "application/json"
        
        user_logger.info(f"Benutzer {current_user.username} hat seine Daten exportiert")
        return response
        
    except Exception as e:
        error = f"Fehler beim Exportieren der Benutzerdaten: {str(e)}"
        user_logger.error(error)
        return jsonify({"error": error}), 500

@app.route("/user/profile", methods=["PUT"])
@login_required
def user_update_profile_api():
    """API-Endpunkt zum Aktualisieren des Benutzerprofils"""
    try:
        if not request.is_json:
            return jsonify({"error": "Anfrage muss im JSON-Format sein"}), 400
            
        data = request.get_json()
        db_session = get_db_session()
        user = db_session.query(User).filter(User.id == int(current_user.id)).first()
        
        if not user:
            db_session.close()
            return jsonify({"error": "Benutzer nicht gefunden"}), 404
        
        # Aktualisiere nur die bereitgestellten Felder
        if "name" in data:
            user.name = data["name"]
        if "email" in data:
            user.email = data["email"]
        if "department" in data:
            user.department = data["department"]
        if "position" in data:
            user.position = data["position"]
        if "phone" in data:
            user.phone = data["phone"]
        if "bio" in data:
            user.bio = data["bio"]
        
        user.updated_at = datetime.now()
        db_session.commit()
        
        # Aktualisierte Benutzerdaten zurückgeben
        user_data = user.to_dict()
        db_session.close()
        
        user_logger.info(f"Benutzer {current_user.username} hat sein Profil über die API aktualisiert")
        return jsonify({
            "success": True, 
            "message": "Profil erfolgreich aktualisiert",
            "user": user_data
        })
        
    except Exception as e:
        error = f"Fehler beim Aktualisieren des Profils: {str(e)}"
        user_logger.error(error)
        return jsonify({"error": error}), 500

# ===== KIOSK-KONTROLL-ROUTEN (ehemals kiosk_control.py) =====

@app.route('/api/kiosk/status', methods=['GET'])
def kiosk_get_status():
    """Kiosk-Status abrufen."""
    try:
        # Prüfen ob Kiosk-Modus aktiv ist
        kiosk_active = os.path.exists('/tmp/kiosk_active')
        
        return jsonify({
            "active": kiosk_active,
            "message": "Kiosk-Status erfolgreich abgerufen"
        })
    except Exception as e:
        kiosk_logger.error(f"Fehler beim Abrufen des Kiosk-Status: {str(e)}")
        return jsonify({"error": "Fehler beim Abrufen des Status"}), 500

@app.route('/api/kiosk/deactivate', methods=['POST'])
def kiosk_deactivate():
    """Kiosk-Modus mit Passwort deaktivieren."""
    try:
        data = request.get_json()
        if not data or 'password' not in data:
            return jsonify({"error": "Passwort erforderlich"}), 400
        
        password = data['password']
        
        # Passwort überprüfen
        if not check_password_hash(KIOSK_PASSWORD_HASH, password):
            kiosk_logger.warning(f"Fehlgeschlagener Kiosk-Deaktivierungsversuch von IP: {request.remote_addr}")
            return jsonify({"error": "Ungültiges Passwort"}), 401
        
        # Kiosk deaktivieren
        try:
            # Kiosk-Service stoppen
            subprocess.run(['sudo', 'systemctl', 'stop', 'myp-kiosk'], check=True)
            subprocess.run(['sudo', 'systemctl', 'disable', 'myp-kiosk'], check=True)
            
            # Kiosk-Marker entfernen
            if os.path.exists('/tmp/kiosk_active'):
                os.remove('/tmp/kiosk_active')
            
            # Normale Desktop-Umgebung wiederherstellen
            subprocess.run(['sudo', 'systemctl', 'set-default', 'graphical.target'], check=True)
            
            kiosk_logger.info(f"Kiosk-Modus erfolgreich deaktiviert von IP: {request.remote_addr}")
            
            return jsonify({
                "success": True,
                "message": "Kiosk-Modus erfolgreich deaktiviert. System wird neu gestartet."
            })
            
        except subprocess.CalledProcessError as e:
            kiosk_logger.error(f"Fehler beim Deaktivieren des Kiosk-Modus: {str(e)}")
            return jsonify({"error": "Fehler beim Deaktivieren des Kiosk-Modus"}), 500
            
    except Exception as e:
        kiosk_logger.error(f"Unerwarteter Fehler bei Kiosk-Deaktivierung: {str(e)}")
        return jsonify({"error": "Unerwarteter Fehler"}), 500
@app.route('/api/kiosk/activate', methods=['POST'])
@login_required
def kiosk_activate():
    """Kiosk-Modus aktivieren (nur für Admins)."""
    try:
        # Admin-Authentifizierung prüfen
        if not current_user.is_admin:
            kiosk_logger.warning(f"Nicht-Admin-Benutzer {current_user.username} versuchte Kiosk-Aktivierung")
            return jsonify({"error": "Nur Administratoren können den Kiosk-Modus aktivieren"}), 403
        
        # Kiosk aktivieren
        try:
            # Kiosk-Marker setzen
            with open('/tmp/kiosk_active', 'w') as f:
                f.write('1')
            
            # Kiosk-Service aktivieren
            subprocess.run(['sudo', 'systemctl', 'enable', 'myp-kiosk'], check=True)
            subprocess.run(['sudo', 'systemctl', 'start', 'myp-kiosk'], check=True)
            
            kiosk_logger.info(f"Kiosk-Modus erfolgreich aktiviert von Admin {current_user.username} (IP: {request.remote_addr})")
            
            return jsonify({
                "success": True,
                "message": "Kiosk-Modus erfolgreich aktiviert"
            })
            
        except subprocess.CalledProcessError as e:
            kiosk_logger.error(f"Fehler beim Aktivieren des Kiosk-Modus: {str(e)}")
            return jsonify({"error": "Fehler beim Aktivieren des Kiosk-Modus"}), 500
            
    except Exception as e:
        kiosk_logger.error(f"Unerwarteter Fehler bei Kiosk-Aktivierung: {str(e)}")
        return jsonify({"error": "Unerwarteter Fehler"}), 500

@app.route('/api/kiosk/restart', methods=['POST'])
def kiosk_restart_system():
    """System neu starten (nur nach Kiosk-Deaktivierung)."""
    try:
        data = request.get_json()
        if not data or 'password' not in data:
            return jsonify({"error": "Passwort erforderlich"}), 400
        
        password = data['password']
        
        # Passwort überprüfen
        if not check_password_hash(KIOSK_PASSWORD_HASH, password):
            kiosk_logger.warning(f"Fehlgeschlagener Neustart-Versuch von IP: {request.remote_addr}")
            return jsonify({"error": "Ungültiges Passwort"}), 401
        
        kiosk_logger.info(f"System-Neustart initiiert von IP: {request.remote_addr}")
        
        # System nach kurzer Verzögerung neu starten
        subprocess.Popen(['sudo', 'shutdown', '-r', '+1'])
        
        return jsonify({
            "success": True,
            "message": "System wird in 1 Minute neu gestartet"
        })
        
    except Exception as e:
        kiosk_logger.error(f"Fehler beim System-Neustart: {str(e)}")
        return jsonify({"error": "Fehler beim Neustart"}), 500

# ===== HILFSFUNKTIONEN =====

@measure_execution_time(logger=printers_logger, task_name="Drucker-Status-Prüfung")
def check_printer_status(ip_address: str, timeout: int = 7) -> Tuple[str, bool]:
    """
    Überprüft den Status eines Druckers über TP-Link Tapo P110-Steckdosenabfrage.
    
    Args:
        ip_address: IP-Adresse der Drucker-Steckdose
        timeout: Timeout in Sekunden (Standard: 7)
        
    Returns:
        Tuple[str, bool]: (Status, Aktiv) - Status ist "online" oder "offline", Aktiv ist True/False
    """
    if not ip_address or ip_address.strip() == "":
        printers_logger.debug(f"Keine IP-Adresse angegeben")
        return "offline", False
    
    try:
        # IP-Adresse validieren
        import ipaddress
        try:
            ipaddress.ip_address(ip_address.strip())
        except ValueError:
            printers_logger.debug(f"Ungültige IP-Adresse: {ip_address}")
            return "offline", False
        
        # Importiere PyP100 für Tapo-Unterstützung
        try:
            from PyP100 import PyP110
        except ImportError:
            printers_logger.error("⚠️ PyP100-Modul nicht verfügbar - kann Tapo-Steckdosen nicht abfragen")
            return "offline", False
        
        # Verwende IMMER die globalen hardkodierten Tapo-Anmeldedaten
        username = TAPO_USERNAME
        password = TAPO_PASSWORD
        
        printers_logger.debug(f"🔌 Teste Tapo-Steckdose {ip_address} mit hardkodierten Anmeldedaten")
        
        # TP-Link Tapo P110 Verbindung herstellen
        p110 = PyP110.P110(ip_address.strip(), username, password)
        p110.handshake()  # Authentifizierung
        p110.login()      # Login
        
        # Geräteinformationen abrufen
        device_info = p110.getDeviceInfo()
        device_on = device_info.get('device_on', False)
        
        if device_on:
            printers_logger.debug(f"✅ Drucker {ip_address}: ONLINE (Steckdose eingeschaltet)")
            return "online", True
        else:
            printers_logger.debug(f"🔄 Drucker {ip_address}: STANDBY (Steckdose ausgeschaltet)")
            return "standby", False
            
    except Exception as e:
        printers_logger.debug(f"❌ Fehler beim Tapo-Status-Check für {ip_address}: {str(e)}")
        return "offline", False

@measure_execution_time(logger=printers_logger, task_name="Mehrere-Drucker-Status-Prüfung")
def check_multiple_printers_status(printers: List[Dict], timeout: int = 7) -> Dict[int, Tuple[str, bool]]:
    """
    Überprüft den Status mehrerer Drucker parallel.
    
    Args:
        printers: Liste der zu prüfenden Drucker
        timeout: Timeout für jeden einzelnen Drucker
    
    Returns:
        Dict[int, Tuple[str, bool]]: Dictionary mit Drucker-ID als Key und (Status, Aktiv) als Value
    """
    results = {}
    
    # Wenn keine Drucker vorhanden sind, gebe leeres Dict zurück
    if not printers:
        printers_logger.info("ℹ️ Keine Drucker zum Status-Check gefunden")
        return results
    
    printers_logger.info(f"🔍 Prüfe Status von {len(printers)} Druckern parallel...")
    
    # Parallel-Ausführung mit ThreadPoolExecutor
    # Sicherstellen, dass max_workers mindestens 1 ist
    max_workers = min(max(len(printers), 1), 10)
    
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        # Futures für alle Drucker erstellen
        future_to_printer = {
            executor.submit(check_printer_status, printer.get('ip_address'), timeout): printer
            for printer in printers
        }
        
        # Ergebnisse sammeln
        for future in as_completed(future_to_printer, timeout=timeout + 2):
            printer = future_to_printer[future]
            try:
                status, active = future.result()
                results[printer['id']] = (status, active)
                printers_logger.info(f"Drucker {printer['name']} ({printer.get('ip_address')}): {status}")
            except Exception as e:
                printers_logger.error(f"Fehler bei Status-Check für Drucker {printer['name']}: {str(e)}")
                results[printer['id']] = ("offline", False)
    
    printers_logger.info(f"✅ Status-Check abgeschlossen für {len(results)} Drucker")
    
    return results

# ===== UI-ROUTEN =====

@app.route("/")
def index():
    if current_user.is_authenticated:
        return render_template("index.html")
    return redirect(url_for("login"))

@app.route("/dashboard")
@login_required
def dashboard():
    return render_template("dashboard.html")

@app.route("/profile")
@login_required
def profile_redirect():
    """Leitet zur neuen Profilseite im User-Blueprint weiter."""
    return redirect(url_for("user_profile"))

@app.route("/profil")
@login_required
def profil_redirect():
    """Leitet zur neuen Profilseite im User-Blueprint weiter (deutsche URL)."""
    return redirect(url_for("user_profile"))

@app.route("/settings")
@login_required
def settings_redirect():
    """Leitet zur neuen Einstellungsseite im User-Blueprint weiter."""
    return redirect(url_for("user_settings"))

@app.route("/einstellungen")
@login_required
def einstellungen_redirect():
    """Leitet zur neuen Einstellungsseite im User-Blueprint weiter (deutsche URL)."""
    return redirect(url_for("user_settings"))

@app.route("/admin")
@login_required
def admin():
    """Leitet zur neuen Admin-Dashboard-Route weiter."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    return redirect(url_for("admin_page"))

@app.route("/demo")
@login_required
def components_demo():
    """Demo-Seite für UI-Komponenten"""
    return render_template("components_demo.html")

@app.route("/printers")
@login_required
def printers_page():
    """Zeigt die Übersichtsseite für Drucker an."""
    return render_template("printers.html")

@app.route("/jobs")
@login_required
def jobs_page():
    """Zeigt die Übersichtsseite für Druckaufträge an."""
    return render_template("jobs.html")

@app.route("/jobs/new")
@login_required
def new_job_page():
    """Zeigt die Seite zum Erstellen neuer Druckaufträge an."""
    return render_template("jobs.html")

@app.route("/stats")
@login_required
def stats_page():
    """Zeigt die Statistik-Seite an."""
    return render_template("stats.html")

@app.route("/admin-dashboard")
@login_required
def admin_page():
    """Zeigt die Administrationsseite an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    # Aktives Tab aus der URL auslesen oder Default-Wert verwenden
    active_tab = request.args.get('tab', 'users')
    
    # Daten für das Admin-Panel direkt beim Laden vorbereiten
    stats = {}
    users = []
    printers = []
    scheduler_status = {"running": False, "message": "Nicht verfügbar"}
    system_info = {"cpu": 0, "memory": 0, "disk": 0}
    logs = []
    
    db_session = get_db_session()
    
    try:
        # Statistiken laden
        from sqlalchemy.orm import joinedload
        
        # Benutzeranzahl
        stats["total_users"] = db_session.query(User).count()
        
        # Druckeranzahl und Online-Status
        all_printers = db_session.query(Printer).all()
        stats["total_printers"] = len(all_printers)
        stats["online_printers"] = len([p for p in all_printers if p.status == "online"])
        
        # Aktive Jobs und Warteschlange
        stats["active_jobs"] = db_session.query(Job).filter(
            Job.status.in_(["printing", "running"])
        ).count()
        
        stats["queued_jobs"] = db_session.query(Job).filter(
            Job.status == "scheduled"
        ).count()
        
        # Erfolgsrate
        total_jobs = db_session.query(Job).filter(
            Job.status.in_(["completed", "failed", "cancelled"])
        ).count()
        
        successful_jobs = db_session.query(Job).filter(
            Job.status == "completed"
        ).count()
        
        if total_jobs > 0:
            stats["success_rate"] = int((successful_jobs / total_jobs) * 100)
        else:
            stats["success_rate"] = 0
        
        # Benutzer laden
        if active_tab == 'users':
            users = db_session.query(User).all()
            users = [user.to_dict() for user in users]
        
        # Drucker laden
        if active_tab == 'printers':
            printers = db_session.query(Printer).all()
            printers = [printer.to_dict() for printer in printers]
        
        # Scheduler-Status laden
        if active_tab == 'scheduler':
            try:
                from utils.scheduler import scheduler_is_running
                is_running = scheduler_is_running()
                scheduler_status = {
                    "running": is_running,
                    "message": "Der Scheduler läuft" if is_running else "Der Scheduler ist gestoppt"
                }
            except (ImportError, AttributeError):
                scheduler_status = {
                    "running": False,
                    "message": "Scheduler-Status nicht verfügbar"
                }
        
        # System-Informationen laden
        if active_tab == 'system':
            import os
            import psutil
            
            # CPU und Memory
            cpu_percent = psutil.cpu_percent(interval=1)
            memory = psutil.virtual_memory()
            disk = psutil.disk_usage('/')
            
            # Uptime
            boot_time = psutil.boot_time()
            uptime_seconds = time.time() - boot_time
            uptime_days = int(uptime_seconds // 86400)
            uptime_hours = int((uptime_seconds % 86400) // 3600)
            uptime_minutes = int((uptime_seconds % 3600) // 60)
            
            # Datenbank-Status
            db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'database', 'myp.db')
            db_size = 0
            if os.path.exists(db_path):
                db_size = os.path.getsize(db_path) / (1024 * 1024)  # MB
            
            # Scheduler-Status
            scheduler_running = False
            scheduler_jobs = 0
            try:
                from utils.job_scheduler import scheduler
                scheduler_running = scheduler.running
                if hasattr(scheduler, 'get_jobs'):
                    scheduler_jobs = len(scheduler.get_jobs())
            except:
                pass
            
            # Nächster Job
            next_job = db_session.query(Job).filter(
                Job.status == "scheduled"
            ).order_by(Job.created_at.asc()).first()
            
            next_job_time = "Keine geplanten Jobs"
            if next_job:
                next_job_time = next_job.created_at.strftime("%d.%m.%Y %H:%M")
            
            system_info = {
                "cpu_usage": round(cpu_percent, 1),
                "memory_usage": round(memory.percent, 1),
                "disk_usage": round((disk.used / disk.total) * 100, 1),
                "uptime": f"{uptime_days}d {uptime_hours}h {uptime_minutes}m",
                "db_size": f"{db_size:.1f} MB",
                "db_connections": "Aktiv",
                "scheduler_running": scheduler_running,
                "scheduler_jobs": scheduler_jobs,
                "next_job": next_job_time
            }
        
        # Logs laden
        if active_tab == 'logs':
            import os
            log_level = request.args.get('log_level', 'all')
            log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logs')
            
            # Logeinträge sammeln
            app_logs = []
            for category in ['app', 'auth', 'jobs', 'printers', 'scheduler', 'errors']:
                log_file = os.path.join(log_dir, category, f'{category}.log')
                if os.path.exists(log_file):
                    with open(log_file, 'r') as f:
                        for line in f.readlines()[-100:]:  # Nur die letzten 100 Zeilen pro Datei
                            if log_level != 'all':
                                if log_level.upper() not in line:
                                    continue
                            app_logs.append({
                                'timestamp': line.split(' - ')[0] if ' - ' in line else '',
                                'level': line.split(' - ')[1].split(' - ')[0] if ' - ' in line and len(line.split(' - ')) > 2 else 'INFO',
                                'category': category,
                                'message': ' - '.join(line.split(' - ')[2:]) if ' - ' in line and len(line.split(' - ')) > 2 else line
                            })
            
            # Nach Zeitstempel sortieren (neueste zuerst)
            logs = sorted(app_logs, key=lambda x: x['timestamp'] if x['timestamp'] else '', reverse=True)[:100]

    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Daten: {str(e)}")
    finally:
        db_session.close()
        
    return render_template(
        "admin.html",
        active_tab=active_tab,
        stats=stats,
        users=users,
        printers=printers,
        scheduler_status=scheduler_status,
        system_info=system_info,
        logs=logs
    )

# ===== ERROR MONITORING SYSTEM =====

@app.route("/api/admin/system-health", methods=['GET'])
@login_required
def api_admin_system_health():
    """API-Endpunkt für System-Gesundheitscheck."""
    if not current_user.is_admin:
        return jsonify({"error": "Berechtigung verweigert"}), 403
    
    db_session = get_db_session()
    critical_errors = []
    warnings = []
    
    try:
        # 1. Datenbank-Schema-Integrität prüfen
        try:
            # Test verschiedene kritische Tabellen und Spalten
            db_session.execute(text("SELECT COUNT(*) FROM guest_requests WHERE duration_minutes IS NOT NULL"))
            schema_integrity = "OK"
        except Exception as e:
            critical_errors.append({
                "type": "database_schema",
                "message": f"Datenbank-Schema-Fehler: {str(e)}",
                "severity": "critical",
                "suggested_fix": "Datenbank-Migration ausführen",
                "timestamp": datetime.now().isoformat()
            })
            schema_integrity = "FEHLER"
        
        # 2. Prüfe kritische Spalten in wichtigen Tabellen
        schema_checks = [
            ("guest_requests", "duration_minutes"),
            ("guest_requests", "file_name"),
            ("guest_requests", "processed_by"),
            ("users", "updated_at"),
            ("jobs", "duration_minutes")
        ]
        
        missing_columns = []
        for table, column in schema_checks:
            try:
                db_session.execute(text(f"SELECT {column} FROM {table} LIMIT 1"))
            except Exception:
                missing_columns.append(f"{table}.{column}")
        
        if missing_columns:
            critical_errors.append({
                "type": "missing_columns",
                "message": f"Fehlende Datenbank-Spalten: {', '.join(missing_columns)}",
                "severity": "critical",
                "suggested_fix": "python utils/database_schema_migration.py ausführen",
                "timestamp": datetime.now().isoformat(),
                "details": missing_columns
            })
        
        # 3. Prüfe auf wiederkehrende Datenbankfehler in den Logs
        import os
        log_file = os.path.join("logs", "app", f"myp_app_{datetime.now().strftime('%Y_%m_%d')}.log")
        recent_db_errors = 0
        
        if os.path.exists(log_file):
            try:
                with open(log_file, 'r', encoding='utf-8') as f:
                    last_lines = f.readlines()[-100:]  # Letzte 100 Zeilen
                    for line in last_lines:
                        if "OperationalError" in line or "no such column" in line:
                            recent_db_errors += 1
            except Exception:
                pass
        
        if recent_db_errors > 5:
            critical_errors.append({
                "type": "frequent_db_errors",
                "message": f"{recent_db_errors} Datenbankfehler in letzter Zeit erkannt",
                "severity": "high",
                "suggested_fix": "System-Logs überprüfen und Migration ausführen",
                "timestamp": datetime.now().isoformat()
            })
        
        # 4. Prüfe Drucker-Konnektivität
        offline_printers = db_session.query(Printer).filter(
            Printer.status == "offline",
            Printer.active == True
        ).count()
        
        if offline_printers > 0:
            warnings.append({
                "type": "printer_offline",
                "message": f"{offline_printers} aktive Drucker sind offline",
                "severity": "warning",
                "suggested_fix": "Drucker-Status überprüfen",
                "timestamp": datetime.now().isoformat()
            })
        
        # 5. System-Performance Metriken
        import psutil
        cpu_usage = psutil.cpu_percent(interval=1)
        memory_usage = psutil.virtual_memory().percent
        disk_usage = psutil.disk_usage('/').percent
        
        if cpu_usage > 90:
            warnings.append({
                "type": "high_cpu",
                "message": f"Hohe CPU-Auslastung: {cpu_usage:.1f}%",
                "severity": "warning",
                "suggested_fix": "System-Ressourcen überprüfen",
                "timestamp": datetime.now().isoformat()
            })
        
        if memory_usage > 85:
            warnings.append({
                "type": "high_memory",
                "message": f"Hohe Speicher-Auslastung: {memory_usage:.1f}%",
                "severity": "warning",
                "suggested_fix": "Speicher-Verbrauch optimieren",
                "timestamp": datetime.now().isoformat()
            })
        
        # 6. Letzte Migration info
        try:
            backup_dir = os.path.join("database", "backups")
            if os.path.exists(backup_dir):
                backup_files = [f for f in os.listdir(backup_dir) if f.endswith('.backup')]
                if backup_files:
                    latest_backup = max(backup_files, key=lambda x: os.path.getctime(os.path.join(backup_dir, x)))
                    last_migration = latest_backup.replace('.backup', '').replace('myp.db.backup_', '')
                else:
                    last_migration = "Keine Backups gefunden"
            else:
                last_migration = "Backup-Verzeichnis nicht gefunden"
        except Exception:
            last_migration = "Unbekannt"
        
        return jsonify({
            "success": True,
            "health_status": "critical" if critical_errors else ("warning" if warnings else "healthy"),
            "critical_errors": critical_errors,
            "warnings": warnings,
            "schema_integrity": schema_integrity,
            "last_migration": last_migration,
            "recent_errors_count": recent_db_errors,
            "system_metrics": {
                "cpu_usage": cpu_usage,
                "memory_usage": memory_usage,
                "disk_usage": disk_usage
            },
            "timestamp": datetime.now().isoformat()
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim System-Gesundheitscheck: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim System-Gesundheitscheck",
            "critical_errors": [{
                "type": "system_check_failed",
                "message": f"System-Check fehlgeschlagen: {str(e)}",
                "severity": "critical",
                "suggested_fix": "System-Logs überprüfen",
                "timestamp": datetime.now().isoformat()
            }]
        }), 500
    finally:
        db_session.close()

@app.route("/api/admin/fix-errors", methods=['POST'])
@login_required 
@csrf.exempt
def api_admin_fix_errors():
    """API-Endpunkt um automatische Fehler-Reparatur auszuführen."""
    if not current_user.is_admin:
        return jsonify({"error": "Berechtigung verweigert"}), 403
    
    try:
        # Automatische Migration ausführen
        import subprocess
        import sys
        
        # Migration in separatem Prozess ausführen
        result = subprocess.run(
            [sys.executable, "utils/database_schema_migration.py"],
            cwd=os.path.dirname(os.path.abspath(__file__)),
            capture_output=True,
            text=True,
            timeout=60
        )
        
        if result.returncode == 0:
            app_logger.info(f"Automatische Migration erfolgreich ausgeführt von Admin {current_user.email}")
            return jsonify({
                "success": True,
                "message": "Automatische Reparatur erfolgreich durchgeführt",
                "details": result.stdout
            })
        else:
            app_logger.error(f"Automatische Migration fehlgeschlagen: {result.stderr}")
            return jsonify({
                "success": False,
                "error": "Automatische Reparatur fehlgeschlagen",
                "details": result.stderr
            }), 500
            
    except subprocess.TimeoutExpired:
        return jsonify({
            "success": False,
            "error": "Migration-Timeout - Vorgang dauerte zu lange"
        }), 500
    except Exception as e:
        app_logger.error(f"Fehler bei automatischer Reparatur: {str(e)}")
        return jsonify({
            "success": False,
            "error": f"Fehler bei automatischer Reparatur: {str(e)}"
        }), 500

# Direkter Zugriff auf Logout-Route (für Fallback)
@app.route("/logout", methods=["GET", "POST"])
def logout_redirect():
    """Leitet zur Blueprint-Logout-Route weiter."""
    return redirect(url_for("auth_logout"))

# ===== JOB-ROUTEN =====

@app.route("/api/jobs", methods=["GET"])
@login_required
def get_jobs():
    db_session = get_db_session()
    
    try:
        # Import joinedload for eager loading
        from sqlalchemy.orm import joinedload
        
        # Admin sieht alle Jobs, User nur eigene
        if current_user.is_admin:
            # Eagerly load the user and printer relationships to avoid detached instance errors
            jobs = db_session.query(Job).options(joinedload(Job.user), joinedload(Job.printer)).all()
        else:
            jobs = db_session.query(Job).options(joinedload(Job.user), joinedload(Job.printer)).filter(Job.user_id == int(current_user.id)).all()
        
        # Convert jobs to dictionaries before closing the session
        job_dicts = [job.to_dict() for job in jobs]
        
        db_session.close()
        
        return jsonify({
            "jobs": job_dicts
        })
    except Exception as e:
        jobs_logger.error(f"Fehler beim Abrufen von Jobs: {str(e)}")
        db_session.close()
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/jobs/<int:job_id>", methods=["GET"])
@login_required
@job_owner_required
def get_job(job_id):
    db_session = get_db_session()
    
    try:
        from sqlalchemy.orm import joinedload
        # Eagerly load the user and printer relationships
        job = db_session.query(Job).options(joinedload(Job.user), joinedload(Job.printer)).filter(Job.id == job_id).first()
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
            
        # Convert to dict before closing session
        job_dict = job.to_dict()
        db_session.close()
        
        return jsonify(job_dict)
    except Exception as e:
        jobs_logger.error(f"Fehler beim Abrufen des Jobs {job_id}: {str(e)}")
        db_session.close()
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/jobs/check-waiting', methods=['POST'])
@login_required
def check_waiting_jobs():
    """Überprüft wartende Jobs und startet sie, wenn Drucker online gehen."""
    try:
        db_session = get_db_session()
        
        # Alle wartenden Jobs finden
        waiting_jobs = db_session.query(Job).filter(
            Job.status == "waiting_for_printer"
        ).all()
        
        if not waiting_jobs:
            db_session.close()
            return jsonify({
                "message": "Keine wartenden Jobs gefunden",
                "updated_jobs": []
            })
        
        updated_jobs = []
        
        for job in waiting_jobs:
            # Drucker-Status prüfen
            printer = db_session.query(Printer).get(job.printer_id)
            if printer and printer.plug_ip:
                status, active = check_printer_status(printer.plug_ip)
                
                if status == "online" and active:
                    # Drucker ist jetzt online - Job kann geplant werden
                    job.status = "scheduled"
                    updated_jobs.append({
                        "id": job.id,
                        "name": job.name,
                        "printer_name": printer.name,
                        "status": "scheduled"
                    })
                    
                    jobs_logger.info(f"Job {job.id} von 'waiting_for_printer' zu 'scheduled' geändert - Drucker {printer.name} ist online")
        
        if updated_jobs:
            db_session.commit()
            
        db_session.close()
        
        return jsonify({
            "message": f"{len(updated_jobs)} Jobs aktualisiert",
            "updated_jobs": updated_jobs
        })
        
    except Exception as e:
        jobs_logger.error(f"Fehler beim Überprüfen wartender Jobs: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/jobs/active', methods=['GET'])
@login_required
def get_active_jobs():
    """
    Gibt alle aktiven Jobs zurück.
    """
    try:
        db_session = get_db_session()
        from sqlalchemy.orm import joinedload
        
        active_jobs = db_session.query(Job).options(
            joinedload(Job.user), 
            joinedload(Job.printer)
        ).filter(
            Job.status.in_(["scheduled", "running"])
        ).all()
        
        result = []
        for job in active_jobs:
            job_dict = job.to_dict()
            # Aktuelle Restzeit berechnen
            if job.status == "running" and job.end_at:
                remaining_time = job.end_at - datetime.now()
                if remaining_time.total_seconds() > 0:
                    job_dict["remaining_minutes"] = int(remaining_time.total_seconds() / 60)
                else:
                    job_dict["remaining_minutes"] = 0
            
            result.append(job_dict)
        
        db_session.close()
        return jsonify({"jobs": result})
    except Exception as e:
        jobs_logger.error(f"Fehler beim Abrufen aktiver Jobs: {str(e)}")
        return jsonify({"error": "Interner Serverfehler", "details": str(e)}), 500

@app.route('/api/jobs', methods=['POST'])
@login_required
@measure_execution_time(logger=jobs_logger, task_name="API-Job-Erstellung")
def create_job():
    """
    Erstellt einen neuen Job mit dem Status "scheduled".
    
    Body: {
        "printer_id": int,
        "start_iso": str,  # ISO-Datum-String
        "duration_minutes": int
    }
    """
    try:
        data = request.json
        
        # Pflichtfelder prüfen
        required_fields = ["printer_id", "start_iso", "duration_minutes"]
        for field in required_fields:
            if field not in data:
                return jsonify({"error": f"Feld '{field}' fehlt"}), 400
        
        # Daten extrahieren und validieren
        printer_id = int(data["printer_id"])
        start_iso = data["start_iso"]
        duration_minutes = int(data["duration_minutes"])
        
        # Optional: Jobtitel und Dateipfad
        name = data.get("name", f"Druckjob vom {datetime.now().strftime('%d.%m.%Y')}")
        file_path = data.get("file_path")
        
        # Start-Zeit parsen
        try:
            start_at = datetime.fromisoformat(start_iso)
        except ValueError:
            return jsonify({"error": "Ungültiges Startdatum"}), 400
        
        # Dauer validieren
        if duration_minutes <= 0:
            return jsonify({"error": "Dauer muss größer als 0 sein"}), 400
        
        # End-Zeit berechnen
        end_at = start_at + timedelta(minutes=duration_minutes)
        
        db_session = get_db_session()
        
        # Prüfen, ob der Drucker existiert
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Prüfen, ob der Drucker online ist
        printer_status, printer_active = check_printer_status(printer.plug_ip if printer.plug_ip else "")
        
        # Status basierend auf Drucker-Verfügbarkeit setzen
        if printer_status == "online" and printer_active:
            job_status = "scheduled"
        else:
            job_status = "waiting_for_printer"
        
        # Neuen Job erstellen
        new_job = Job(
            name=name,
            printer_id=printer_id,
            user_id=current_user.id,
            owner_id=current_user.id,
            start_at=start_at,
            end_at=end_at,
            status=job_status,
            file_path=file_path,
            duration_minutes=duration_minutes
        )
        
        db_session.add(new_job)
        db_session.commit()
        
        # Job-Objekt für die Antwort serialisieren
        job_dict = new_job.to_dict()
        db_session.close()
        
        jobs_logger.info(f"Neuer Job {new_job.id} erstellt für Drucker {printer_id}, Start: {start_at}, Dauer: {duration_minutes} Minuten")
        return jsonify({"job": job_dict}), 201
    
    except Exception as e:
        jobs_logger.error(f"Fehler beim Erstellen eines Jobs: {str(e)}")
        return jsonify({"error": "Interner Serverfehler", "details": str(e)}), 500

@app.route('/api/jobs/<int:job_id>/extend', methods=['POST'])
@login_required
@job_owner_required
def extend_job(job_id):
    """
    Verlängert die Endzeit eines Jobs.
    
    Body: {
        "extra_minutes": int
    }
    """
    try:
        data = request.json
        
        # Prüfen, ob die erforderlichen Daten vorhanden sind
        if "extra_minutes" not in data:
            return jsonify({"error": "Feld 'extra_minutes' fehlt"}), 400
        
        extra_minutes = int(data["extra_minutes"])
        
        # Validieren
        if extra_minutes <= 0:
            return jsonify({"error": "Zusätzliche Minuten müssen größer als 0 sein"}), 400
        
        db_session = get_db_session()
        job = db_session.query(Job).get(job_id)
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
        
        # Prüfen, ob der Job verlängert werden kann
        if job.status not in ["scheduled", "running"]:
            db_session.close()
            return jsonify({"error": f"Job kann im Status '{job.status}' nicht verlängert werden"}), 400
        
        # Endzeit aktualisieren
        job.end_at = job.end_at + timedelta(minutes=extra_minutes)
        job.duration_minutes += extra_minutes
        
        db_session.commit()
        
        # Job-Objekt für die Antwort serialisieren
        job_dict = job.to_dict()
        db_session.close()
        
        jobs_logger.info(f"Job {job_id} um {extra_minutes} Minuten verlängert, neue Endzeit: {job.end_at}")
        return jsonify({"job": job_dict})
    
    except Exception as e:
        jobs_logger.error(f"Fehler beim Verlängern von Job {job_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler", "details": str(e)}), 500

@app.route('/api/jobs/<int:job_id>/finish', methods=['POST'])
@login_required
def finish_job(job_id):
    """
    Beendet einen Job manuell und schaltet die Steckdose aus.
    Nur für Administratoren erlaubt.
    """
    try:
        # Prüfen, ob der Benutzer Administrator ist
        if not current_user.is_admin:
            return jsonify({"error": "Nur Administratoren können Jobs manuell beenden"}), 403
        
        db_session = get_db_session()
        job = db_session.query(Job).options(joinedload(Job.printer)).get(job_id)
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
        
        # Prüfen, ob der Job beendet werden kann
        if job.status not in ["scheduled", "running"]:
            db_session.close()
            return jsonify({"error": f"Job kann im Status '{job.status}' nicht beendet werden"}), 400
        
        # Steckdose ausschalten
        from utils.job_scheduler import toggle_plug
        if not toggle_plug(job.printer_id, False):
            # Trotzdem weitermachen, aber Warnung loggen
            jobs_logger.warning(f"Steckdose für Job {job_id} konnte nicht ausgeschaltet werden")
        
        # Job als beendet markieren
        job.status = "finished"
        job.actual_end_time = datetime.now()
        
        db_session.commit()
        
        # Job-Objekt für die Antwort serialisieren
        job_dict = job.to_dict()
        db_session.close()
        
        jobs_logger.info(f"Job {job_id} manuell beendet durch Admin {current_user.id}")
        return jsonify({"job": job_dict})
    
    except Exception as e:
        jobs_logger.error(f"Fehler beim manuellen Beenden von Job {job_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler", "details": str(e)}), 500

# ===== DRUCKER-ROUTEN =====

@app.route("/api/printers", methods=["GET"])
@login_required
def get_printers():
    """Gibt alle Drucker zurück - OHNE Status-Check für schnelleres Laden."""
    db_session = get_db_session()
    
    try:
        # Windows-kompatible Timeout-Implementierung
        import threading
        import time
        
        printers = None
        timeout_occurred = False
        
        def fetch_printers():
            nonlocal printers, timeout_occurred
            try:
                printers = db_session.query(Printer).all()
            except Exception as e:
                printers_logger.error(f"Datenbankfehler beim Laden der Drucker: {str(e)}")
                timeout_occurred = True
        
        # Starte Datenbankabfrage in separatem Thread
        thread = threading.Thread(target=fetch_printers)
        thread.daemon = True
        thread.start()
        thread.join(timeout=5)  # 5 Sekunden Timeout
        
        if thread.is_alive() or timeout_occurred or printers is None:
            printers_logger.warning("Database timeout when fetching printers for basic loading")
            return jsonify({
                'error': 'Database timeout beim Laden der Drucker',
                'timeout': True,
                'printers': []
            }), 408
        
        # Drucker-Daten OHNE Status-Check zusammenstellen für schnelles Laden
        printer_data = []
        current_time = datetime.now()
        
        for printer in printers:
            printer_data.append({
                "id": printer.id,
                "name": printer.name,
                "model": printer.model or 'Unbekanntes Modell',
                "location": printer.location or 'Unbekannter Standort',
                "mac_address": printer.mac_address,
                "plug_ip": printer.plug_ip,
                "status": printer.status or "offline",  # Letzter bekannter Status
                "active": printer.active if hasattr(printer, 'active') else True,
                "ip_address": printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None),
                "created_at": printer.created_at.isoformat() if printer.created_at else current_time.isoformat(),
                "last_checked": printer.last_checked.isoformat() if hasattr(printer, 'last_checked') and printer.last_checked else None
            })
        
        db_session.close()
        
        printers_logger.info(f"Schnelles Laden abgeschlossen: {len(printer_data)} Drucker geladen (ohne Status-Check)")
        
        return jsonify({
            "printers": printer_data,
            "count": len(printer_data),
            "message": "Drucker erfolgreich geladen"
        })
        
    except Exception as e:
        db_session.rollback()
        db_session.close()
        printers_logger.error(f"Fehler beim Abrufen der Drucker: {str(e)}")
        return jsonify({
            "error": f"Fehler beim Laden der Drucker: {str(e)}",
            "printers": []
        }), 500

@app.route("/api/printers/status", methods=["GET"])
@login_required
@measure_execution_time(logger=printers_logger, task_name="API-Drucker-Status-Abfrage")
def get_printers_with_status():
    """Gibt alle Drucker MIT aktuellem Status-Check zurück - für Aktualisierung."""
    db_session = get_db_session()
    
    try:
        # Windows-kompatible Timeout-Implementierung
        import threading
        import time
        
        printers = None
        timeout_occurred = False
        
        def fetch_printers():
            nonlocal printers, timeout_occurred
            try:
                printers = db_session.query(Printer).all()
            except Exception as e:
                printers_logger.error(f"Datenbankfehler beim Status-Check: {str(e)}")
                timeout_occurred = True
        
        # Starte Datenbankabfrage in separatem Thread
        thread = threading.Thread(target=fetch_printers)
        thread.daemon = True
        thread.start()
        thread.join(timeout=8)  # 8 Sekunden Timeout für Status-Check
        
        if thread.is_alive() or timeout_occurred or printers is None:
            printers_logger.warning("Database timeout when fetching printers for status check")
            return jsonify({
                'error': 'Database timeout beim Status-Check der Drucker',
                'timeout': True
            }), 408
        
        # Drucker-Daten für Status-Check vorbereiten
        printer_data = []
        for printer in printers:
            # Verwende plug_ip als primäre IP-Adresse, fallback auf ip_address
            ip_to_check = printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None)
            printer_data.append({
                'id': printer.id,
                'name': printer.name,
                'ip_address': ip_to_check,
                'location': printer.location,
                'model': printer.model
            })
        
        # Status aller Drucker parallel überprüfen mit 7-Sekunden-Timeout
        printers_logger.info(f"Starte Status-Check für {len(printer_data)} Drucker mit 7-Sekunden-Timeout")
        
        # Fallback: Wenn keine IP-Adressen vorhanden sind, alle als offline markieren
        if not any(p['ip_address'] for p in printer_data):
            printers_logger.warning("Keine IP-Adressen für Drucker gefunden - alle als offline markiert")
            status_results = {p['id']: ("offline", False) for p in printer_data}
        else:
            try:
                status_results = check_multiple_printers_status(printer_data, timeout=7)
            except Exception as e:
                printers_logger.error(f"Fehler beim Status-Check: {str(e)}")
                # Fallback: alle als offline markieren
                status_results = {p['id']: ("offline", False) for p in printer_data}
        
        # Ergebnisse zusammenstellen und Datenbank aktualisieren
        status_data = []
        current_time = datetime.now()
        
        for printer in printers:
            if printer.id in status_results:
                status, active = status_results[printer.id]
                # Mapping für Frontend-Kompatibilität
                if status == "online":
                    frontend_status = "available"
                else:
                    frontend_status = "offline"
            else:
                # Fallback falls kein Ergebnis vorliegt
                frontend_status = "offline"
                active = False
            
            # Status in der Datenbank aktualisieren
            printer.status = frontend_status
            printer.active = active
            
            # Setze last_checked falls das Feld existiert
            if hasattr(printer, 'last_checked'):
                printer.last_checked = current_time
            
            status_data.append({
                "id": printer.id,
                "name": printer.name,
                "model": printer.model or 'Unbekanntes Modell',
                "location": printer.location or 'Unbekannter Standort',
                "mac_address": printer.mac_address,
                "plug_ip": printer.plug_ip,
                "status": frontend_status,
                "active": active,
                "ip_address": printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None),
                "created_at": printer.created_at.isoformat() if printer.created_at else current_time.isoformat(),
                "last_checked": current_time.isoformat()
            })
        
        # Speichere die aktualisierten Status
        try:
            db_session.commit()
            printers_logger.info("Drucker-Status erfolgreich in Datenbank aktualisiert")
        except Exception as e:
            printers_logger.warning(f"Fehler beim Speichern der Status-Updates: {str(e)}")
            # Nicht kritisch, Status-Check kann trotzdem zurückgegeben werden
        
        db_session.close()
        
        online_count = len([s for s in status_data if s['status'] == 'available'])
        printers_logger.info(f"Status-Check abgeschlossen: {online_count} von {len(status_data)} Drucker online")
        
        return jsonify(status_data)
        
    except Exception as e:
        db_session.rollback()
        db_session.close()
        printers_logger.error(f"Fehler beim Status-Check der Drucker: {str(e)}")
        return jsonify({
            "error": f"Fehler beim Status-Check: {str(e)}",
            "printers": []
        }), 500

@app.route("/api/jobs/current", methods=["GET"])
@login_required
def get_current_job():
    """Gibt den aktuellen Job des Benutzers zurück."""
    db_session = get_db_session()
    try:
        current_job = db_session.query(Job).filter(
            Job.user_id == int(current_user.id),
            Job.status.in_(["scheduled", "running"])
        ).order_by(Job.start_at).first()
        
        if current_job:
            job_data = current_job.to_dict()
        else:
            job_data = None
            
        db_session.close()
        return jsonify(job_data)
    except Exception as e:
        db_session.close()
        return jsonify({"error": str(e)}), 500

# ===== WEITERE API-ROUTEN =====

@app.route("/api/printers/<int:printer_id>", methods=["GET"])
@login_required
def get_printer(printer_id):
    """Gibt einen spezifischen Drucker zurück."""
    db_session = get_db_session()
    
    try:
        printer = db_session.query(Printer).get(printer_id)
        
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Status-Check für diesen Drucker
        ip_to_check = printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None)
        if ip_to_check:
            status, active = check_printer_status(ip_to_check)
            printer.status = "available" if status == "online" else "offline"
            printer.active = active
            db_session.commit()
        
        printer_data = {
            "id": printer.id,
            "name": printer.name,
            "model": printer.model or 'Unbekanntes Modell',
            "location": printer.location or 'Unbekannter Standort',
            "mac_address": printer.mac_address,
            "plug_ip": printer.plug_ip,
            "status": printer.status or "offline",
            "active": printer.active if hasattr(printer, 'active') else True,
            "ip_address": ip_to_check,
            "created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        return jsonify(printer_data)
        
    except Exception as e:
        db_session.close()
        printers_logger.error(f"Fehler beim Abrufen des Druckers {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/printers", methods=["POST"])
@login_required
def create_printer():
    """Erstellt einen neuen Drucker (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Drucker erstellen"}), 403
    
    try:
        data = request.json
        
        # Pflichtfelder prüfen
        required_fields = ["name", "plug_ip"]
        for field in required_fields:
            if field not in data:
                return jsonify({"error": f"Feld '{field}' fehlt"}), 400
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Drucker mit diesem Namen existiert
        existing_printer = db_session.query(Printer).filter(Printer.name == data["name"]).first()
        if existing_printer:
            db_session.close()
            return jsonify({"error": "Ein Drucker mit diesem Namen existiert bereits"}), 400
        
        # Neuen Drucker erstellen
        new_printer = Printer(
            name=data["name"],
            model=data.get("model", ""),
            location=data.get("location", ""),
            mac_address=data.get("mac_address", ""),
            plug_ip=data["plug_ip"],
            status="offline",
            active=True,  # Neue Drucker sind standardmäßig aktiv
            created_at=datetime.now()
        )
        
        db_session.add(new_printer)
        db_session.commit()
        
        # Sofortiger Status-Check für den neuen Drucker
        ip_to_check = new_printer.plug_ip
        if ip_to_check:
            status, active = check_printer_status(ip_to_check)
            new_printer.status = "available" if status == "online" else "offline"
            new_printer.active = active
            db_session.commit()
        
        printer_data = {
            "id": new_printer.id,
            "name": new_printer.name,
            "model": new_printer.model,
            "location": new_printer.location,
            "mac_address": new_printer.mac_address,
            "plug_ip": new_printer.plug_ip,
            "status": new_printer.status,
            "active": new_printer.active,
            "created_at": new_printer.created_at.isoformat()
        }
        
        db_session.close()
        
        printers_logger.info(f"Neuer Drucker '{new_printer.name}' erstellt von Admin {current_user.id}")
        return jsonify({"printer": printer_data, "message": "Drucker erfolgreich erstellt"}), 201
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Erstellen eines Druckers: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/printers/add", methods=["POST"])
@login_required
def add_printer():
    """Alternativer Endpunkt zum Hinzufügen von Druckern (für Frontend-Kompatibilität)."""
    return create_printer()

@app.route("/api/printers/<int:printer_id>", methods=["PUT"])
@login_required
def update_printer(printer_id):
    """Aktualisiert einen Drucker (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Drucker bearbeiten"}), 403
    
    try:
        data = request.json
        db_session = get_db_session()
        
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Aktualisierbare Felder
        updatable_fields = ["name", "model", "location", "mac_address", "plug_ip"]
        for field in updatable_fields:
            if field in data:
                setattr(printer, field, data[field])
        
        db_session.commit()
        
        printer_data = {
            "id": printer.id,
            "name": printer.name,
            "model": printer.model,
            "location": printer.location,
            "mac_address": printer.mac_address,
            "plug_ip": printer.plug_ip,
            "status": printer.status,
            "created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        
        printers_logger.info(f"Drucker {printer_id} aktualisiert von Admin {current_user.id}")
        return jsonify({"printer": printer_data})
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Aktualisieren des Druckers {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/printers/<int:printer_id>", methods=["DELETE"])
@login_required
def delete_printer(printer_id):
    """Löscht einen Drucker (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Drucker löschen"}), 403
    
    try:
        db_session = get_db_session()
        
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Prüfen, ob noch aktive Jobs für diesen Drucker existieren
        active_jobs = db_session.query(Job).filter(
            Job.printer_id == printer_id,
            Job.status.in_(["scheduled", "running"])
        ).count()
        
        if active_jobs > 0:
            db_session.close()
            return jsonify({"error": f"Drucker kann nicht gelöscht werden: {active_jobs} aktive Jobs vorhanden"}), 400
        
        printer_name = printer.name
        db_session.delete(printer)
        db_session.commit()
        db_session.close()
        
        printers_logger.info(f"Drucker '{printer_name}' (ID: {printer_id}) gelöscht von Admin {current_user.id}")
        return jsonify({"message": "Drucker erfolgreich gelöscht"})
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Löschen des Druckers {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/jobs/<int:job_id>", methods=["DELETE"])
@login_required
@job_owner_required
def delete_job(job_id):
    """Löscht einen Job."""
    try:
        db_session = get_db_session()
        job = db_session.query(Job).get(job_id)
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
        
        # Prüfen, ob der Job gelöscht werden kann
        if job.status == "running":
            db_session.close()
            return jsonify({"error": "Laufende Jobs können nicht gelöscht werden"}), 400
        
        job_name = job.name
        db_session.delete(job)
        db_session.commit()
        db_session.close()
        
        jobs_logger.info(f"Job '{job_name}' (ID: {job_id}) gelöscht von Benutzer {current_user.id}")
        return jsonify({"message": "Job erfolgreich gelöscht"})
        
    except Exception as e:
        jobs_logger.error(f"Fehler beim Löschen des Jobs {job_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/jobs/<int:job_id>/cancel", methods=["POST"])
@login_required
@job_owner_required
def cancel_job(job_id):
    """Bricht einen Job ab."""
    try:
        db_session = get_db_session()
        job = db_session.query(Job).get(job_id)
        
        if not job:
            db_session.close()
            return jsonify({"error": "Job nicht gefunden"}), 404
        
        # Prüfen, ob der Job abgebrochen werden kann
        if job.status not in ["scheduled", "running"]:
            db_session.close()
            return jsonify({"error": f"Job kann im Status '{job.status}' nicht abgebrochen werden"}), 400
        
        # Job als abgebrochen markieren
        job.status = "cancelled"
        job.actual_end_time = datetime.now()
        
        # Wenn der Job läuft, Steckdose ausschalten
        if job.status == "running":
            from utils.job_scheduler import toggle_plug
            toggle_plug(job.printer_id, False)
        
        db_session.commit()
        
        job_dict = job.to_dict()
        db_session.close()
        
        jobs_logger.info(f"Job {job_id} abgebrochen von Benutzer {current_user.id}")
        return jsonify({"job": job_dict})
        
    except Exception as e:
        jobs_logger.error(f"Fehler beim Abbrechen des Jobs {job_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats", methods=["GET"])
@login_required
def get_stats():
    """Gibt Statistiken zurück."""
    try:
        db_session = get_db_session()
        
        # Grundlegende Statistiken
        total_users = db_session.query(User).count()
        total_printers = db_session.query(Printer).count()
        total_jobs = db_session.query(Job).count()
        
        # Jobs nach Status
        completed_jobs = db_session.query(Job).filter(Job.status == "completed").count()
        failed_jobs = db_session.query(Job).filter(Job.status == "failed").count()
        cancelled_jobs = db_session.query(Job).filter(Job.status == "cancelled").count()
        active_jobs = db_session.query(Job).filter(Job.status.in_(["scheduled", "running"])).count()
        
        # Online-Drucker
        online_printers = db_session.query(Printer).filter(Printer.status == "available").count()
        
        # Erfolgsrate
        finished_jobs = completed_jobs + failed_jobs + cancelled_jobs
        success_rate = (completed_jobs / finished_jobs * 100) if finished_jobs > 0 else 0
        
        # Benutzer-spezifische Statistiken (falls nicht Admin)
        user_stats = {}
        if not current_user.is_admin:
            user_jobs = db_session.query(Job).filter(Job.user_id == int(current_user.id)).count()
            user_completed = db_session.query(Job).filter(
                Job.user_id == int(current_user.id),
                Job.status == "completed"
            ).count()
            user_stats = {
                "total_jobs": user_jobs,
                "completed_jobs": user_completed,
                "success_rate": (user_completed / user_jobs * 100) if user_jobs > 0 else 0
            }
        
        db_session.close()
        
        stats = {
            "total_users": total_users,
            "total_printers": total_printers,
            "online_printers": online_printers,
            "total_jobs": total_jobs,
            "completed_jobs": completed_jobs,
            "failed_jobs": failed_jobs,
            "cancelled_jobs": cancelled_jobs,
            "active_jobs": active_jobs,
            "success_rate": round(success_rate, 1),
            "user_stats": user_stats
        }
        
        return jsonify(stats)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Statistiken: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/charts/job-status", methods=["GET"])
@login_required
def get_job_status_chart_data():
    """Gibt Diagrammdaten für Job-Status-Verteilung zurück."""
    try:
        db_session = get_db_session()
        
        # Job-Status zählen
        job_status_counts = {
            'completed': db_session.query(Job).filter(Job.status == 'completed').count(),
            'failed': db_session.query(Job).filter(Job.status == 'failed').count(),
            'cancelled': db_session.query(Job).filter(Job.status == 'cancelled').count(),
            'running': db_session.query(Job).filter(Job.status == 'running').count(),
            'scheduled': db_session.query(Job).filter(Job.status == 'scheduled').count()
        }
        
        db_session.close()
        
        chart_data = {
            'labels': ['Abgeschlossen', 'Fehlgeschlagen', 'Abgebrochen', 'Läuft', 'Geplant'],
            'datasets': [{
                'label': 'Anzahl Jobs',
                'data': [
                    job_status_counts['completed'],
                    job_status_counts['failed'], 
                    job_status_counts['cancelled'],
                    job_status_counts['running'],
                    job_status_counts['scheduled']
                ],
                'backgroundColor': [
                    '#10b981',  # Grün für abgeschlossen
                    '#ef4444',  # Rot für fehlgeschlagen
                    '#6b7280',  # Grau für abgebrochen
                    '#3b82f6',  # Blau für läuft
                    '#f59e0b'   # Orange für geplant
                ]
            }]
        }
        
        return jsonify(chart_data)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Job-Status-Diagrammdaten: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/charts/printer-usage", methods=["GET"])
@login_required
def get_printer_usage_chart_data():
    """Gibt Diagrammdaten für Drucker-Nutzung zurück."""
    try:
        db_session = get_db_session()
        
        # Drucker mit Job-Anzahl
        printer_usage = db_session.query(
            Printer.name,
            func.count(Job.id).label('job_count')
        ).outerjoin(Job).group_by(Printer.id, Printer.name).all()
        
        db_session.close()
        
        chart_data = {
            'labels': [usage[0] for usage in printer_usage],
            'datasets': [{
                'label': 'Anzahl Jobs',
                'data': [usage[1] for usage in printer_usage],
                'backgroundColor': '#3b82f6',
                'borderColor': '#1d4ed8',
                'borderWidth': 1
            }]
        }
        
        return jsonify(chart_data)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Drucker-Nutzung-Diagrammdaten: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/charts/jobs-timeline", methods=["GET"])
@login_required
def get_jobs_timeline_chart_data():
    """Gibt Diagrammdaten für Jobs-Timeline der letzten 30 Tage zurück."""
    try:
        db_session = get_db_session()
        
        # Letzte 30 Tage
        end_date = datetime.now().date()
        start_date = end_date - timedelta(days=30)
        
        # Jobs pro Tag der letzten 30 Tage
        daily_jobs = db_session.query(
            func.date(Job.created_at).label('date'),
            func.count(Job.id).label('count')
        ).filter(
            func.date(Job.created_at) >= start_date,
            func.date(Job.created_at) <= end_date
        ).group_by(func.date(Job.created_at)).all()
        
        # Alle Tage füllen (auch ohne Jobs)
        date_dict = {job_date: count for job_date, count in daily_jobs}
        
        labels = []
        data = []
        current_date = start_date
        
        while current_date <= end_date:
            labels.append(current_date.strftime('%d.%m'))
            data.append(date_dict.get(current_date, 0))
            current_date += timedelta(days=1)
        
        db_session.close()
        
        chart_data = {
            'labels': labels,
            'datasets': [{
                'label': 'Jobs pro Tag',
                'data': data,
                'fill': True,
                'backgroundColor': 'rgba(59, 130, 246, 0.1)',
                'borderColor': '#3b82f6',
                'tension': 0.4
            }]
        }
        
        return jsonify(chart_data)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Jobs-Timeline-Diagrammdaten: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/charts/user-activity", methods=["GET"])
@login_required
def get_user_activity_chart_data():
    """Gibt Diagrammdaten für Top-Benutzer-Aktivität zurück."""
    try:
        db_session = get_db_session()
        
        # Top 10 Benutzer nach Job-Anzahl
        top_users = db_session.query(
            User.username,
            func.count(Job.id).label('job_count')
        ).join(Job).group_by(
            User.id, User.username
        ).order_by(
            func.count(Job.id).desc()
        ).limit(10).all()
        
        db_session.close()
        
        chart_data = {
            'labels': [user[0] for user in top_users],
            'datasets': [{
                'label': 'Anzahl Jobs',
                'data': [user[1] for user in top_users],
                'backgroundColor': '#8b5cf6',
                'borderColor': '#7c3aed',
                'borderWidth': 1
            }]
        }
        
        return jsonify(chart_data)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Benutzer-Aktivität-Diagrammdaten: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/stats/export", methods=["GET"])
@login_required
def export_stats():
    """Exportiert Statistiken als CSV."""
    try:
        db_session = get_db_session()
        
        # Basis-Statistiken sammeln
        total_users = db_session.query(User).count()
        total_printers = db_session.query(Printer).count()
        total_jobs = db_session.query(Job).count()
        completed_jobs = db_session.query(Job).filter(Job.status == "completed").count()
        failed_jobs = db_session.query(Job).filter(Job.status == "failed").count()
        
        # CSV-Inhalt erstellen
        import io
        import csv
        
        output = io.StringIO()
        writer = csv.writer(output)
        
        # Header
        writer.writerow(['Metrik', 'Wert'])
        
        # Daten
        writer.writerow(['Gesamte Benutzer', total_users])
        writer.writerow(['Gesamte Drucker', total_printers])
        writer.writerow(['Gesamte Jobs', total_jobs])
        writer.writerow(['Abgeschlossene Jobs', completed_jobs])
        writer.writerow(['Fehlgeschlagene Jobs', failed_jobs])
        writer.writerow(['Erfolgsrate (%)', round((completed_jobs / total_jobs * 100), 2) if total_jobs > 0 else 0])
        writer.writerow(['Exportiert am', datetime.now().strftime('%d.%m.%Y %H:%M:%S')])
        
        db_session.close()
        
        # Response vorbereiten
        output.seek(0)
        
        response = Response(
            output.getvalue(),
            mimetype='text/csv',
            headers={
                'Content-Disposition': f'attachment; filename=statistiken_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv'
            }
        )
        
        return response
        
    except Exception as e:
        app_logger.error(f"Fehler beim Exportieren der Statistiken: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/admin/users", methods=["GET"])
@login_required
def get_users():
    """Gibt alle Benutzer zurück (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Benutzer anzeigen"}), 403
    
    try:
        db_session = get_db_session()
        users = db_session.query(User).all()
        
        user_data = []
        for user in users:
            user_data.append({
                "id": user.id,
                "username": user.username,
                "email": user.email,
                "first_name": user.first_name,
                "last_name": user.last_name,
                "is_admin": user.is_admin,
                "created_at": user.created_at.isoformat() if user.created_at else None,
                "last_login": user.last_login.isoformat() if hasattr(user, 'last_login') and user.last_login else None
            })
        
        db_session.close()
        return jsonify({"users": user_data})
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Benutzer: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/admin/users/<int:user_id>", methods=["PUT"])
@login_required
def update_user(user_id):
    """Aktualisiert einen Benutzer (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Benutzer bearbeiten"}), 403
    
    try:
        data = request.json
        db_session = get_db_session()
        
        user = db_session.get(User, user_id)
        if not user:
            db_session.close()
            return jsonify({"error": "Benutzer nicht gefunden"}), 404
        
        # Aktualisierbare Felder
        updatable_fields = ["username", "email", "first_name", "last_name", "is_admin"]
        for field in updatable_fields:
            if field in data:
                setattr(user, field, data[field])
        
        # Passwort separat behandeln
        if "password" in data and data["password"]:
            user.set_password(data["password"])
        
        db_session.commit()
        
        user_data = {
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "first_name": user.first_name,
            "last_name": user.last_name,
            "is_admin": user.is_admin,
            "created_at": user.created_at.isoformat() if user.created_at else None
        }
        
        db_session.close()
        
        user_logger.info(f"Benutzer {user_id} aktualisiert von Admin {current_user.id}")
        return jsonify({"user": user_data})
        
    except Exception as e:
        user_logger.error(f"Fehler beim Aktualisieren des Benutzers {user_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/admin/users/<int:user_id>", methods=["DELETE"])
@login_required
def delete_user(user_id):
    """Löscht einen Benutzer (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Benutzer löschen"}), 403
    
    # Verhindern, dass sich der Admin selbst löscht
    if user_id == current_user.id:
        return jsonify({"error": "Sie können sich nicht selbst löschen"}), 400
    
    try:
        db_session = get_db_session()
        
        user = db_session.get(User, user_id)
        if not user:
            db_session.close()
            return jsonify({"error": "Benutzer nicht gefunden"}), 404
        
        # Prüfen, ob noch aktive Jobs für diesen Benutzer existieren
        active_jobs = db_session.query(Job).filter(
            Job.user_id == user_id,
            Job.status.in_(["scheduled", "running"])
        ).count()
        
        if active_jobs > 0:
            db_session.close()
            return jsonify({"error": f"Benutzer kann nicht gelöscht werden: {active_jobs} aktive Jobs vorhanden"}), 400
        
        username = user.username
        db_session.delete(user)
        db_session.commit()
        db_session.close()
        
        user_logger.info(f"Benutzer '{username}' (ID: {user_id}) gelöscht von Admin {current_user.id}")
        return jsonify({"message": "Benutzer erfolgreich gelöscht"})
        
    except Exception as e:
        user_logger.error(f"Fehler beim Löschen des Benutzers {user_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

# ===== FEHLERBEHANDLUNG =====

@app.errorhandler(404)
def not_found_error(error):
    return render_template('errors/404.html'), 404

@app.errorhandler(500)
def internal_error(error):
    return render_template('errors/500.html'), 500

@app.errorhandler(403)
def forbidden_error(error):
    return render_template('errors/403.html'), 403

# ===== ADMIN - DATENBANK-VERWALTUNG =====

@app.route('/api/admin/database/stats', methods=['GET'])
@admin_required
def get_database_stats():
    """Gibt Datenbank-Statistiken zurück."""
    try:
        if database_monitor is None:
            return jsonify({
                "success": False,
                "error": "Database Monitor nicht verfügbar"
            }), 503
            
        stats = database_monitor.get_database_stats()
        return jsonify({
            "success": True,
            "stats": stats
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Datenbank-Statistiken: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/health', methods=['GET'])
@admin_required
def check_database_health():
    """Führt eine Datenbank-Gesundheitsprüfung durch."""
    try:
        if database_monitor is None:
            return jsonify({
                "success": False,
                "error": "Database Monitor nicht verfügbar"
            }), 503
            
        health = database_monitor.check_database_health()
        return jsonify({
            "success": True,
            "health": health
        })
    except Exception as e:
        app_logger.error(f"Fehler bei Datenbank-Gesundheitsprüfung: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/optimize', methods=['POST'])
@admin_required
def optimize_database():
    """Führt Datenbank-Optimierung durch."""
    try:
        if database_monitor is None:
            return jsonify({
                "success": False,
                "error": "Database Monitor nicht verfügbar"
            }), 503
            
        result = database_monitor.optimize_database()
        return jsonify({
            "success": result["success"],
            "result": result
        })
    except Exception as e:
        app_logger.error(f"Fehler bei Datenbank-Optimierung: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/backup', methods=['POST'])
@admin_required
def create_database_backup():
    """Erstellt ein manuelles Datenbank-Backup."""
    try:
        if backup_manager is None:
            return jsonify({
                "success": False,
                "error": "Backup Manager nicht verfügbar"
            }), 503
            
        data = request.get_json() or {}
        compress = data.get('compress', True)
        
        backup_path = backup_manager.create_backup(compress=compress)
        
        return jsonify({
            "success": True,
            "backup_path": backup_path,
            "message": "Backup erfolgreich erstellt"
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Erstellen des Backups: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/backups', methods=['GET'])
@admin_required
def list_database_backups():
    """Listet alle verfügbaren Datenbank-Backups auf."""
    try:
        if backup_manager is None:
            return jsonify({
                "success": False,
                "error": "Backup Manager nicht verfügbar"
            }), 503
            
        backups = backup_manager.get_backup_list()
        
        # Konvertiere datetime-Objekte zu Strings für JSON
        for backup in backups:
            backup['created'] = backup['created'].isoformat()
        
        return jsonify({
            "success": True,
            "backups": backups
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Backup-Liste: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/backup/restore', methods=['POST'])
@admin_required
def restore_database_backup():
    """Stellt ein Datenbank-Backup wieder her."""
    try:
        if backup_manager is None:
            return jsonify({
                "success": False,
                "error": "Backup Manager nicht verfügbar"
            }), 503
            
        data = request.get_json()
        if not data or 'backup_path' not in data:
            return jsonify({
                "success": False,
                "error": "Backup-Pfad erforderlich"
            }), 400
        
        backup_path = data['backup_path']
        
        # Sicherheitsprüfung: Nur Backups aus dem Backup-Verzeichnis erlauben
        if not backup_path.startswith(backup_manager.backup_dir):
            return jsonify({
                "success": False,
                "error": "Ungültiger Backup-Pfad"
            }), 400
        
        success = backup_manager.restore_backup(backup_path)
        
        if success:
            return jsonify({
                "success": True,
                "message": "Backup erfolgreich wiederhergestellt"
            })
        else:
            return jsonify({
                "success": False,
                "error": "Fehler beim Wiederherstellen des Backups"
            }), 500
            
    except Exception as e:
        app_logger.error(f"Fehler beim Wiederherstellen des Backups: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/admin/database/backup/cleanup', methods=['POST'])
@admin_required
def cleanup_old_backups():
    """Löscht alte Datenbank-Backups."""
    try:
        backup_dir = os.path.join(os.path.dirname(__file__), 'database', 'backups')
        if not os.path.exists(backup_dir):
            return jsonify({"error": "Backup-Verzeichnis nicht gefunden"}), 404
        
        # Backups älter als 30 Tage löschen
        cutoff_date = datetime.now() - timedelta(days=30)
        deleted_count = 0
        
        for filename in os.listdir(backup_dir):
            if filename.endswith('.sql'):
                file_path = os.path.join(backup_dir, filename)
                file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
                
                if file_mtime < cutoff_date:
                    os.remove(file_path)
                    deleted_count += 1
        
        return jsonify({
            "message": f"{deleted_count} alte Backups gelöscht",
            "deleted_count": deleted_count
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Löschen alter Backups: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/admin/stats/live', methods=['GET'])
@admin_required
def get_admin_live_stats():
    """Liefert Live-Statistiken für das Admin-Dashboard."""
    try:
        db_session = get_db_session()
        
        # Aktuelle Statistiken sammeln
        total_users = db_session.query(User).count()
        total_printers = db_session.query(Printer).count()
        total_jobs = db_session.query(Job).count()
        active_jobs = db_session.query(Job).filter(Job.status.in_(["scheduled", "running"])).count()
        
        # Printer-Status
        available_printers = db_session.query(Printer).filter(Printer.status == "available").count()
        offline_printers = db_session.query(Printer).filter(Printer.status == "offline").count()
        maintenance_printers = db_session.query(Printer).filter(Printer.status == "maintenance").count()
        
        # Jobs heute
        today = datetime.now().date()
        jobs_today = db_session.query(Job).filter(
            func.date(Job.created_at) == today
        ).count()
        
        # Erfolgreiche Jobs heute
        completed_jobs_today = db_session.query(Job).filter(
            func.date(Job.created_at) == today,
            Job.status == "completed"
        ).count()
        
        db_session.close()
        
        stats = {
            "users": {
                "total": total_users
            },
            "printers": {
                "total": total_printers,
                "available": available_printers,
                "offline": offline_printers,
                "maintenance": maintenance_printers
            },
            "jobs": {
                "total": total_jobs,
                "active": active_jobs,
                "today": jobs_today,
                "completed_today": completed_jobs_today
            },
            "timestamp": datetime.now().isoformat()
        }
        
        return jsonify(stats)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Live-Statistiken: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/admin/system/status', methods=['GET'])
@admin_required
def get_system_status():
    """Liefert System-Status-Informationen."""
    try:
        import psutil
        import platform
        
        # CPU und Memory
        cpu_percent = psutil.cpu_percent(interval=1)
        memory = psutil.virtual_memory()
        disk = psutil.disk_usage('/')
        
        # Netzwerk (vereinfacht)
        network = psutil.net_io_counters()
        
        system_info = {
            "platform": platform.system(),
            "platform_release": platform.release(),
            "platform_version": platform.version(),
            "machine": platform.machine(),
            "processor": platform.processor(),
            "cpu": {
                "percent": cpu_percent,
                "count": psutil.cpu_count()
            },
            "memory": {
                "total": memory.total,
                "available": memory.available,
                "percent": memory.percent,
                "used": memory.used
            },
            "disk": {
                "total": disk.total,
                "used": disk.used,
                "free": disk.free,
                "percent": (disk.used / disk.total) * 100
            },
            "network": {
                "bytes_sent": network.bytes_sent,
                "bytes_recv": network.bytes_recv
            },
            "timestamp": datetime.now().isoformat()
        }
        
        return jsonify(system_info)
        
    except ImportError:
        return jsonify({
            "error": "psutil nicht installiert",
            "message": "Systemstatus kann nicht abgerufen werden"
        }), 500
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen des Systemstatus: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route('/api/admin/database/status', methods=['GET'])
@admin_required  
def get_database_status():
    """Liefert Datenbank-Status-Informationen."""
    try:
        db_session = get_db_session()
        
        # Tabellen-Informationen sammeln
        table_stats = {}
        
        # User-Tabelle
        user_count = db_session.query(User).count()
        latest_user = db_session.query(User).order_by(User.created_at.desc()).first()
        
        # Printer-Tabelle  
        printer_count = db_session.query(Printer).count()
        latest_printer = db_session.query(Printer).order_by(Printer.created_at.desc()).first()
        
        # Job-Tabelle
        job_count = db_session.query(Job).count()
        latest_job = db_session.query(Job).order_by(Job.created_at.desc()).first()
        
        table_stats = {
            "users": {
                "count": user_count,
                "latest": latest_user.created_at.isoformat() if latest_user else None
            },
            "printers": {
                "count": printer_count,
                "latest": latest_printer.created_at.isoformat() if latest_printer else None
            },
            "jobs": {
                "count": job_count,
                "latest": latest_job.created_at.isoformat() if latest_job else None
            }
        }
        
        db_session.close()
        
        # Datenbank-Dateigröße (falls SQLite)
        db_file_size = None
        try:
            db_path = os.path.join(os.path.dirname(__file__), 'database', 'app.db')
            if os.path.exists(db_path):
                db_file_size = os.path.getsize(db_path)
        except:
            pass
        
        status = {
            "tables": table_stats,
            "database_size": db_file_size,
            "timestamp": datetime.now().isoformat(),
            "connection_status": "connected"
        }
        
        return jsonify(status)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen des Datenbankstatus: {str(e)}")
        return jsonify({
            "error": "Datenbankfehler",
            "connection_status": "error",
            "timestamp": datetime.now().isoformat()
        }), 500

# ===== WEITERE UI-ROUTEN =====

@app.route("/terms")
def terms():
    """Zeigt die Nutzungsbedingungen an."""
    return render_template("terms.html")

@app.route("/privacy")
def privacy():
    """Zeigt die Datenschutzerklärung an."""
    return render_template("privacy.html")

@app.route("/admin/users/add")
@login_required
def admin_add_user_page():
    """Zeigt die Seite zum Hinzufügen eines neuen Benutzers an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    return render_template("admin_add_user.html")

@app.route("/admin/printers/add")
@login_required
def admin_add_printer_page():
    """Zeigt die Seite zum Hinzufügen eines neuen Druckers an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    return render_template("admin_add_printer.html")

@app.route("/admin/printers/<int:printer_id>/manage")
@login_required
def admin_manage_printer_page(printer_id):
    """Zeigt die Drucker-Verwaltungsseite an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    db_session = get_db_session()
    try:
        printer = db_session.get(Printer, printer_id)
        if not printer:
            flash("Drucker nicht gefunden.", "error")
            return redirect(url_for("admin_page"))
        
        printer_data = {
            "id": printer.id,
            "name": printer.name,
            "model": printer.model or 'Unbekanntes Modell',
            "location": printer.location or 'Unbekannter Standort',
            "mac_address": printer.mac_address,
            "plug_ip": printer.plug_ip,
            "status": printer.status or "offline",
            "active": printer.active if hasattr(printer, 'active') else True,
            "created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        return render_template("admin_manage_printer.html", printer=printer_data)
        
    except Exception as e:
        db_session.close()
        app_logger.error(f"Fehler beim Laden der Drucker-Verwaltung: {str(e)}")
        flash("Fehler beim Laden der Drucker-Daten.", "error")
        return redirect(url_for("admin_page"))

@app.route("/admin/printers/<int:printer_id>/settings")
@login_required
def admin_printer_settings_page(printer_id):
    """Zeigt die Drucker-Einstellungsseite an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    db_session = get_db_session()
    try:
        printer = db_session.get(Printer, printer_id)
        if not printer:
            flash("Drucker nicht gefunden.", "error")
            return redirect(url_for("admin_page"))
        
        printer_data = {
            "id": printer.id,
            "name": printer.name,
            "model": printer.model or 'Unbekanntes Modell',
            "location": printer.location or 'Unbekannter Standort',
            "mac_address": printer.mac_address,
            "plug_ip": printer.plug_ip,
            "status": printer.status or "offline",
            "active": printer.active if hasattr(printer, 'active') else True,
            "created_at": printer.created_at.isoformat() if printer.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        return render_template("admin_printer_settings.html", printer=printer_data)
        
    except Exception as e:
        db_session.close()
        app_logger.error(f"Fehler beim Laden der Drucker-Einstellungen: {str(e)}")
        flash("Fehler beim Laden der Drucker-Daten.", "error")
        return redirect(url_for("admin_page"))

@app.route("/admin/guest-requests")
@login_required
@admin_required
def admin_guest_requests():
    """Admin-Seite für Gastanfragen Verwaltung"""
    try:
        app_logger.info(f"Admin-Gastanfragen Seite aufgerufen von User {current_user.id}")
        return render_template("admin_guest_requests.html")
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Gastanfragen Seite: {str(e)}")
        flash("Fehler beim Laden der Gastanfragen-Verwaltung.", "danger")
        return redirect(url_for("admin"))

@app.route("/requests/overview")
@login_required
@admin_required
def admin_guest_requests_overview():
    """Admin-Oberfläche für die Verwaltung von Gastanfragen mit direkten Aktionen."""
    try:
        app_logger.info(f"Admin-Gastanträge Übersicht aufgerufen von User {current_user.id}")
        return render_template("admin_guest_requests_overview.html")
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Gastanträge Übersicht: {str(e)}")
        flash("Fehler beim Laden der Gastanträge-Übersicht.", "danger")
        return redirect(url_for("admin"))

# ===== ADMIN API-ROUTEN FÜR BENUTZER UND DRUCKER =====

@app.route("/api/admin/users", methods=["POST"])
@login_required
def create_user_api():
    """Erstellt einen neuen Benutzer (nur für Admins)."""
    if not current_user.is_admin:
        return jsonify({"error": "Nur Administratoren können Benutzer erstellen"}), 403
    
    try:
        data = request.json
        
        # Pflichtfelder prüfen
        required_fields = ["username", "email", "password"]
        for field in required_fields:
            if field not in data or not data[field]:
                return jsonify({"error": f"Feld '{field}' ist erforderlich"}), 400
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Benutzer mit diesem Benutzernamen oder E-Mail existiert
        existing_user = db_session.query(User).filter(
            (User.username == data["username"]) | (User.email == data["email"])
        ).first()
        
        if existing_user:
            db_session.close()
            return jsonify({"error": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert bereits"}), 400
        
        # Neuen Benutzer erstellen
        new_user = User(
            username=data["username"],
            email=data["email"],
            first_name=data.get("first_name", ""),
            last_name=data.get("last_name", ""),
            is_admin=data.get("is_admin", False),
            created_at=datetime.now()
        )
        
        # Passwort setzen
        new_user.set_password(data["password"])
        
        db_session.add(new_user)
        db_session.commit()
        
        user_data = {
            "id": new_user.id,
            "username": new_user.username,
            "email": new_user.email,
            "first_name": new_user.first_name,
            "last_name": new_user.last_name,
            "is_admin": new_user.is_admin,
            "created_at": new_user.created_at.isoformat()
        }
        
        db_session.close()
        
        user_logger.info(f"Neuer Benutzer '{new_user.username}' erstellt von Admin {current_user.id}")
        return jsonify({"user": user_data}), 201
        
    except Exception as e:
        user_logger.error(f"Fehler beim Erstellen eines Benutzers: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/admin/printers/<int:printer_id>/toggle", methods=["POST"])
@login_required
def toggle_printer_power(printer_id):
    """
    Schaltet einen Drucker über die zugehörige Steckdose ein/aus.
    """
    if not current_user.is_admin:
        return jsonify({"error": "Administratorrechte erforderlich"}), 403
    
    try:
        # Robuste JSON-Datenverarbeitung
        data = {}
        try:
            if request.is_json and request.get_json():
                data = request.get_json()
            elif request.form:
                # Fallback für Form-Daten
                data = request.form.to_dict()
        except Exception as json_error:
            printers_logger.warning(f"Fehler beim Parsen der JSON-Daten für Drucker {printer_id}: {str(json_error)}")
            # Verwende Standard-Werte wenn JSON-Parsing fehlschlägt
            data = {}
        
        # Standard-Zustand ermitteln (Toggle-Verhalten)
        db_session = get_db_session()
        printer = db_session.query(Printer).get(printer_id)
        
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Aktuellen Status ermitteln für Toggle-Verhalten
        current_status = getattr(printer, 'status', 'offline')
        current_active = getattr(printer, 'active', False)
        
        # Zielzustand bestimmen
        if 'state' in data:
            # Expliziter Zustand angegeben
            state = bool(data.get("state", True))
        else:
            # Toggle-Verhalten: Umschalten basierend auf aktuellem Status
            state = not (current_status == "available" and current_active)
        
        db_session.close()
        
        # Steckdose schalten
        from utils.job_scheduler import toggle_plug
        success = toggle_plug(printer_id, state)
        
        if success:
            action = "eingeschaltet" if state else "ausgeschaltet"
            printers_logger.info(f"Drucker {printer.name} (ID: {printer_id}) erfolgreich {action} von Admin {current_user.name}")
            
            return jsonify({
                "success": True,
                "message": f"Drucker erfolgreich {action}",
                "printer_id": printer_id,
                "printer_name": printer.name,
                "state": state,
                "action": action
            })
        else:
            printers_logger.error(f"Fehler beim Schalten der Steckdose für Drucker {printer_id}")
            return jsonify({
                "success": False,
                "error": "Fehler beim Schalten der Steckdose",
                "printer_id": printer_id
            }), 500
            
    except Exception as e:
        printers_logger.error(f"Fehler beim Schalten von Drucker {printer_id}: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Interner Serverfehler",
            "details": str(e)
        }), 500

@app.route("/api/admin/printers/<int:printer_id>/test-tapo", methods=["POST"])
@login_required
@admin_required
def test_printer_tapo_connection(printer_id):
    """
    Testet die Tapo-Steckdosen-Verbindung für einen Drucker.
    """
    try:
        db_session = get_db_session()
        printer = db_session.query(Printer).get(printer_id)
        
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        if not printer.plug_ip or not printer.plug_username or not printer.plug_password:
            db_session.close()
            return jsonify({
                "error": "Unvollständige Tapo-Konfiguration",
                "missing": [
                    key for key, value in {
                        "plug_ip": printer.plug_ip,
                        "plug_username": printer.plug_username,
                        "plug_password": printer.plug_password
                    }.items() if not value
                ]
            }), 400
        
        db_session.close()
        
        # Tapo-Verbindung testen
        from utils.job_scheduler import test_tapo_connection
        test_result = test_tapo_connection(
            printer.plug_ip,
            printer.plug_username,
            printer.plug_password
        )
        
        return jsonify({
            "printer_id": printer_id,
            "printer_name": printer.name,
            "tapo_test": test_result
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Testen der Tapo-Verbindung für Drucker {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler beim Verbindungstest"}), 500

@app.route("/api/admin/printers/test-all-tapo", methods=["POST"])
@login_required
@admin_required
def test_all_printers_tapo_connection():
    """
    Testet die Tapo-Steckdosen-Verbindung für alle Drucker.
    Nützlich für Diagnose und Setup-Validierung.
    """
    try:
        db_session = get_db_session()
        printers = db_session.query(Printer).filter(Printer.active == True).all()
        db_session.close()
        
        if not printers:
            return jsonify({
                "message": "Keine aktiven Drucker gefunden",
                "results": []
            })
        
        # Alle Drucker testen
        from utils.job_scheduler import test_tapo_connection
        results = []
        
        for printer in printers:
            result = {
                "printer_id": printer.id,
                "printer_name": printer.name,
                "plug_ip": printer.plug_ip,
                "has_config": bool(printer.plug_ip and printer.plug_username and printer.plug_password)
            }
            
            if result["has_config"]:
                # Tapo-Verbindung testen
                test_result = test_tapo_connection(
                    printer.plug_ip,
                    printer.plug_username,
                    printer.plug_password
                )
                result["tapo_test"] = test_result
            else:
                result["tapo_test"] = {
                    "success": False,
                    "error": "Unvollständige Tapo-Konfiguration",
                    "device_info": None,
                    "status": "unconfigured"
                }
                result["missing_config"] = [
                    key for key, value in {
                        "plug_ip": printer.plug_ip,
                        "plug_username": printer.plug_username,
                        "plug_password": printer.plug_password
                    }.items() if not value
                ]
            
            results.append(result)
        
        # Zusammenfassung erstellen
        total_printers = len(results)
        successful_connections = sum(1 for r in results if r["tapo_test"]["success"])
        configured_printers = sum(1 for r in results if r["has_config"])
        
        return jsonify({
            "summary": {
                "total_printers": total_printers,
                "configured_printers": configured_printers,
                "successful_connections": successful_connections,
                "success_rate": round(successful_connections / total_printers * 100, 1) if total_printers > 0 else 0
            },
            "results": results
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Testen aller Tapo-Verbindungen: {str(e)}")
        return jsonify({"error": "Interner Serverfehler beim Massentest"}), 500

# ===== ADMIN FORM ENDPOINTS =====

@app.route("/admin/users/create", methods=["POST"])
@login_required
def admin_create_user_form():
    """Erstellt einen neuen Benutzer über HTML-Form (nur für Admins)."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    try:
        # Form-Daten lesen
        email = request.form.get("email", "").strip()
        name = request.form.get("name", "").strip()
        password = request.form.get("password", "").strip()
        role = request.form.get("role", "user").strip()
        
        # Pflichtfelder prüfen
        if not email or not password:
            flash("E-Mail und Passwort sind erforderlich.", "error")
            return redirect(url_for("admin_add_user_page"))
        
        # E-Mail validieren
        import re
        email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        if not re.match(email_pattern, email):
            flash("Ungültige E-Mail-Adresse.", "error")
            return redirect(url_for("admin_add_user_page"))
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Benutzer mit dieser E-Mail existiert
        existing_user = db_session.query(User).filter(User.email == email).first()
        if existing_user:
            db_session.close()
            flash("Ein Benutzer mit dieser E-Mail existiert bereits.", "error")
            return redirect(url_for("admin_add_user_page"))
        
        # E-Mail als Username verwenden (falls kein separates Username-Feld)
        username = email.split('@')[0]
        counter = 1
        original_username = username
        while db_session.query(User).filter(User.username == username).first():
            username = f"{original_username}{counter}"
            counter += 1
        
        # Neuen Benutzer erstellen
        new_user = User(
            username=username,
            email=email,
            first_name=name.split(' ')[0] if name else "",
            last_name=" ".join(name.split(' ')[1:]) if name and ' ' in name else "",
            is_admin=(role == "admin"),
            created_at=datetime.now()
        )
        
        # Passwort setzen
        new_user.set_password(password)
        
        db_session.add(new_user)
        db_session.commit()
        db_session.close()
        
        user_logger.info(f"Neuer Benutzer '{new_user.username}' erstellt von Admin {current_user.id}")
        flash(f"Benutzer '{new_user.email}' erfolgreich erstellt.", "success")
        return redirect(url_for("admin_page", tab="users"))
        
    except Exception as e:
        user_logger.error(f"Fehler beim Erstellen eines Benutzers über Form: {str(e)}")
        flash("Fehler beim Erstellen des Benutzers.", "error")
        return redirect(url_for("admin_add_user_page"))

@app.route("/admin/printers/create", methods=["POST"])
@login_required
def admin_create_printer_form():
    """Erstellt einen neuen Drucker über HTML-Form (nur für Admins)."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    try:
        # Form-Daten lesen
        name = request.form.get("name", "").strip()
        ip_address = request.form.get("ip_address", "").strip()
        model = request.form.get("model", "").strip()
        location = request.form.get("location", "").strip()
        description = request.form.get("description", "").strip()
        status = request.form.get("status", "available").strip()
        
        # Pflichtfelder prüfen
        if not name or not ip_address:
            flash("Name und IP-Adresse sind erforderlich.", "error")
            return redirect(url_for("admin_add_printer_page"))
        
        # IP-Adresse validieren
        import re
        ip_pattern = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
        if not re.match(ip_pattern, ip_address):
            flash("Ungültige IP-Adresse.", "error")
            return redirect(url_for("admin_add_printer_page"))
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Drucker mit diesem Namen existiert
        existing_printer = db_session.query(Printer).filter(Printer.name == name).first()
        if existing_printer:
            db_session.close()
            flash("Ein Drucker mit diesem Namen existiert bereits.", "error")
            return redirect(url_for("admin_add_printer_page"))
        
        # Neuen Drucker erstellen
        new_printer = Printer(
            name=name,
            model=model,
            location=location,
            description=description,
            mac_address="",  # Wird später ausgefüllt
            plug_ip=ip_address,
            status=status,
            created_at=datetime.now()
        )
        
        db_session.add(new_printer)
        db_session.commit()
        db_session.close()
        
        printers_logger.info(f"Neuer Drucker '{new_printer.name}' erstellt von Admin {current_user.id}")
        flash(f"Drucker '{new_printer.name}' erfolgreich erstellt.", "success")
        return redirect(url_for("admin_page", tab="printers"))
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Erstellen eines Druckers über Form: {str(e)}")
        flash("Fehler beim Erstellen des Druckers.", "error")
        return redirect(url_for("admin_add_printer_page"))

@app.route("/admin/users/<int:user_id>/edit", methods=["GET"])
@login_required
def admin_edit_user_page(user_id):
    """Zeigt die Benutzer-Bearbeitungsseite an."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    db_session = get_db_session()
    try:
        user = db_session.get(User, user_id)
        if not user:
            flash("Benutzer nicht gefunden.", "error")
            return redirect(url_for("admin_page", tab="users"))
        
        user_data = {
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "name": user.name or "",
            "is_admin": user.is_admin,
            "active": user.active,
            "created_at": user.created_at.isoformat() if user.created_at else datetime.now().isoformat()
        }
        
        db_session.close()
        return render_template("admin_edit_user.html", user=user_data)
        
    except Exception as e:
        db_session.close()
        app_logger.error(f"Fehler beim Laden der Benutzer-Daten: {str(e)}")
        flash("Fehler beim Laden der Benutzer-Daten.", "error")
        return redirect(url_for("admin_page", tab="users"))

@app.route("/admin/users/<int:user_id>/update", methods=["POST"])
@login_required
def admin_update_user_form(user_id):
    """Aktualisiert einen Benutzer über HTML-Form (nur für Admins)."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    try:
        # Form-Daten lesen
        email = request.form.get("email", "").strip()
        name = request.form.get("name", "").strip()
        password = request.form.get("password", "").strip()
        role = request.form.get("role", "user").strip()
        is_active = request.form.get("is_active", "true").strip() == "true"
        
        # Pflichtfelder prüfen
        if not email:
            flash("E-Mail-Adresse ist erforderlich.", "error")
            return redirect(url_for("admin_edit_user_page", user_id=user_id))
        
        # E-Mail validieren
        import re
        email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        if not re.match(email_pattern, email):
            flash("Ungültige E-Mail-Adresse.", "error")
            return redirect(url_for("admin_edit_user_page", user_id=user_id))
        
        db_session = get_db_session()
        
        user = db_session.query(User).get(user_id)
        if not user:
            db_session.close()
            flash("Benutzer nicht gefunden.", "error")
            return redirect(url_for("admin_page", tab="users"))
        
        # Prüfen, ob bereits ein anderer Benutzer mit dieser E-Mail existiert
        existing_user = db_session.query(User).filter(
            User.email == email, 
            User.id != user_id
        ).first()
        if existing_user:
            db_session.close()
            flash("Ein Benutzer mit dieser E-Mail-Adresse existiert bereits.", "error")
            return redirect(url_for("admin_edit_user_page", user_id=user_id))
        
        # Benutzer aktualisieren
        user.email = email
        if name:
            user.name = name
        
        # Passwort nur ändern, wenn eines angegeben wurde
        if password:
            user.password_hash = generate_password_hash(password)
        
        user.role = "admin" if role == "admin" else "user"
        user.active = is_active
        
        db_session.commit()
        db_session.close()
        
        auth_logger.info(f"Benutzer '{user.email}' (ID: {user_id}) aktualisiert von Admin {current_user.id}")
        flash(f"Benutzer '{user.email}' erfolgreich aktualisiert.", "success")
        return redirect(url_for("admin_page", tab="users"))
        
    except Exception as e:
        auth_logger.error(f"Fehler beim Aktualisieren eines Benutzers über Form: {str(e)}")
        flash("Fehler beim Aktualisieren des Benutzers.", "error")
        return redirect(url_for("admin_edit_user_page", user_id=user_id))

@app.route("/admin/printers/<int:printer_id>/update", methods=["POST"])
@login_required
def admin_update_printer_form(printer_id):
    """Aktualisiert einen Drucker über HTML-Form (nur für Admins)."""
    if not current_user.is_admin:
        flash("Sie haben keine Berechtigung für den Admin-Bereich.", "error")
        return redirect(url_for("index"))
    
    try:
        # Form-Daten lesen
        name = request.form.get("name", "").strip()
        ip_address = request.form.get("ip_address", "").strip()
        model = request.form.get("model", "").strip()
        location = request.form.get("location", "").strip()
        description = request.form.get("description", "").strip()
        status = request.form.get("status", "available").strip()
        
        # Pflichtfelder prüfen
        if not name or not ip_address:
            flash("Name und IP-Adresse sind erforderlich.", "error")
            return redirect(url_for("admin_printer_settings_page", printer_id=printer_id))
        
        # IP-Adresse validieren
        import re
        ip_pattern = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
        if not re.match(ip_pattern, ip_address):
            flash("Ungültige IP-Adresse.", "error")
            return redirect(url_for("admin_printer_settings_page", printer_id=printer_id))
        
        db_session = get_db_session()
        
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            flash("Drucker nicht gefunden.", "error")
            return redirect(url_for("admin_page", tab="printers"))
        
        # Prüfen, ob bereits ein anderer Drucker mit diesem Namen existiert
        existing_printer = db_session.query(Printer).filter(
            Printer.name == name, 
            Printer.id != printer_id
        ).first()
        if existing_printer:
            db_session.close()
            flash("Ein Drucker mit diesem Namen existiert bereits.", "error")
            return redirect(url_for("admin_printer_settings_page", printer_id=printer_id))
        
        # Drucker aktualisieren
        printer.name = name
        printer.model = model
        printer.location = location
        printer.description = description
        printer.plug_ip = ip_address
        printer.status = status
        
        db_session.commit()
        db_session.close()
        
        printers_logger.info(f"Drucker '{printer.name}' (ID: {printer_id}) aktualisiert von Admin {current_user.id}")
        flash(f"Drucker '{printer.name}' erfolgreich aktualisiert.", "success")
        return redirect(url_for("admin_manage_printer_page", printer_id=printer_id))
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Aktualisieren eines Druckers über Form: {str(e)}")
        flash("Fehler beim Aktualisieren des Druckers.", "error")
        return redirect(url_for("admin_printer_settings_page", printer_id=printer_id))

# Neue API-Endpunkte für erweiterte Drucker-Status-Verwaltung hinzufügen
@app.route("/api/printers/online", methods=["GET"])
@login_required
def get_online_printers():
    """Gibt nur die online/verfügbaren Drucker zurück - optimiert für schnelle Anzeige."""
    db_session = get_db_session()
    printers_logger = get_logger("printers")
    
    try:
        # Session-Cache für Online-Drucker prüfen
        cache_key = f"online_printers_{current_user.id}"
        cached_data = session.get(cache_key)
        cache_timestamp = session.get(f"{cache_key}_timestamp")
        
        # Cache ist 30 Sekunden gültig
        if cached_data and cache_timestamp:
            cache_age = (datetime.now() - datetime.fromisoformat(cache_timestamp)).total_seconds()
            if cache_age < 30:
                printers_logger.info(f"Online-Drucker aus Session-Cache geladen (Alter: {cache_age:.1f}s)")
                return jsonify({
                    "printers": cached_data,
                    "count": len(cached_data),
                    "cached": True,
                    "cache_age": cache_age
                })
        
        # Nur verfügbare/online Drucker aus Datenbank laden
        printers = db_session.query(Printer).filter(
            Printer.status.in_(["available", "online", "idle"]),
            Printer.active == True
        ).all()
        
        current_time = datetime.now()
        online_printers = []
        
        for printer in printers:
            printer_data = {
                "id": printer.id,
                "name": printer.name,
                "model": printer.model or 'Unbekanntes Modell',
                "location": printer.location or 'Unbekannter Standort',
                "mac_address": printer.mac_address,
                "plug_ip": printer.plug_ip,
                "status": printer.status,
                "active": printer.active,
                "ip_address": printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None),
                "created_at": printer.created_at.isoformat() if printer.created_at else current_time.isoformat(),
                "last_checked": printer.last_checked.isoformat() if hasattr(printer, 'last_checked') and printer.last_checked else None,
                "is_online": True  # Alle Drucker in dieser Liste sind online
            }
            online_printers.append(printer_data)
        
        # In Session-Cache speichern
        session[cache_key] = online_printers
        session[f"{cache_key}_timestamp"] = current_time.isoformat()
        session.permanent = True
        
        db_session.close()
        
        printers_logger.info(f"Online-Drucker geladen: {len(online_printers)} verfügbare Drucker")
        
        return jsonify({
            "printers": online_printers,
            "count": len(online_printers),
            "cached": False,
            "message": f"{len(online_printers)} online Drucker gefunden"
        })
        
    except Exception as e:
        db_session.rollback()
        db_session.close()
        printers_logger.error(f"Fehler beim Abrufen der Online-Drucker: {str(e)}")
        return jsonify({
            "error": f"Fehler beim Laden der Online-Drucker: {str(e)}",
            "printers": []
        }), 500

@app.route("/api/printers/status/live", methods=["GET"])
@login_required
@measure_execution_time(logger=printers_logger, task_name="API-Live-Drucker-Status")
def get_live_printer_status():
    """Gibt Live-Status aller Drucker zurück mit Session-Caching und Echtzeit-Updates."""
    db_session = get_db_session()
    printers_logger = get_logger("printers")
    
    try:
        # Session-Cache für Live-Status prüfen
        cache_key = f"live_printer_status_{current_user.id}"
        cached_data = session.get(cache_key)
        cache_timestamp = session.get(f"{cache_key}_timestamp")
        
        # Cache ist 15 Sekunden gültig für Live-Status
        if cached_data and cache_timestamp:
            cache_age = (datetime.now() - datetime.fromisoformat(cache_timestamp)).total_seconds()
            if cache_age < 15:
                printers_logger.info(f"Live-Status aus Session-Cache geladen (Alter: {cache_age:.1f}s)")
                return jsonify({
                    "printers": cached_data,
                    "cached": True,
                    "cache_age": cache_age,
                    "next_update": 15 - cache_age
                })
        
        # Alle Drucker aus der Datenbank laden
        printers = db_session.query(Printer).all()
        
        if not printers:
            return jsonify({
                "printers": [],
                "count": 0,
                "message": "Keine Drucker in der Datenbank gefunden"
            })
        
        # Drucker-Daten für Status-Check vorbereiten
        printer_data = []
        for printer in printers:
            printer_data.append({
                'id': printer.id,
                'name': printer.name,
                'ip_address': printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None)
            })
        
        # Paralleler Status-Check mit kürzerem Timeout für Live-Updates
        try:
            status_results = check_multiple_printers_status(printer_data, timeout=3)
        except Exception as e:
            printers_logger.warning(f"Status-Check fehlgeschlagen, verwende letzte bekannte Status: {str(e)}")
            # Fallback: verwende letzte bekannte Status
            status_results = {p['id']: (p.get('last_status', 'offline'), False) for p in printer_data}
        
        # Live-Status-Daten zusammenstellen
        live_status_data = []
        current_time = datetime.now()
        online_count = 0
        
        for printer in printers:
            if printer.id in status_results:
                status, active = status_results[printer.id]
                frontend_status = "available" if status == "online" else "offline"
                if frontend_status == "available":
                    online_count += 1
            else:
                frontend_status = printer.status or "offline"
                active = printer.active if hasattr(printer, 'active') else False
            
            # Status in Datenbank aktualisieren (asynchron)
            printer.status = frontend_status
            printer.active = active
            if hasattr(printer, 'last_checked'):
                printer.last_checked = current_time
            
            live_status_data.append({
                "id": printer.id,
                "name": printer.name,
                "model": printer.model or 'Unbekanntes Modell',
                "location": printer.location or 'Unbekannter Standort',
                "mac_address": printer.mac_address,
                "plug_ip": printer.plug_ip,
                "status": frontend_status,
                "active": active,
                "ip_address": printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None),
                "created_at": printer.created_at.isoformat() if printer.created_at else current_time.isoformat(),
                "last_checked": current_time.isoformat(),
                "is_online": frontend_status == "available",
                "status_changed": True  # Für Frontend-Animationen
            })
        
        # Änderungen in Datenbank speichern
        try:
            db_session.commit()
        except Exception as e:
            printers_logger.warning(f"Fehler beim Speichern der Live-Status-Updates: {str(e)}")
        
        # In Session-Cache speichern
        session[cache_key] = live_status_data
        session[f"{cache_key}_timestamp"] = current_time.isoformat()
        session.permanent = True
        
        # Online-Drucker-Cache invalidieren
        online_cache_key = f"online_printers_{current_user.id}"
        if online_cache_key in session:
            del session[online_cache_key]
            del session[f"{online_cache_key}_timestamp"]
        
        db_session.close()
        
        printers_logger.info(f"Live-Status aktualisiert: {online_count} von {len(live_status_data)} Drucker online")
        
        return jsonify({
            "printers": live_status_data,
            "count": len(live_status_data),
            "online_count": online_count,
            "offline_count": len(live_status_data) - online_count,
            "cached": False,
            "timestamp": current_time.isoformat(),
            "next_update": 15
        })
        
    except Exception as e:
        db_session.rollback()
        db_session.close()
        printers_logger.error(f"Fehler beim Live-Status-Check: {str(e)}")
        return jsonify({
            "error": f"Fehler beim Live-Status-Check: {str(e)}",
            "printers": []
        }), 500

@app.route("/api/printers/status/summary", methods=["GET"])
@login_required
def get_printer_status_summary():
    """Gibt eine Zusammenfassung des Drucker-Status zurück - sehr schnell."""
    db_session = get_db_session()
    
    try:
        # Session-Cache für Status-Zusammenfassung
        cache_key = f"printer_summary_{current_user.id}"
        cached_data = session.get(cache_key)
        cache_timestamp = session.get(f"{cache_key}_timestamp")
        
        # Cache ist 60 Sekunden gültig
        if cached_data and cache_timestamp:
            cache_age = (datetime.now() - datetime.fromisoformat(cache_timestamp)).total_seconds()
            if cache_age < 60:
                return jsonify({
                    **cached_data,
                    "cached": True,
                    "cache_age": cache_age
                })
        
        # Status-Zusammenfassung aus Datenbank
        total_printers = db_session.query(Printer).count()
        online_printers = db_session.query(Printer).filter(
            Printer.status.in_(["available", "online", "idle"]),
            Printer.active == True
        ).count()
        offline_printers = total_printers - online_printers
        
        # Letzte Aktualisierung ermitteln
        last_checked = db_session.query(func.max(Printer.last_checked)).scalar()
        
        summary_data = {
            "total": total_printers,
            "online": online_printers,
            "offline": offline_printers,
            "percentage_online": round((online_printers / total_printers * 100) if total_printers > 0 else 0, 1),
            "last_checked": last_checked.isoformat() if last_checked else None,
            "timestamp": datetime.now().isoformat()
        }
        
        # In Session-Cache speichern
        session[cache_key] = summary_data
        session[f"{cache_key}_timestamp"] = datetime.now().isoformat()
        session.permanent = True
        
        db_session.close()
        
        return jsonify({
            **summary_data,
            "cached": False
        })
        
    except Exception as e:
        db_session.close()
        return jsonify({
            "error": f"Fehler beim Laden der Status-Zusammenfassung: {str(e)}",
            "total": 0,
            "online": 0,
            "offline": 0
        }), 500

# Session-Cache-Management
@app.route("/api/printers/cache/clear", methods=["POST"])
@login_required
def clear_printer_cache():
    """
    Löscht den Drucker-Cache für eine Aktualisierung.
    """
    try:
        # Invalidate model cache for printers
        from models import invalidate_model_cache
        invalidate_model_cache("Printer")
        
        # Clear any additional printer-specific caches
        # Hier können Sie weitere Cache-Löschungen hinzufügen
        
        printers_logger.info(f"Drucker-Cache geleert von Benutzer {current_user.name}")
        
        return jsonify({
            "success": True,
            "message": "Drucker-Cache erfolgreich geleert"
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Leeren des Drucker-Caches: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Leeren des Caches",
            "details": str(e)
        }), 500

@app.route("/api/printers/monitor/live-status", methods=["GET"])
@login_required
@limit_requests("printer_monitor_live")
def get_live_printer_monitor_status():
    """
    Live-Druckerstatus über den neuen PrinterMonitor mit Session-Caching.
    """
    try:
        use_cache = request.args.get('use_cache', 'true').lower() == 'true'
        
        printers_logger.info(f"Live-Druckerstatus angefordert von {current_user.name} (Cache: {use_cache})")
        
        # Drucker-Status über Monitor abrufen
        status_dict = printer_monitor.get_live_printer_status(use_session_cache=use_cache)
        
        # Zusätzliche Statistiken hinzufügen
        summary = printer_monitor.get_printer_summary()
        
        response_data = {
            "success": True,
            "printers": status_dict,
            "summary": summary,
            "cache_used": use_cache,
            "timestamp": datetime.now().isoformat(),
            "total_printers": len(status_dict)
        }
        
        printers_logger.info(f"Live-Status für {len(status_dict)} Drucker zurückgegeben")
        
        return jsonify(response_data)
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Abrufen des Live-Druckerstatus: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Abrufen des Live-Status",
            "details": str(e),
            "printers": {},
            "summary": {"total": 0, "online": 0, "offline": 0}
        }), 500

@app.route("/api/printers/monitor/summary", methods=["GET"])
@login_required
@limit_requests("printer_monitor_summary")
def get_printer_monitor_summary():
    """
    Schnelle Zusammenfassung des Druckerstatus ohne vollständige Details.
    """
    try:
        summary = printer_monitor.get_printer_summary()
        
        return jsonify({
            "success": True,
            "summary": summary,
            "timestamp": datetime.now().isoformat()
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Abrufen der Drucker-Zusammenfassung: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Abrufen der Zusammenfassung",
            "summary": {"total": 0, "online": 0, "offline": 0}
        }), 500

@app.route("/api/printers/monitor/clear-cache", methods=["POST"])
@login_required
@limit_requests("printer_monitor_cache")
def clear_printer_monitor_cache():
    """
    Löscht alle Caches des Drucker-Monitors.
    """
    try:
        printer_monitor.clear_all_caches()
        
        printers_logger.info(f"Drucker-Monitor-Cache geleert von Benutzer {current_user.name}")
        
        return jsonify({
            "success": True,
            "message": "Drucker-Monitor-Cache erfolgreich geleert"
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Leeren des Drucker-Monitor-Caches: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Leeren des Monitor-Caches",
            "details": str(e)
        }), 500

@app.route("/api/printers/monitor/initialize-outlets", methods=["POST"])
@login_required
@admin_required
@limit_requests("printer_monitor_init")
def initialize_printer_outlets():
    """
    Initialisiert alle Drucker-Steckdosen (schaltet sie aus für einheitlichen Zustand).
    Nur für Administratoren.
    """
    try:
        printers_logger.info(f"Steckdosen-Initialisierung gestartet von Admin {current_user.name}")
        
        # Steckdosen initialisieren
        results = printer_monitor.initialize_all_outlets_on_startup()
        
        success_count = sum(1 for success in results.values() if success)
        total_count = len(results)
        
        return jsonify({
            "success": True,
            "message": f"Steckdosen-Initialisierung abgeschlossen: {success_count}/{total_count} erfolgreich",
            "results": results,
            "statistics": {
                "total": total_count,
                "successful": success_count,
                "failed": total_count - success_count
            }
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler bei Steckdosen-Initialisierung: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler bei der Steckdosen-Initialisierung",
            "details": str(e)
        }), 500

# ===== FEHLENDE ADMIN-API-ENDPUNKTE =====

@app.route('/api/admin/cache/clear', methods=['POST'])
@admin_required
def clear_admin_cache():
    """Leert den System-Cache"""
    try:
        # Cache-Verzeichnisse leeren
        import shutil
        import os
        
        cache_dirs = [
            os.path.join(os.path.dirname(__file__), 'static', 'cache'),
            os.path.join(os.path.dirname(__file__), '__pycache__'),
        ]
        
        cleared_items = 0
        for cache_dir in cache_dirs:
            if os.path.exists(cache_dir):
                for item in os.listdir(cache_dir):
                    item_path = os.path.join(cache_dir, item)
                    try:
                        if os.path.isfile(item_path):
                            os.unlink(item_path)
                            cleared_items += 1
                        elif os.path.isdir(item_path):
                            shutil.rmtree(item_path)
                            cleared_items += 1
                    except Exception as e:
                        app_logger.warning(f"Konnte Cache-Element nicht löschen: {item_path} - {str(e)}")
        
        # Modell-Cache leeren
        try:
            from models import clear_cache
            clear_cache()
        except (ImportError, AttributeError):
            app_logger.warning("clear_cache Funktion nicht verfügbar")
        
        app_logger.info(f"System-Cache geleert: {cleared_items} Elemente entfernt")
        return jsonify({
            "success": True,
            "message": f"Cache erfolgreich geleert ({cleared_items} Elemente)",
            "cleared_items": cleared_items
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Leeren des Cache: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Leeren des Cache: {str(e)}"
        }), 500

@app.route('/api/admin/system/restart', methods=['POST'])
@admin_required
def restart_admin_system():
    """Startet das System neu (nur für Entwicklung)"""
    try:
        import os
        import signal
        
        app_logger.warning("System-Neustart durch Admin angefordert")
        
        # In Produktionsumgebung sollte dies anders gehandhabt werden
        if os.environ.get('FLASK_ENV') == 'development':
            # Graceful shutdown für Development
            def shutdown_server():
                func = request.environ.get('werkzeug.server.shutdown')
                if func is None:
                    raise RuntimeError('Not running with the Werkzeug Server')
                func()
            
            shutdown_server()
            return jsonify({
                "success": True,
                "message": "System wird neugestartet..."
            })
        else:
            # Für Produktion - Signal an Parent Process
            os.kill(os.getpid(), signal.SIGTERM)
            return jsonify({
                "success": True,
                "message": "Neustart-Signal gesendet"
            })
            
    except Exception as e:
        app_logger.error(f"Fehler beim System-Neustart: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Neustart: {str(e)}"
        }), 500

@app.route('/api/admin/printers/update-all', methods=['POST'])
@admin_required
def update_all_printers():
    """Aktualisiert den Status aller Drucker"""
    try:
        db_session = get_db_session()
        printers = db_session.query(Printer).all()
        
        updated_printers = []
        
        for printer in printers:
            if printer.plug_ip:
                try:
                    status, active = check_printer_status(printer.plug_ip)
                    old_status = printer.status
                    
                    printer.update_status(status, active)
                    
                    updated_printers.append({
                        "id": printer.id,
                        "name": printer.name,
                        "old_status": old_status,
                        "new_status": status,
                        "active": active
                    })
                    
                except Exception as e:
                    printers_logger.warning(f"Fehler beim Aktualisieren von Drucker {printer.name}: {str(e)}")
        
        db_session.commit()
        db_session.close()
        
        app_logger.info(f"Status von {len(updated_printers)} Druckern aktualisiert")
        return jsonify({
            "success": True,
            "message": f"Status von {len(updated_printers)} Druckern aktualisiert",
            "updated_printers": updated_printers
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Aktualisieren aller Drucker: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Aktualisieren: {str(e)}"
        }), 500

@app.route('/api/admin/settings', methods=['GET'])
@admin_required
def get_admin_settings():
    """Holt die aktuellen Admin-Einstellungen"""
    try:
        from config.settings import (
            FLASK_HOST, FLASK_PORT, FLASK_DEBUG, SESSION_LIFETIME,
            SCHEDULER_INTERVAL, SCHEDULER_ENABLED, SSL_ENABLED
        )
        
        settings = {
            "server": {
                "host": FLASK_HOST,
                "port": FLASK_PORT,
                "debug": FLASK_DEBUG,
                "ssl_enabled": SSL_ENABLED
            },
            "session": {
                "lifetime_minutes": SESSION_LIFETIME.total_seconds() / 60
            },
            "scheduler": {
                "interval_seconds": SCHEDULER_INTERVAL,
                "enabled": SCHEDULER_ENABLED
            }
        }
        
        return jsonify({
            "success": True,
            "settings": settings
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Einstellungen: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Laden der Einstellungen: {str(e)}"
        }), 500

@app.route('/api/admin/settings', methods=['POST'])
@admin_required
def update_admin_settings():
    """Aktualisiert die Admin-Einstellungen"""
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({
                "success": False,
                "message": "Keine Daten empfangen"
            }), 400
        
        # Hier würden normalerweise die Einstellungen in einer Konfigurationsdatei gespeichert
        # Für diese Demo loggen wir nur die Änderungen
        app_logger.info(f"Admin-Einstellungen aktualisiert: {data}")
        
        return jsonify({
            "success": True,
            "message": "Einstellungen erfolgreich aktualisiert"
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Aktualisieren der Admin-Einstellungen: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Aktualisieren: {str(e)}"
        }), 500

@app.route('/api/admin/logs/export', methods=['GET'])
@admin_required
def export_admin_logs():
    """Exportiert System-Logs"""
    try:
        import os
        import zipfile
        import tempfile
        from datetime import datetime
        
        # Temporäre ZIP-Datei erstellen
        temp_dir = tempfile.mkdtemp()
        zip_filename = f"myp_logs_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip"
        zip_path = os.path.join(temp_dir, zip_filename)
        
        log_dir = os.path.join(os.path.dirname(__file__), 'logs')
        
        with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, dirs, files in os.walk(log_dir):
                for file in files:
                    if file.endswith('.log'):
                        file_path = os.path.join(root, file)
                        arcname = os.path.relpath(file_path, log_dir)
                        zipf.write(file_path, arcname)
        
        app_logger.info("System-Logs exportiert")
        return send_file(zip_path, as_attachment=True, download_name=zip_filename)
        
    except Exception as e:
        app_logger.error(f"Fehler beim Exportieren der Logs: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Exportieren: {str(e)}"
        }), 500

@app.route('/api/logs', methods=['GET'])
@login_required
def get_system_logs():
    """API-Endpunkt zum Laden der System-Logs für das Dashboard."""
    if not current_user.is_admin:
        return jsonify({"success": False, "error": "Berechtigung verweigert"}), 403
    
    try:
        import os
        from datetime import datetime
        
        log_level = request.args.get('log_level', 'all')
        log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logs')
        
        # Logeinträge sammeln
        app_logs = []
        for category in ['app', 'auth', 'jobs', 'printers', 'scheduler', 'errors']:
            log_file = os.path.join(log_dir, category, f'{category}.log')
            if os.path.exists(log_file):
                try:
                    with open(log_file, 'r', encoding='utf-8') as f:
                        lines = f.readlines()
                        # Nur die letzten 100 Zeilen pro Datei
                        for line in lines[-100:]:
                            line = line.strip()
                            if not line:
                                continue
                                
                            # Log-Level-Filter anwenden
                            if log_level != 'all':
                                if log_level.upper() not in line:
                                    continue
                            
                            # Log-Eintrag parsen
                            parts = line.split(' - ')
                            if len(parts) >= 3:
                                timestamp = parts[0]
                                level = parts[1]
                                message = ' - '.join(parts[2:])
                            else:
                                timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                                level = 'INFO'
                                message = line
                            
                            app_logs.append({
                                'timestamp': timestamp,
                                'level': level,
                                'category': category,
                                'module': category,
                                'message': message,
                                'source': category
                            })
                except Exception as file_error:
                    app_logger.warning(f"Fehler beim Lesen der Log-Datei {log_file}: {str(file_error)}")
                    continue
        
        # Nach Zeitstempel sortieren (neueste zuerst)
        try:
            logs = sorted(app_logs, key=lambda x: x['timestamp'] if x['timestamp'] else '', reverse=True)[:100]
        except:
            # Falls Sortierung fehlschlägt, einfach die letzten 100 nehmen
            logs = app_logs[-100:]
        
        app_logger.info(f"Logs erfolgreich geladen: {len(logs)} Einträge")
        
        return jsonify({
            "success": True,
            "logs": logs,
            "count": len(logs),
            "message": f"{len(logs)} Log-Einträge geladen"
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Logs: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden der Logs",
            "message": str(e),
            "logs": []
        }), 500

# ===== ENDE FEHLENDE ADMIN-API-ENDPUNKTE =====

# ===== BENACHRICHTIGUNGS-API-ENDPUNKTE =====

@app.route('/api/notifications', methods=['GET'])
@login_required
def get_notifications():
    """Holt alle Benachrichtigungen für den aktuellen Benutzer"""
    try:
        db_session = get_db_session()
        
        # Sicherstellen, dass current_user.id als Integer behandelt wird
        user_id = int(current_user.id)
        
        # Benachrichtigungen für den aktuellen Benutzer laden
        notifications = db_session.query(Notification).filter(
            Notification.user_id == user_id
        ).order_by(Notification.created_at.desc()).limit(50).all()
        
        notifications_data = [notification.to_dict() for notification in notifications]
        
        db_session.close()
        
        return jsonify({
            "success": True,
            "notifications": notifications_data
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Benachrichtigungen: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Laden der Benachrichtigungen: {str(e)}"
        }), 500

@app.route('/api/notifications/<int:notification_id>/read', methods=['POST'])
@login_required
def mark_notification_read(notification_id):
    """Markiert eine Benachrichtigung als gelesen"""
    try:
        db_session = get_db_session()
        
        # Sicherstellen, dass current_user.id als Integer behandelt wird
        user_id = int(current_user.id)
        
        notification = db_session.query(Notification).filter(
            Notification.id == notification_id,
            Notification.user_id == user_id
        ).first()
        
        if not notification:
            db_session.close()
            return jsonify({
                "success": False,
                "message": "Benachrichtigung nicht gefunden"
            }), 404
        
        notification.read = True
        db_session.commit()
        db_session.close()
        
        return jsonify({
            "success": True,
            "message": "Benachrichtigung als gelesen markiert"
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Markieren der Benachrichtigung: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Markieren: {str(e)}"
        }), 500

@app.route('/api/notifications/mark-all-read', methods=['POST'])
@login_required
def mark_all_notifications_read():
    """Markiert alle Benachrichtigungen als gelesen"""
    try:
        db_session = get_db_session()
        
        # Sicherstellen, dass current_user.id als Integer behandelt wird
        user_id = int(current_user.id)
        
        # Alle ungelesenen Benachrichtigungen des Benutzers finden und als gelesen markieren
        updated_count = db_session.query(Notification).filter(
            Notification.user_id == user_id,
            Notification.read == False
        ).update({"read": True})
        
        db_session.commit()
        db_session.close()
        
        return jsonify({
            "success": True,
            "message": f"{updated_count} Benachrichtigungen als gelesen markiert"
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Markieren aller Benachrichtigungen: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Markieren: {str(e)}"
        }), 500

# ===== ENDE BENACHRICHTIGUNGS-API-ENDPUNKTE =====

# ===== QUEUE-MANAGER-API-ENDPUNKTE =====

@app.route('/api/queue/status', methods=['GET'])
@login_required  
def get_queue_status():
    """Gibt den aktuellen Status der Drucker-Warteschlangen zurück."""
    try:
        queue_manager = get_queue_manager()
        status = queue_manager.get_queue_status()
        
        return jsonify({
            "success": True,
            "queue_status": status
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen des Queue-Status: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim Abrufen des Queue-Status: {str(e)}"
        }), 500

@app.route('/api/queue/check-now', methods=['POST'])
@login_required
def trigger_queue_check():
    """Triggert eine sofortige Überprüfung der Warteschlangen."""
    try:
        # Bestehende check_waiting_jobs API verwenden
        return check_waiting_jobs()
        
    except Exception as e:
        app_logger.error(f"Fehler beim manuellen Queue-Check: {str(e)}")
        return jsonify({
            "success": False,
            "message": f"Fehler beim manuellen Queue-Check: {str(e)}"
        }), 500

# ===== ENDE QUEUE-MANAGER-API-ENDPUNKTE =====


# ===== NEUE ADMIN API-ROUTEN FÜR BUTTON-FUNKTIONALITÄTEN =====

@app.route('/api/admin/maintenance/activate', methods=['POST'])
@admin_required
def activate_maintenance_mode():
    """Aktiviert den Wartungsmodus"""
    try:
        # Hier würde die Wartungsmodus-Logik implementiert werden
        # Zum Beispiel: Setze einen globalen Flag, blockiere neue Jobs, etc.
        
        # Für Demo-Zwecke simulieren wir die Aktivierung
        app_logger.info("Wartungsmodus aktiviert durch Admin")
        
        return jsonify({
            "success": True,
            "message": "Wartungsmodus wurde aktiviert"
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Aktivieren des Wartungsmodus: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Aktivieren des Wartungsmodus"
        }), 500

@app.route('/api/admin/maintenance/deactivate', methods=['POST'])
@admin_required
def deactivate_maintenance_mode():
    """Deaktiviert den Wartungsmodus"""
    try:
        # Hier würde die Wartungsmodus-Deaktivierung implementiert werden
        
        app_logger.info("Wartungsmodus deaktiviert durch Admin")
        
        return jsonify({
            "success": True,
            "message": "Wartungsmodus wurde deaktiviert"
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Deaktivieren des Wartungsmodus: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Deaktivieren des Wartungsmodus"
        }), 500

@app.route('/api/admin/stats/live', methods=['GET'])
@admin_required
def get_live_admin_stats():
    """Liefert Live-Statistiken für das Admin-Dashboard"""
    try:
        db_session = get_db_session()
        
        # Benutzer-Statistiken
        total_users = db_session.query(func.count(User.id)).scalar() or 0
        
        # Drucker-Statistiken
        total_printers = db_session.query(func.count(Printer.id)).scalar() or 0
        online_printers = db_session.query(func.count(Printer.id)).filter(
            Printer.status.in_(['online', 'idle'])
        ).scalar() or 0
        
        # Job-Statistiken
        active_jobs = db_session.query(func.count(Job.id)).filter(
            Job.status == 'running'
        ).scalar() or 0
        
        queued_jobs = db_session.query(func.count(Job.id)).filter(
            Job.status == 'queued'
        ).scalar() or 0
        
        # Erfolgsrate berechnen
        total_jobs = db_session.query(func.count(Job.id)).scalar() or 1
        completed_jobs = db_session.query(func.count(Job.id)).filter(
            Job.status == 'completed'
        ).scalar() or 0
        
        success_rate = round((completed_jobs / total_jobs) * 100, 1) if total_jobs > 0 else 0
        
        db_session.close()
        
        return jsonify({
            "success": True,
            "stats": {
                "total_users": total_users,
                "total_printers": total_printers,
                "online_printers": online_printers,
                "active_jobs": active_jobs,
                "queued_jobs": queued_jobs,
                "success_rate": success_rate
            }
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Live-Admin-Statistiken: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden der Statistiken"
        }), 500

@app.route('/api/admin/system/status', methods=['GET'])
@admin_required  
def get_admin_system_status():
    """Liefert detaillierte System-Status-Informationen"""
    try:
        import psutil
        import os
        from datetime import datetime, timedelta
        
        # CPU-Nutzung
        cpu_usage = round(psutil.cpu_percent(interval=1), 1)
        
        # RAM-Nutzung
        memory = psutil.virtual_memory()
        memory_usage = round(memory.percent, 1)
        
        # Festplatten-Nutzung
        disk = psutil.disk_usage('/')
        disk_usage = round((disk.used / disk.total) * 100, 1)
        
        # System-Uptime
        boot_time = datetime.fromtimestamp(psutil.boot_time())
        uptime = datetime.now() - boot_time
        uptime_str = f"{uptime.days}d {uptime.seconds//3600}h {(uptime.seconds//60)%60}m"
        
        # Datenbankverbindung testen
        db_session = get_db_session()
        db_status = "Verbunden"
        try:
            db_session.execute("SELECT 1")
            db_session.close()
        except:
            db_status = "Fehler"
            db_session.close()
        
        return jsonify({
            "success": True,
            "status": {
                "cpu_usage": cpu_usage,
                "memory_usage": memory_usage,
                "disk_usage": disk_usage,
                "uptime": uptime_str,
                "database_status": db_status,
                "timestamp": datetime.now().isoformat()
            }
        })
        
    except ImportError:
        # Falls psutil nicht verfügbar ist, Dummy-Daten zurückgeben
        return jsonify({
            "success": True,
            "status": {
                "cpu_usage": 15.2,
                "memory_usage": 42.8,
                "disk_usage": 67.3,
                "uptime": "2d 14h 32m",
                "database_status": "Verbunden",
                "timestamp": datetime.now().isoformat()
            }
        })
    except Exception as e:
        app_logger.error(f"Fehler beim Laden des System-Status: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden des System-Status"
        }), 500

@app.route('/api/dashboard/stats', methods=['GET'])
@login_required
def get_dashboard_stats():
    """Liefert Dashboard-Statistiken für Hintergrund-Updates"""
    try:
        db_session = get_db_session()
        
        # Aktive Jobs zählen
        active_jobs_count = db_session.query(func.count(Job.id)).filter(
            Job.status == 'running'
        ).scalar() or 0
        
        # Verfügbare Drucker zählen
        available_printers_count = db_session.query(func.count(Printer.id)).filter(
            Printer.status.in_(['online', 'idle'])
        ).scalar() or 0
        
        # Gesamte Jobs zählen
        total_jobs_count = db_session.query(func.count(Job.id)).scalar() or 0
        
        # Erfolgsrate berechnen
        completed_jobs = db_session.query(func.count(Job.id)).filter(
            Job.status == 'completed'
        ).scalar() or 0
        
        success_rate = round((completed_jobs / total_jobs_count) * 100, 1) if total_jobs_count > 0 else 100.0
        
        db_session.close()
        
        return jsonify({
            "success": True,
            "active_jobs_count": active_jobs_count,
            "available_printers_count": available_printers_count,
            "total_jobs_count": total_jobs_count,
            "success_rate": success_rate
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Dashboard-Statistiken: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden der Statistiken"
        }), 500

@app.route('/api/dashboard/active-jobs', methods=['GET'])
@login_required
def get_dashboard_active_jobs():
    """Liefert aktive Jobs für Dashboard-Updates"""
    try:
        db_session = get_db_session()
        
        active_jobs = db_session.query(Job).filter(
            Job.status.in_(['running', 'paused'])
        ).limit(5).all()
        
        jobs_data = []
        for job in active_jobs:
            jobs_data.append({
                "id": job.id,
                "name": job.name,
                "status": job.status,
                "progress": getattr(job, 'progress', 0),
                "printer": job.printer.name if job.printer else 'Unbekannt',
                "start_time": job.created_at.strftime('%H:%M') if job.created_at else '--:--'
            })
        
        db_session.close()
        
        return jsonify({
            "success": True,
            "jobs": jobs_data
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der aktiven Jobs: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden der aktiven Jobs"
        }), 500

@app.route('/api/dashboard/printers', methods=['GET'])
@login_required
def get_dashboard_printers():
    """Liefert Drucker-Status für Dashboard-Updates"""
    try:
        db_session = get_db_session()
        
        printers = db_session.query(Printer).limit(5).all()
        
        printers_data = []
        for printer in printers:
            printers_data.append({
                "id": printer.id,
                "name": printer.name,
                "status": printer.status,
                "location": printer.location,
                "model": printer.model
            })
        
        db_session.close()
        
        return jsonify({
            "success": True,
            "printers": printers_data
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Drucker: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden der Drucker"
        }), 500

@app.route('/api/dashboard/activities', methods=['GET'])
@login_required
def get_dashboard_activities():
    """Liefert die neuesten Aktivitäten für das Dashboard"""
    try:
        db_session = get_db_session()
        
        # Neueste Jobs abrufen
        activities = []
        recent_jobs = db_session.query(Job).order_by(Job.created_at.desc()).limit(10).all()
        
        for job in recent_jobs:
            activities.append({
                'description': f"Job '{job.name}' wurde {job.status}",
                'time': job.created_at.strftime('%H:%M'),
                'type': 'job',
                'status': job.status
            })
        
        db_session.close()
        return jsonify({
            'success': True,
            'activities': activities
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Dashboard-Aktivitäten: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Fehler beim Laden der Aktivitäten'
        }), 500

@app.route('/admin/settings', methods=['GET'])
@login_required
@admin_required
def admin_settings():
    """Admin-Einstellungen Seite"""
    try:
        return render_template('admin_settings.html')
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Einstellungen: {str(e)}")
        flash("Fehler beim Laden der Einstellungen", "error")
        return redirect(url_for('admin_page'))

@app.route('/analytics', methods=['GET'])
@login_required
def analytics_page():
    """Analytics Seite"""
    try:
        return render_template('analytics.html')
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Analytics-Seite: {str(e)}")
        flash("Fehler beim Laden der Analytics", "error")
        return redirect(url_for('dashboard'))

@app.route('/api/optimization/auto-optimize', methods=['POST'])
@login_required
def auto_optimize_jobs():
    """Automatische Optimierung der Druckaufträge durchführen"""
    try:
        data = request.get_json()
        settings = data.get('settings', {})
        enabled = data.get('enabled', False)
        
        db_session = get_db_session()
        
        # Aktuelle Jobs in der Warteschlange abrufen
        pending_jobs = db_session.query(Job).filter(
            Job.status.in_(['queued', 'pending'])
        ).all()
        
        if not pending_jobs:
            db_session.close()
            return jsonify({
                'success': True,
                'message': 'Keine Jobs zur Optimierung verfügbar',
                'optimized_jobs': 0
            })
        
        # Verfügbare Drucker abrufen
        available_printers = db_session.query(Printer).filter(Printer.active == True).all()
        
        if not available_printers:
            db_session.close()
            return jsonify({
                'success': False,
                'error': 'Keine verfügbaren Drucker für Optimierung'
            })
        
        # Optimierungs-Algorithmus anwenden
        algorithm = settings.get('algorithm', 'round_robin')
        optimized_count = 0
        
        if algorithm == 'round_robin':
            optimized_count = apply_round_robin_optimization(pending_jobs, available_printers, db_session)
        elif algorithm == 'load_balance':
            optimized_count = apply_load_balance_optimization(pending_jobs, available_printers, db_session)
        elif algorithm == 'priority_based':
            optimized_count = apply_priority_optimization(pending_jobs, available_printers, db_session)
        
        db_session.commit()
        jobs_logger.info(f"Auto-Optimierung durchgeführt: {optimized_count} Jobs optimiert mit Algorithmus {algorithm}")
        
        # System-Log erstellen
        log_entry = SystemLog(
            level='INFO',
            component='optimization',
            message=f'Auto-Optimierung durchgeführt: {optimized_count} Jobs optimiert',
            user_id=current_user.id if current_user.is_authenticated else None,
            details=json.dumps({
                'algorithm': algorithm,
                'optimized_jobs': optimized_count,
                'settings': settings
            })
        )
        db_session.add(log_entry)
        db_session.commit()
        db_session.close()
        
        return jsonify({
            'success': True,
            'optimized_jobs': optimized_count,
            'algorithm': algorithm,
            'message': f'Optimierung erfolgreich: {optimized_count} Jobs wurden optimiert'
        })
        
    except Exception as e:
        app_logger.error(f"Fehler bei der Auto-Optimierung: {str(e)}")
        return jsonify({
            'success': False,
            'error': f'Optimierung fehlgeschlagen: {str(e)}'
        }), 500

@app.route('/api/optimization/settings', methods=['GET', 'POST'])
@login_required
def optimization_settings():
    """Optimierungs-Einstellungen abrufen und speichern"""
    db_session = get_db_session()
    if request.method == 'GET':
        try:
            # Standard-Einstellungen oder benutzerdefinierte laden
            default_settings = {
                'algorithm': 'round_robin',
                'consider_distance': True,
                'minimize_changeover': True,
                'max_batch_size': 10,
                'time_window': 24,
                'auto_optimization_enabled': False
            }
            
            # Benutzereinstellungen aus der Session laden oder Standardwerte verwenden
            user_settings = session.get('user_settings', {})
            optimization_settings = user_settings.get('optimization', default_settings)
            
            # Sicherstellen, dass alle erforderlichen Schlüssel vorhanden sind
            for key, value in default_settings.items():
                if key not in optimization_settings:
                    optimization_settings[key] = value
            
            return jsonify({
                'success': True,
                'settings': optimization_settings
            })
            
        except Exception as e:
            app_logger.error(f"Fehler beim Abrufen der Optimierungs-Einstellungen: {str(e)}")
            return jsonify({
                'success': False,
                'error': 'Fehler beim Laden der Einstellungen'
            }), 500
    elif request.method == 'POST':
        try:
            settings = request.get_json()
            
            # Validierung der Einstellungen
            if not validate_optimization_settings(settings):
                return jsonify({
                    'success': False,
                    'error': 'Ungültige Optimierungs-Einstellungen'
                }), 400
            
            # Einstellungen in der Session speichern
            user_settings = session.get('user_settings', {})
            if 'optimization' not in user_settings:
                user_settings['optimization'] = {}
                
            # Aktualisiere die Optimierungseinstellungen
            user_settings['optimization'].update(settings)
            session['user_settings'] = user_settings
            
            # Einstellungen in der Datenbank speichern, wenn möglich
            if hasattr(current_user, 'settings'):
                import json
                current_user.settings = json.dumps(user_settings)
                current_user.updated_at = datetime.now()
                db_session.commit()
            
            app_logger.info(f"Optimierungs-Einstellungen für Benutzer {current_user.id} aktualisiert")
            
            return jsonify({
                'success': True,
                'message': 'Optimierungs-Einstellungen erfolgreich gespeichert'
            })
            
        except Exception as e:
            db_session.rollback()
            app_logger.error(f"Fehler beim Speichern der Optimierungs-Einstellungen: {str(e)}")
            return jsonify({
                'success': False,
                'error': f'Fehler beim Speichern der Einstellungen: {str(e)}'
            }), 500

# ===== OPTIMIERUNGS-ALGORITHMUS-FUNKTIONEN =====

def apply_round_robin_optimization(jobs, printers, db_session):
    """Round-Robin-Optimierung: Gleichmäßige Verteilung der Jobs auf Drucker"""
    optimized_count = 0
    printer_index = 0
    
    for job in jobs:
        if printer_index >= len(printers):
            printer_index = 0
        
        # Job dem nächsten Drucker zuweisen
        job.printer_id = printers[printer_index].id
        job.assigned_at = datetime.now()
        optimized_count += 1
        printer_index += 1
    
    return optimized_count

def apply_load_balance_optimization(jobs, printers, db_session):
    """Load-Balancing-Optimierung: Jobs basierend auf aktueller Auslastung verteilen"""
    optimized_count = 0
    
    # Aktuelle Drucker-Auslastung berechnen
    printer_loads = {}
    for printer in printers:
        current_jobs = db_session.query(Job).filter(
            Job.printer_id == printer.id,
            Job.status.in_(['running', 'queued'])
        ).count()
        printer_loads[printer.id] = current_jobs
    
    for job in jobs:
        # Drucker mit geringster Auslastung finden
        min_load_printer_id = min(printer_loads, key=printer_loads.get)
        
        job.printer_id = min_load_printer_id
        job.assigned_at = datetime.now()
        
        # Auslastung für nächste Iteration aktualisieren
        printer_loads[min_load_printer_id] += 1
        optimized_count += 1
    
    return optimized_count

def apply_priority_optimization(jobs, printers, db_session):
    """Prioritätsbasierte Optimierung: Jobs nach Priorität und verfügbaren Druckern verteilen"""
    optimized_count = 0
    
    # Jobs nach Priorität sortieren
    priority_order = {'urgent': 1, 'high': 2, 'normal': 3, 'low': 4}
    sorted_jobs = sorted(jobs, key=lambda j: priority_order.get(getattr(j, 'priority', 'normal'), 3))
    
    # Hochpriorisierte Jobs den besten verfügbaren Druckern zuweisen
    printer_assignments = {printer.id: 0 for printer in printers}
    
    for job in sorted_jobs:
        # Drucker mit geringster Anzahl zugewiesener Jobs finden
        best_printer_id = min(printer_assignments, key=printer_assignments.get)
        
        job.printer_id = best_printer_id
        job.assigned_at = datetime.now()
        
        printer_assignments[best_printer_id] += 1
        optimized_count += 1
    
    return optimized_count

def validate_optimization_settings(settings):
    """Validiert die Optimierungs-Einstellungen"""
    try:
        # Algorithmus validieren
        valid_algorithms = ['round_robin', 'load_balance', 'priority_based']
        if settings.get('algorithm') not in valid_algorithms:
            return False
        
        # Numerische Werte validieren
        max_batch_size = settings.get('max_batch_size', 10)
        if not isinstance(max_batch_size, int) or max_batch_size < 1 or max_batch_size > 50:
            return False
        
        time_window = settings.get('time_window', 24)
        if not isinstance(time_window, int) or time_window < 1 or time_window > 168:
            return False
        
        return True
        
    except Exception:
        return False

# ===== ERWEITERTE REFRESH-FUNKTIONEN =====

@app.route('/api/dashboard/refresh', methods=['POST'])
@login_required
def refresh_dashboard():
    """Aktualisiert Dashboard-Daten und gibt aktuelle Statistiken zurück"""
    try:
        db_session = get_db_session()
        
        # Aktuelle Statistiken abrufen
        stats = {
            'active_jobs': db_session.query(Job).filter(Job.status == 'running').count(),
            'available_printers': db_session.query(Printer).filter(Printer.active == True).count(),
            'total_jobs': db_session.query(Job).count(),
            'pending_jobs': db_session.query(Job).filter(Job.status == 'queued').count()
        }
        
        # Erfolgsrate berechnen
        total_jobs = stats['total_jobs']
        if total_jobs > 0:
            completed_jobs = db_session.query(Job).filter(Job.status == 'completed').count()
            stats['success_rate'] = round((completed_jobs / total_jobs) * 100, 1)
        else:
            stats['success_rate'] = 0
        
        db_session.close()
        
        return jsonify({
            'success': True,
            'stats': stats,
            'timestamp': datetime.now().isoformat()
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Dashboard-Refresh: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Fehler beim Aktualisieren der Dashboard-Daten'
        }), 500

# ===== ADMIN GASTAUFTRÄGE API-ENDPUNKTE =====

@app.route('/api/admin/guest-requests/test', methods=['GET'])
def test_admin_guest_requests():
    """Test-Endpunkt für Guest Requests Routing"""
    app_logger.info("Test-Route /api/admin/guest-requests/test aufgerufen")
    return jsonify({
        'success': True,
        'message': 'Test-Route funktioniert',
        'user_authenticated': current_user.is_authenticated,
        'user_is_admin': current_user.is_admin if current_user.is_authenticated else False
    })

@app.route('/api/admin/guest-requests', methods=['GET'])
@admin_required
def get_admin_guest_requests():
    """Gibt alle Gastaufträge für Admin-Verwaltung zurück"""
    try:
        app_logger.info(f"API-Aufruf /api/admin/guest-requests von User {current_user.id if current_user.is_authenticated else 'Anonymous'}")
        
        db_session = get_db_session()
        
        # Parameter auslesen
        status = request.args.get('status', 'all')
        limit = int(request.args.get('limit', 50))
        offset = int(request.args.get('offset', 0))
        search = request.args.get('search', '')
        
        # Basis-Query
        query = db_session.query(GuestRequest)
        
        # Status-Filter
        if status != 'all':
            query = query.filter(GuestRequest.status == status)
        
        # Suchfilter
        if search:
            search_term = f"%{search}%"
            query = query.filter(
                (GuestRequest.name.ilike(search_term)) |
                (GuestRequest.email.ilike(search_term)) |
                (GuestRequest.file_name.ilike(search_term)) |
                (GuestRequest.reason.ilike(search_term))
            )
        
        # Gesamtanzahl vor Pagination
        total = query.count()
        
        # Sortierung und Pagination
        requests = query.order_by(GuestRequest.created_at.desc()).offset(offset).limit(limit).all()
        
        # Statistiken berechnen
        stats = {
            'total': db_session.query(GuestRequest).count(),
            'pending': db_session.query(GuestRequest).filter(GuestRequest.status == 'pending').count(),
            'approved': db_session.query(GuestRequest).filter(GuestRequest.status == 'approved').count(),
            'rejected': db_session.query(GuestRequest).filter(GuestRequest.status == 'rejected').count(),
        }
        
        # Requests zu Dictionary konvertieren
        requests_data = []
        for req in requests:
            # Priorität berechnen
            now = datetime.now()
            hours_old = (now - req.created_at).total_seconds() / 3600 if req.created_at else 0
            is_urgent = hours_old > 24 and req.status == 'pending'
            
            request_data = {
                'id': req.id,
                'name': req.name,
                'email': req.email,
                'file_name': req.file_name,
                'file_path': req.file_path,
                'duration_minutes': req.duration_minutes,
                'copies': req.copies,
                'reason': req.reason,
                'status': req.status,
                'created_at': req.created_at.isoformat() if req.created_at else None,
                'updated_at': req.updated_at.isoformat() if req.updated_at else None,
                'approved_at': req.approved_at.isoformat() if req.approved_at else None,
                'rejected_at': req.rejected_at.isoformat() if req.rejected_at else None,
                'approval_notes': req.approval_notes,
                'rejection_reason': req.rejection_reason,
                'is_urgent': is_urgent,
                'hours_old': round(hours_old, 1)
            }
            requests_data.append(request_data)
        
        db_session.close()
        
        app_logger.info(f"Admin-Gastaufträge geladen: {len(requests_data)} von {total} (Status: {status})")
        
        return jsonify({
            'success': True,
            'requests': requests_data,
            'stats': stats,
            'total': total,
            'offset': offset,
            'limit': limit,
            'has_more': offset + limit < total
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Laden der Admin-Gastaufträge: {str(e)}", exc_info=True)
        return jsonify({
            'success': False,
            'message': f'Fehler beim Laden der Gastaufträge: {str(e)}'
        }), 500

@app.route('/api/guest-requests/<int:request_id>/approve', methods=['POST'])
@admin_required
def approve_guest_request(request_id):
    """Genehmigt einen Gastauftrag"""
    try:
        db_session = get_db_session()
        
        guest_request = db_session.query(GuestRequest).filter(GuestRequest.id == request_id).first()
        
        if not guest_request:
            db_session.close()
            return jsonify({
                'success': False,
                'message': 'Gastauftrag nicht gefunden'
            }), 404
        
        if guest_request.status != 'pending':
            db_session.close()
            return jsonify({
                'success': False,
                'message': f'Gastauftrag kann im Status "{guest_request.status}" nicht genehmigt werden'
            }), 400
        
        # Daten aus Request Body
        data = request.get_json() or {}
        notes = data.get('notes', '')
        printer_id = data.get('printer_id')
        
        # Status aktualisieren
        guest_request.status = 'approved'
        guest_request.approved_at = datetime.now()
        guest_request.approved_by = current_user.id
        guest_request.approval_notes = notes
        guest_request.updated_at = datetime.now()
        
        # Falls Drucker zugewiesen werden soll
        if printer_id:
            printer = db_session.query(Printer).filter(Printer.id == printer_id).first()
            if printer:
                guest_request.assigned_printer_id = printer_id
        
        # OTP-Code generieren für den Gast
        import secrets
        otp_code = ''.join([str(secrets.randbelow(10)) for _ in range(6)])
        guest_request.otp_code = otp_code
        guest_request.otp_expires_at = datetime.now() + timedelta(hours=24)
        
        db_session.commit()
        
        # Benachrichtigung an den Gast senden (falls E-Mail verfügbar)
        if guest_request.email:
            try:
                # Hier würde normalerweise eine E-Mail gesendet werden
                app_logger.info(f"E-Mail-Benachrichtigung würde an {guest_request.email} gesendet (OTP: {otp_code})")
            except Exception as e:
                app_logger.warning(f"Fehler beim Senden der E-Mail-Benachrichtigung: {str(e)}")
        
        db_session.close()
        
        app_logger.info(f"Gastauftrag {request_id} von Admin {current_user.id} genehmigt (OTP: {otp_code})")
        
        return jsonify({
            'success': True,
            'message': 'Gastauftrag erfolgreich genehmigt',
            'otp_code': otp_code,
            'expires_at': (datetime.now() + timedelta(hours=24)).isoformat()
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Genehmigen des Gastauftrags {request_id}: {str(e)}")
        return jsonify({
            'success': False,
            'message': f'Fehler beim Genehmigen: {str(e)}'
        }), 500

@app.route('/api/guest-requests/<int:request_id>/reject', methods=['POST'])
@admin_required
def reject_guest_request(request_id):
    """Lehnt einen Gastauftrag ab"""
    try:
        db_session = get_db_session()
        
        guest_request = db_session.query(GuestRequest).filter(GuestRequest.id == request_id).first()
        
        if not guest_request:
            db_session.close()
            return jsonify({
                'success': False,
                'message': 'Gastauftrag nicht gefunden'
            }), 404
        
        if guest_request.status != 'pending':
            db_session.close()
            return jsonify({
                'success': False,
                'message': f'Gastauftrag kann im Status "{guest_request.status}" nicht abgelehnt werden'
            }), 400
        
        # Daten aus Request Body
        data = request.get_json() or {}
        reason = data.get('reason', '').strip()
        
        if not reason:
            db_session.close()
            return jsonify({
                'success': False,
                'message': 'Ablehnungsgrund ist erforderlich'
            }), 400
        
        # Status aktualisieren
        guest_request.status = 'rejected'
        guest_request.rejected_at = datetime.now()
        guest_request.rejected_by = current_user.id
        guest_request.rejection_reason = reason
        guest_request.updated_at = datetime.now()
        
        db_session.commit()
        
        # Benachrichtigung an den Gast senden (falls E-Mail verfügbar)
        if guest_request.email:
            try:
                # Hier würde normalerweise eine E-Mail gesendet werden
                app_logger.info(f"Ablehnungs-E-Mail würde an {guest_request.email} gesendet (Grund: {reason})")
            except Exception as e:
                app_logger.warning(f"Fehler beim Senden der Ablehnungs-E-Mail: {str(e)}")
        
        db_session.close()
        
        app_logger.info(f"Gastauftrag {request_id} von Admin {current_user.id} abgelehnt (Grund: {reason})")
        
        return jsonify({
            'success': True,
            'message': 'Gastauftrag erfolgreich abgelehnt'
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Ablehnen des Gastauftrags {request_id}: {str(e)}")
        return jsonify({
            'success': False,
            'message': f'Fehler beim Ablehnen: {str(e)}'
        }), 500

@app.route('/api/guest-requests/<int:request_id>', methods=['DELETE'])
@admin_required
def delete_guest_request(request_id):
    """Löscht einen Gastauftrag"""
    try:
        db_session = get_db_session()
        
        guest_request = db_session.query(GuestRequest).filter(GuestRequest.id == request_id).first()
        
        if not guest_request:
            db_session.close()
            return jsonify({
                'success': False,
                'message': 'Gastauftrag nicht gefunden'
            }), 404
        
        # Datei löschen falls vorhanden
        if guest_request.file_path and os.path.exists(guest_request.file_path):
            try:
                os.remove(guest_request.file_path)
                app_logger.info(f"Datei {guest_request.file_path} für Gastauftrag {request_id} gelöscht")
            except Exception as e:
                app_logger.warning(f"Fehler beim Löschen der Datei: {str(e)}")
        
        # Gastauftrag aus Datenbank löschen
        request_name = guest_request.name
        db_session.delete(guest_request)
        db_session.commit()
        db_session.close()
        
        app_logger.info(f"Gastauftrag {request_id} ({request_name}) von Admin {current_user.id} gelöscht")
        
        return jsonify({
            'success': True,
            'message': 'Gastauftrag erfolgreich gelöscht'
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Löschen des Gastauftrags {request_id}: {str(e)}")
        return jsonify({
            'success': False,
            'message': f'Fehler beim Löschen: {str(e)}'
        }), 500

@app.route('/api/guest-requests/<int:request_id>', methods=['GET'])
@admin_required
def get_guest_request_detail(request_id):
    """Gibt Details eines spezifischen Gastauftrags zurück"""
    try:
        db_session = get_db_session()
        
        guest_request = db_session.query(GuestRequest).filter(GuestRequest.id == request_id).first()
        
        if not guest_request:
            db_session.close()
            return jsonify({
                'success': False,
                'message': 'Gastauftrag nicht gefunden'
            }), 404
        
        # Detaildaten zusammenstellen
        request_data = {
            'id': guest_request.id,
            'name': guest_request.name,
            'email': guest_request.email,
            'file_name': guest_request.file_name,
            'file_path': guest_request.file_path,
            'file_size': None,
            'duration_minutes': guest_request.duration_minutes,
            'copies': guest_request.copies,
            'reason': guest_request.reason,
            'status': guest_request.status,
            'created_at': guest_request.created_at.isoformat() if guest_request.created_at else None,
            'updated_at': guest_request.updated_at.isoformat() if guest_request.updated_at else None,
            'approved_at': guest_request.approved_at.isoformat() if guest_request.approved_at else None,
            'rejected_at': guest_request.rejected_at.isoformat() if guest_request.rejected_at else None,
            'approval_notes': guest_request.approval_notes,
            'rejection_reason': guest_request.rejection_reason,
            'otp_code': guest_request.otp_code,
            'otp_expires_at': guest_request.otp_expires_at.isoformat() if guest_request.otp_expires_at else None,
            'author_ip': guest_request.author_ip
        }
        
        # Dateigröße ermitteln
        if guest_request.file_path and os.path.exists(guest_request.file_path):
            try:
                file_size = os.path.getsize(guest_request.file_path)
                request_data['file_size'] = file_size
                request_data['file_size_mb'] = round(file_size / (1024 * 1024), 2)
            except Exception as e:
                app_logger.warning(f"Fehler beim Ermitteln der Dateigröße: {str(e)}")
        
        # Bearbeiter-Informationen hinzufügen
        if guest_request.approved_by:
            approved_by_user = db_session.query(User).filter(User.id == guest_request.approved_by).first()
            if approved_by_user:
                request_data['approved_by_name'] = approved_by_user.name or approved_by_user.username
        
        if guest_request.rejected_by:
            rejected_by_user = db_session.query(User).filter(User.id == guest_request.rejected_by).first()
            if rejected_by_user:
                request_data['rejected_by_name'] = rejected_by_user.name or rejected_by_user.username
        
        # Zugewiesener Drucker
        if hasattr(guest_request, 'assigned_printer_id') and guest_request.assigned_printer_id:
            assigned_printer = db_session.query(Printer).filter(Printer.id == guest_request.assigned_printer_id).first()
            if assigned_printer:
                request_data['assigned_printer'] = {
                    'id': assigned_printer.id,
                    'name': assigned_printer.name,
                    'location': assigned_printer.location,
                    'status': assigned_printer.status
                }
        
        db_session.close()
        
        return jsonify({
            'success': True,
            'request': request_data
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Gastauftrag-Details {request_id}: {str(e)}")
        return jsonify({
            'success': False,
            'message': f'Fehler beim Abrufen der Details: {str(e)}'
        }), 500

@app.route('/api/admin/guest-requests/stats', methods=['GET'])
@admin_required
def get_guest_requests_stats():
    """Gibt detaillierte Statistiken zu Gastaufträgen zurück"""
    try:
        db_session = get_db_session()
        
        # Basis-Statistiken
        total = db_session.query(GuestRequest).count()
        pending = db_session.query(GuestRequest).filter(GuestRequest.status == 'pending').count()
        approved = db_session.query(GuestRequest).filter(GuestRequest.status == 'approved').count()
        rejected = db_session.query(GuestRequest).filter(GuestRequest.status == 'rejected').count()
        
        # Zeitbasierte Statistiken
        today = datetime.now().date()
        week_ago = datetime.now() - timedelta(days=7)
        month_ago = datetime.now() - timedelta(days=30)
        
        today_requests = db_session.query(GuestRequest).filter(
            func.date(GuestRequest.created_at) == today
        ).count()
        
        week_requests = db_session.query(GuestRequest).filter(
            GuestRequest.created_at >= week_ago
        ).count()
        
        month_requests = db_session.query(GuestRequest).filter(
            GuestRequest.created_at >= month_ago
        ).count()
        
        # Dringende Requests (älter als 24h und pending)
        urgent_cutoff = datetime.now() - timedelta(hours=24)
        urgent_requests = db_session.query(GuestRequest).filter(
            GuestRequest.status == 'pending',
            GuestRequest.created_at < urgent_cutoff
        ).count()
        
        # Durchschnittliche Bearbeitungszeit
        avg_processing_time = None
        try:
            processed_requests = db_session.query(GuestRequest).filter(
                GuestRequest.status.in_(['approved', 'rejected']),
                GuestRequest.updated_at.isnot(None)
            ).all()
            
            if processed_requests:
                total_time = sum([
                    (req.updated_at - req.created_at).total_seconds() 
                    for req in processed_requests 
                    if req.updated_at and req.created_at
                ])
                avg_processing_time = round(total_time / len(processed_requests) / 3600, 2)  # Stunden
        except Exception as e:
            app_logger.warning(f"Fehler beim Berechnen der durchschnittlichen Bearbeitungszeit: {str(e)}")
        
        # Erfolgsrate
        success_rate = 0
        if approved + rejected > 0:
            success_rate = round((approved / (approved + rejected)) * 100, 1)
        
        stats = {
            'total': total,
            'pending': pending,
            'approved': approved,
            'rejected': rejected,
            'urgent': urgent_requests,
            'today': today_requests,
            'week': week_requests,
            'month': month_requests,
            'success_rate': success_rate,
            'avg_processing_time_hours': avg_processing_time,
            'completion_rate': round(((approved + rejected) / total * 100), 1) if total > 0 else 0
        }
        
        db_session.close()
        
        return jsonify({
            'success': True,
            'stats': stats,
            'generated_at': datetime.now().isoformat()
        })
        
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Gastauftrag-Statistiken: {str(e)}")
        return jsonify({
            'success': False,
            'message': f'Fehler beim Abrufen der Statistiken: {str(e)}'
        }), 500

@app.route('/api/admin/guest-requests/export', methods=['GET'])
@admin_required
def export_guest_requests():
    """Exportiert Gastaufträge als CSV"""
    try:
        db_session = get_db_session()
        
        # Filter-Parameter
        status = request.args.get('status', 'all')
        start_date = request.args.get('start_date')
        end_date = request.args.get('end_date')
        
        # Query aufbauen
        query = db_session.query(GuestRequest)
        
        if status != 'all':
            query = query.filter(GuestRequest.status == status)
        
        if start_date:
            try:
                start_dt = datetime.fromisoformat(start_date)
                query = query.filter(GuestRequest.created_at >= start_dt)
            except ValueError:
                pass
        
        if end_date:
            try:
                end_dt = datetime.fromisoformat(end_date)
                query = query.filter(GuestRequest.created_at <= end_dt)
            except ValueError:
                pass
        
        requests = query.order_by(GuestRequest.created_at.desc()).all()
        
        # CSV-Daten erstellen
        import csv
        import io
        
        output = io.StringIO()
        writer = csv.writer(output)
        
        # Header
        writer.writerow([
            'ID', 'Name', 'E-Mail', 'Datei', 'Status', 'Erstellt am', 
            'Dauer (Min)', 'Kopien', 'Begründung', 'Genehmigt am', 
            'Abgelehnt am', 'Bearbeitungsnotizen', 'Ablehnungsgrund'
        ])
        
        # Daten
        for req in requests:
            writer.writerow([
                req.id,
                req.name or '',
                req.email or '',
                req.file_name or '',
                req.status,
                req.created_at.strftime('%Y-%m-%d %H:%M:%S') if req.created_at else '',
                req.duration_minutes or '',
                req.copies or '',
                req.reason or '',
                req.approved_at.strftime('%Y-%m-%d %H:%M:%S') if req.approved_at else '',
                req.rejected_at.strftime('%Y-%m-%d %H:%M:%S') if req.rejected_at else '',
                req.approval_notes or '',
                req.rejection_reason or ''
            ])
        
        db_session.close()
        
        # Response erstellen
        output_value = output.getvalue()
        output.close()
        
        response = make_response(output_value)
        response.headers["Content-Disposition"] = f"attachment; filename=gastauftraege_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
        response.headers["Content-Type"] = "text/csv; charset=utf-8"
        
        app_logger.info(f"Gastaufträge-Export erstellt: {len(requests)} Einträge")
        
        return response
        
    except Exception as e:
        app_logger.error(f"Fehler beim Exportieren der Gastaufträge: {str(e)}")
        return jsonify({
            'success': False,
            'message': f'Fehler beim Export: {str(e)}'
        }), 500

# ===== ENDE ADMIN GASTAUFTRÄGE API-ENDPUNKTE =====

@app.route("/api/user/settings/auto-logout", methods=["GET"])
@login_required
def get_auto_logout_settings():
    """Holt nur die Auto-Logout-Einstellungen des Benutzers"""
    try:
        user_settings = session.get('user_settings', {})
        auto_logout = user_settings.get('privacy', {}).get('auto_logout', 60)
        
        return jsonify({
            "success": True,
            "auto_logout": auto_logout
        })
        
    except Exception as e:
        user_logger.error(f"Fehler beim Laden der Auto-Logout-Einstellungen: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Laden der Auto-Logout-Einstellungen"
        }), 500

@app.route("/api/user/setting", methods=["PATCH"])
@login_required
def update_single_setting():
    """Aktualisiert eine einzelne Benutzereinstellung"""
    try:
        if not request.is_json:
            return jsonify({"error": "Anfrage muss im JSON-Format sein"}), 400
            
        data = request.get_json()
        if not data:
            return jsonify({"error": "Keine Daten erhalten"}), 400
        
        # Aktuelle Einstellungen laden
        user_settings = session.get('user_settings', {
            "theme": "system",
            "reduced_motion": False,
            "contrast": "normal",
            "notifications": {
                "new_jobs": True,
                "job_updates": True,
                "system": True,
                "email": False
            },
            "privacy": {
                "activity_logs": True,
                "two_factor": False,
                "auto_logout": 60
            }
        })
        
        # Einzelne Einstellung aktualisieren
        for key, value in data.items():
            if key == "auto_logout":
                # Validierung für Auto-Logout
                try:
                    timeout = int(value) if value != "never" else "never"
                    if timeout != "never" and (timeout < 5 or timeout > 480):
                        return jsonify({"error": "Auto-Logout muss zwischen 5 und 480 Minuten liegen"}), 400
                    user_settings.setdefault('privacy', {})['auto_logout'] = timeout
                except (ValueError, TypeError):
                    return jsonify({"error": "Ungültiger Auto-Logout-Wert"}), 400
        
        user_settings['last_updated'] = datetime.now().isoformat()
        session['user_settings'] = user_settings
        
        user_logger.info(f"Benutzer {current_user.username} hat Einstellung '{key}' aktualisiert")
        
        return jsonify({
            "success": True,
            "message": "Einstellung erfolgreich aktualisiert"
        })
        
    except Exception as e:
        user_logger.error(f"Fehler beim Aktualisieren der Einzeleinstellung: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Aktualisieren der Einstellung"
        }), 500

@app.route("/api/auth/keep-alive", methods=["POST"])
@login_required
def keep_alive():
    """Keep-Alive-Endpunkt für Auto-Logout-System"""
    try:
        # Session-Timestamp aktualisieren
        session.permanent = True
        session.modified = True
        
        auth_logger.info(f"Keep-Alive für Benutzer {current_user.username}")
        
        return jsonify({
            "success": True,
            "message": "Session verlängert",
            "timestamp": datetime.now().isoformat()
        })
        
    except Exception as e:
        auth_logger.error(f"Fehler beim Keep-Alive: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Fehler beim Verlängern der Session"
        }), 500

# ===== FILE-UPLOAD-ROUTEN =====

@app.route('/api/upload/job', methods=['POST'])
@login_required
def upload_job_file():
    """
    Lädt eine Datei für einen Druckjob hoch
    
    Form Data:
        file: Die hochzuladende Datei
        job_name: Name des Jobs (optional)
    """
    try:
        if 'file' not in request.files:
            return jsonify({'error': 'Keine Datei ausgewählt'}), 400
        
        file = request.files['file']
        job_name = request.form.get('job_name', '')
        
        if file.filename == '':
            return jsonify({'error': 'Keine Datei ausgewählt'}), 400
        
        # Metadaten für die Datei
        metadata = {
            'uploader_id': current_user.id,
            'uploader_name': current_user.username,
            'job_name': job_name
        }
        
        # Datei speichern
        result = save_job_file(file, current_user.id, metadata)
        
        if result:
            relative_path, absolute_path, file_metadata = result
            
            app_logger.info(f"Job-Datei hochgeladen: {file_metadata['original_filename']} von User {current_user.id}")
            
            return jsonify({
                'success': True,
                'message': 'Datei erfolgreich hochgeladen',
                'file_path': relative_path,
                'filename': file_metadata['original_filename'],
                'unique_filename': file_metadata['unique_filename'],
                'file_size': file_metadata['file_size'],
                'metadata': file_metadata
            })
        else:
            return jsonify({'error': 'Fehler beim Speichern der Datei'}), 500
    
    except Exception as e:
        app_logger.error(f"Fehler beim Hochladen der Job-Datei: {str(e)}")
        return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500

@app.route('/api/upload/guest', methods=['POST'])
def upload_guest_file():
    """
    Lädt eine Datei für einen Gastauftrag hoch
    
    Form Data:
        file: Die hochzuladende Datei
        guest_name: Name des Gasts (optional)
        guest_email: E-Mail des Gasts (optional)
    """
    try:
        if 'file' not in request.files:
            return jsonify({'error': 'Keine Datei ausgewählt'}), 400
        
        file = request.files['file']
        guest_name = request.form.get('guest_name', '')
        guest_email = request.form.get('guest_email', '')
        
        if file.filename == '':
            return jsonify({'error': 'Keine Datei ausgewählt'}), 400
        
        # Metadaten für die Datei
        metadata = {
            'guest_name': guest_name,
            'guest_email': guest_email
        }
        
        # Datei speichern
        result = save_guest_file(file, metadata)
        
        if result:
            relative_path, absolute_path, file_metadata = result
            
            app_logger.info(f"Gast-Datei hochgeladen: {file_metadata['original_filename']} für {guest_name or 'Unbekannt'}")
            
            return jsonify({
                'success': True,
                'message': 'Datei erfolgreich hochgeladen',
                'file_path': relative_path,
                'filename': file_metadata['original_filename'],
                'unique_filename': file_metadata['unique_filename'],
                'file_size': file_metadata['file_size'],
                'metadata': file_metadata
            })
        else:
            return jsonify({'error': 'Fehler beim Speichern der Datei'}), 500
    
    except Exception as e:
        app_logger.error(f"Fehler beim Hochladen der Gast-Datei: {str(e)}")
        return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500

@app.route('/api/upload/avatar', methods=['POST'])
@login_required
def upload_avatar():
    """
    Lädt ein Avatar-Bild für den aktuellen Benutzer hoch
    
    Form Data:
        file: Das Avatar-Bild
    """
    try:
        if 'file' not in request.files:
            return jsonify({'error': 'Keine Datei ausgewählt'}), 400
        
        file = request.files['file']
        
        if file.filename == '':
            return jsonify({'error': 'Keine Datei ausgewählt'}), 400
        
        # Nur Bilder erlauben
        allowed_extensions = {'png', 'jpg', 'jpeg', 'gif', 'webp'}
        if not file.filename or '.' not in file.filename:
            return jsonify({'error': 'Ungültiger Dateityp'}), 400
        
        file_ext = file.filename.rsplit('.', 1)[1].lower()
        if file_ext not in allowed_extensions:
            return jsonify({'error': 'Nur Bilddateien sind erlaubt (PNG, JPG, JPEG, GIF, WebP)'}), 400
        
        # Alte Avatar-Datei löschen falls vorhanden
        db_session = get_db_session()
        user = db_session.query(User).get(current_user.id)
        if user and user.avatar_path:
            delete_file_safe(user.avatar_path)
        
        # Neue Avatar-Datei speichern
        result = save_avatar_file(file, current_user.id)
        
        if result:
            relative_path, absolute_path, file_metadata = result
            
            # Benutzer-Avatar-Pfad in Datenbank aktualisieren
            user.avatar_path = relative_path
            db_session.commit()
            db_session.close()
            
            app_logger.info(f"Avatar hochgeladen für User {current_user.id}: {file_metadata['original_filename']}")
            
            return jsonify({
                'success': True,
                'message': 'Avatar erfolgreich hochgeladen',
                'avatar_path': relative_path,
                'filename': file_metadata['original_filename'],
                'file_size': file_metadata['file_size']
            })
        else:
            db_session.close()
            return jsonify({'error': 'Fehler beim Speichern des Avatars'}), 500
    
    except Exception as e:
        app_logger.error(f"Fehler beim Hochladen des Avatars: {str(e)}")
        return jsonify({'error': f'Fehler beim Hochladen: {str(e)}'}), 500

@app.route('/api/files/<path:file_path>', methods=['GET'])
@login_required
def serve_uploaded_file(file_path):
    """
    Stellt hochgeladene Dateien bereit (mit Zugriffskontrolle)
    """
    try:
        # Datei-Info abrufen
        file_info = file_manager.get_file_info(file_path)
        
        if not file_info:
            return jsonify({'error': 'Datei nicht gefunden'}), 404
        
        # Zugriffskontrolle basierend auf Dateikategorie
        if file_path.startswith('jobs/'):
            # Job-Dateien: Nur Besitzer und Admins
            if not current_user.is_admin:
                # Prüfen ob Benutzer der Besitzer ist
                if f"user_{current_user.id}" not in file_path:
                    return jsonify({'error': 'Zugriff verweigert'}), 403
        
        elif file_path.startswith('guests/'):
            # Gast-Dateien: Nur Admins
            if not current_user.is_admin:
                return jsonify({'error': 'Zugriff verweigert'}), 403
        
        elif file_path.startswith('avatars/'):
            # Avatar-Dateien: Öffentlich zugänglich für angemeldete Benutzer
            pass
        
        else:
            # Andere Dateien: Nur Admins
            if not current_user.is_admin:
                return jsonify({'error': 'Zugriff verweigert'}), 403
        
        # Datei bereitstellen
        return send_file(file_info['absolute_path'], as_attachment=False)
    
    except Exception as e:
        app_logger.error(f"Fehler beim Bereitstellen der Datei {file_path}: {str(e)}")
        return jsonify({'error': 'Fehler beim Laden der Datei'}), 500

@app.route('/api/files/<path:file_path>', methods=['DELETE'])
@login_required
def delete_uploaded_file(file_path):
    """
    Löscht eine hochgeladene Datei (mit Zugriffskontrolle)
    """
    try:
        # Zugriffskontrolle
        if file_path.startswith('jobs/'):
            if not current_user.is_admin and f"user_{current_user.id}" not in file_path:
                return jsonify({'error': 'Zugriff verweigert'}), 403
        elif not current_user.is_admin:
            return jsonify({'error': 'Zugriff verweigert'}), 403
        
        # Datei löschen
        success = delete_file_safe(file_path)
        
        if success:
            app_logger.info(f"Datei gelöscht: {file_path} von User {current_user.id}")
            return jsonify({'success': True, 'message': 'Datei erfolgreich gelöscht'})
        else:
            return jsonify({'error': 'Datei konnte nicht gelöscht werden'}), 500
    
    except Exception as e:
        app_logger.error(f"Fehler beim Löschen der Datei {file_path}: {str(e)}")
        return jsonify({'error': f'Fehler beim Löschen: {str(e)}'}), 500

@app.route('/api/admin/files/stats', methods=['GET'])
@admin_required
def get_file_statistics():
    """
    Gibt Statistiken über alle hochgeladenen Dateien zurück (nur für Admins)
    """
    try:
        stats = file_manager.get_category_stats()
        
        # Gesamtstatistiken berechnen
        total_files = sum(cat_stats['file_count'] for cat_stats in stats.values())
        total_size = sum(cat_stats['total_size'] for cat_stats in stats.values())
        total_size_mb = round(total_size / (1024 * 1024), 2)
        
        return jsonify({
            'success': True,
            'categories': stats,
            'totals': {
                'file_count': total_files,
                'total_size': total_size,
                'total_size_mb': total_size_mb
            }
        })
    
    except Exception as e:
        app_logger.error(f"Fehler beim Abrufen der Datei-Statistiken: {str(e)}")
        return jsonify({'error': f'Fehler beim Abrufen der Statistiken: {str(e)}'}), 500

@app.route('/api/admin/files/cleanup', methods=['POST'])
@admin_required
def cleanup_temp_files():
    """
    Räumt temporäre Dateien auf (nur für Admins)
    """
    try:
        max_age_hours = request.json.get('max_age_hours', 24)
        deleted_count = file_manager.cleanup_temp_files(max_age_hours)
        
        app_logger.info(f"Temporäre Dateien aufgeräumt: {deleted_count} Dateien gelöscht (älter als {max_age_hours}h)")
        
        return jsonify({
            'success': True,
            'message': f'{deleted_count} temporäre Dateien gelöscht',
            'deleted_count': deleted_count
        })
    
    except Exception as e:
        app_logger.error(f"Fehler beim Aufräumen temporärer Dateien: {str(e)}")
        return jsonify({'error': f'Fehler beim Aufräumen: {str(e)}'}), 500

# ===== FEHLENDE DRUCKER-SPEZIFISCHE API-ENDPOINTS =====

@app.route("/api/printers/<int:printer_id>/jobs", methods=["GET"])
@login_required
def get_printer_jobs(printer_id):
    """Gibt alle Jobs für einen spezifischen Drucker zurück."""
    try:
        db_session = get_db_session()
        
        # Prüfen ob Drucker existiert
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Jobs für diesen Drucker abrufen
        jobs = db_session.query(Job).filter(Job.printer_id == printer_id).order_by(Job.created_at.desc()).all()
        
        jobs_data = []
        for job in jobs:
            job_data = {
                "id": job.id,
                "title": job.title,
                "status": job.status,
                "priority": job.priority,
                "created_at": job.created_at.isoformat() if job.created_at else None,
                "scheduled_time": job.scheduled_time.isoformat() if job.scheduled_time else None,
                "started_at": job.started_at.isoformat() if job.started_at else None,
                "finished_at": job.finished_at.isoformat() if job.finished_at else None,
                "estimated_duration": job.estimated_duration,
                "user_id": job.user_id,
                "printer_id": job.printer_id,
                "printer_name": printer.name
            }
            jobs_data.append(job_data)
        
        db_session.close()
        
        return jsonify({
            "jobs": jobs_data,
            "total": len(jobs_data),
            "printer": {
                "id": printer.id,
                "name": printer.name,
                "status": printer.status
            }
        })
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Abrufen der Jobs für Drucker {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/printers/<int:printer_id>/stats", methods=["GET"])
@login_required
def get_printer_stats(printer_id):
    """Gibt Statistiken für einen spezifischen Drucker zurück."""
    try:
        db_session = get_db_session()
        
        # Prüfen ob Drucker existiert
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # Statistiken berechnen
        total_jobs = db_session.query(Job).filter(Job.printer_id == printer_id).count()
        completed_jobs = db_session.query(Job).filter(
            Job.printer_id == printer_id,
            Job.status == "completed"
        ).count()
        failed_jobs = db_session.query(Job).filter(
            Job.printer_id == printer_id,
            Job.status == "failed"
        ).count()
        active_jobs = db_session.query(Job).filter(
            Job.printer_id == printer_id,
            Job.status.in_(["scheduled", "running"])
        ).count()
        
        # Durchschnittliche Job-Dauer berechnen
        avg_duration_result = db_session.query(func.avg(Job.estimated_duration)).filter(
            Job.printer_id == printer_id,
            Job.status == "completed",
            Job.estimated_duration.isnot(None)
        ).scalar()
        
        avg_duration = round(avg_duration_result, 2) if avg_duration_result else 0
        
        # Erfolgsrate berechnen
        success_rate = round((completed_jobs / total_jobs * 100), 2) if total_jobs > 0 else 0
        
        # Letzte Aktivität
        last_job = db_session.query(Job).filter(Job.printer_id == printer_id).order_by(Job.created_at.desc()).first()
        last_activity = last_job.created_at.isoformat() if last_job and last_job.created_at else None
        
        db_session.close()
        
        stats_data = {
            "printer": {
                "id": printer.id,
                "name": printer.name,
                "status": printer.status,
                "location": printer.location
            },
            "jobs": {
                "total": total_jobs,
                "completed": completed_jobs,
                "failed": failed_jobs,
                "active": active_jobs,
                "success_rate": success_rate
            },
            "performance": {
                "average_duration": avg_duration,
                "last_activity": last_activity
            },
            "generated_at": datetime.now().isoformat()
        }
        
        return jsonify(stats_data)
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Abrufen der Statistiken für Drucker {printer_id}: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/api/printers/<int:printer_id>/test", methods=["POST"])
@login_required
def test_printer_connection(printer_id):
    """Testet die Verbindung zu einem spezifischen Drucker."""
    try:
        db_session = get_db_session()
        
        # Prüfen ob Drucker existiert
        printer = db_session.query(Printer).get(printer_id)
        if not printer:
            db_session.close()
            return jsonify({"error": "Drucker nicht gefunden"}), 404
        
        # IP-Adresse für Test ermitteln
        ip_to_test = printer.plug_ip if printer.plug_ip else getattr(printer, 'ip_address', None)
        
        if not ip_to_test:
            db_session.close()
            return jsonify({
                "success": False,
                "error": "Keine IP-Adresse für Drucker konfiguriert",
                "printer": {
                    "id": printer.id,
                    "name": printer.name
                }
            }), 400
        
        # Verbindungstest durchführen
        printers_logger.info(f"Teste Verbindung zu Drucker {printer.name} (ID: {printer_id}) auf IP {ip_to_test}")
        
        status, active = check_printer_status(ip_to_test, timeout=10)
        
        # Status in Datenbank aktualisieren
        printer.status = "available" if status == "online" else "offline"
        if hasattr(printer, 'active'):
            printer.active = active
        db_session.commit()
        
        test_result = {
            "success": status == "online",
            "status": status,
            "active": active,
            "ip_address": ip_to_test,
            "printer": {
                "id": printer.id,
                "name": printer.name,
                "location": printer.location,
                "model": printer.model
            },
            "test_time": datetime.now().isoformat(),
            "message": f"Drucker ist {'online und erreichbar' if status == 'online' else 'offline oder nicht erreichbar'}"
        }
        
        db_session.close()
        
        printers_logger.info(f"Verbindungstest für Drucker {printer.name}: {status}")
        
        return jsonify(test_result)
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Testen der Verbindung zu Drucker {printer_id}: {str(e)}")
        return jsonify({
            "success": False,
            "error": "Interner Serverfehler beim Verbindungstest",
            "details": str(e)
        }), 500

# ===== ADMIN-SPEZIFISCHE DRUCKER-ENDPOINTS =====

@app.route("/api/admin/printers/create", methods=["POST"])
@login_required
@admin_required
def admin_create_printer_api():
    """Admin-Endpoint zum Erstellen neuer Drucker."""
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({"error": "Keine Daten empfangen"}), 400
        
        # Pflichtfelder prüfen
        required_fields = ["name", "plug_ip"]
        for field in required_fields:
            if field not in data or not data[field]:
                return jsonify({"error": f"Feld '{field}' ist erforderlich"}), 400
        
        db_session = get_db_session()
        
        # Prüfen, ob bereits ein Drucker mit diesem Namen existiert
        existing_printer = db_session.query(Printer).filter(Printer.name == data["name"]).first()
        if existing_printer:
            db_session.close()
            return jsonify({"error": "Ein Drucker mit diesem Namen existiert bereits"}), 400
        
        # Neuen Drucker erstellen
        new_printer = Printer(
            name=data["name"],
            model=data.get("model", ""),
            location=data.get("location", ""),
            mac_address=data.get("mac_address", ""),
            plug_ip=data["plug_ip"],
            status="offline",
            active=True,
            created_at=datetime.now()
        )
        
        db_session.add(new_printer)
        db_session.commit()
        
        # Sofortiger Status-Check
        if new_printer.plug_ip:
            status, active = check_printer_status(new_printer.plug_ip)
            new_printer.status = "available" if status == "online" else "offline"
            new_printer.active = active
            db_session.commit()
        
        printer_data = {
            "id": new_printer.id,
            "name": new_printer.name,
            "model": new_printer.model,
            "location": new_printer.location,
            "mac_address": new_printer.mac_address,
            "plug_ip": new_printer.plug_ip,
            "status": new_printer.status,
            "active": new_printer.active,
            "created_at": new_printer.created_at.isoformat()
        }
        
        db_session.close()
        
        printers_logger.info(f"Admin {current_user.name} hat Drucker '{new_printer.name}' erstellt")
        
        return jsonify({
            "success": True,
            "message": "Drucker erfolgreich erstellt",
            "printer": printer_data
        }), 201
        
    except Exception as e:
        printers_logger.error(f"Fehler beim Erstellen eines Druckers durch Admin: {str(e)}")
        return jsonify({"error": "Interner Serverfehler"}), 500

@app.route("/debug/tapo-test", methods=["GET"])
@login_required
@admin_required
def debug_tapo_test():
    """
    DEBUG-Route: Testet alle bekannten Tapo-Steckdosen-IPs direkt.
    """
    from config.settings import TAPO_USERNAME, TAPO_PASSWORD, DEFAULT_TAPO_IPS
    
    results = []
    
    # Alle bekannten IPs testen
    test_ips = [
        "192.168.1.100", "192.168.1.101", "192.168.1.102", 
        "192.168.1.103", "192.168.1.104", "192.168.1.105",
        "192.168.0.100", "192.168.0.101", "192.168.0.102",
        "192.168.0.103", "192.168.0.104", "192.168.0.105"
    ]
    
    app_logger.info(f"🔍 DEBUG: Teste {len(test_ips)} Tapo-Steckdosen-IPs...")
    
    for ip in test_ips:
        result = {
            "ip": ip,
            "ping_success": False,
            "tapo_success": False,
            "device_on": False,
            "device_info": None,
            "error": None
        }
        
        # 1. Ping-Test
        try:
            import subprocess
            ping_result = subprocess.run(
                ['ping', '-n', '1', '-w', '1000', ip], 
                capture_output=True, 
                text=True, 
                timeout=2
            )
            result["ping_success"] = ping_result.returncode == 0
        except Exception as e:
            result["error"] = f"Ping-Fehler: {str(e)}"
        
        # 2. Tapo-Test (nur wenn Ping erfolgreich)
        if result["ping_success"]:
            try:
                from PyP100 import PyP110
                
                p110 = PyP110.P110(ip, TAPO_USERNAME, TAPO_PASSWORD)
                p110.handshake()
                p110.login()
                
                device_info = p110.getDeviceInfo()
                result["tapo_success"] = True
                result["device_on"] = device_info.get('device_on', False)
                result["device_info"] = {
                    "nickname": device_info.get('nickname', 'Unbekannt'),
                    "model": device_info.get('model', 'Unbekannt'),
                    "device_id": device_info.get('device_id', 'Unbekannt'),
                    "fw_ver": device_info.get('fw_ver', 'Unbekannt')
                }
                
            except Exception as e:
                result["error"] = f"Tapo-Fehler: {str(e)}"
        
        results.append(result)
        app_logger.info(f"  {ip}: Ping={result['ping_success']}, Tapo={result['tapo_success']}, Ein={result['device_on']}")
    
    # HTML-Response für bessere Darstellung
    html = """
    <!DOCTYPE html>
    <html>
    <head>
        <title>Tapo-Steckdosen Debug-Test</title>
        <style>
            body { font-family: Arial, sans-serif; margin: 20px; }
            .success { color: green; font-weight: bold; }
            .error { color: red; font-weight: bold; }
            .warning { color: orange; font-weight: bold; }
            table { border-collapse: collapse; width: 100%; }
            th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
            th { background-color: #f2f2f2; }
            .status-on { background-color: #d4edda; }
            .status-off { background-color: #f8d7da; }
            .status-error { background-color: #fff3cd; }
        </style>
    </head>
    <body>
        <h1>🔌 Tapo-Steckdosen Debug-Test</h1>
        <p><strong>Benutzername:</strong> """ + TAPO_USERNAME + """</p>
        <p><strong>Passwort:</strong> """ + ("*" * len(TAPO_PASSWORD)) + """</p>
        <hr>
        
        <table>
            <tr>
                <th>IP-Adresse</th>
                <th>Ping</th>
                <th>Tapo-Verbindung</th>
                <th>Status</th>
                <th>Gerätename</th>
                <th>Modell</th>
                <th>Fehler</th>
            </tr>
    """
    
    found_count = 0
    online_count = 0
    
    for result in results:
        if result["tapo_success"]:
            found_count += 1
            if result["device_on"]:
                online_count += 1
        
        # Zeilen-CSS-Klasse basierend auf Status
        if result["tapo_success"]:
            if result["device_on"]:
                row_class = "status-on"
                status_text = "🟢 EIN"
            else:
                row_class = "status-off"
                status_text = "🔴 AUS"
        else:
            row_class = "status-error"
            status_text = "❌ FEHLER"
        
        html += f"""
            <tr class="{row_class}">
                <td><strong>{result['ip']}</strong></td>
                <td>{'✅' if result['ping_success'] else '❌'}</td>
                <td>{'✅' if result['tapo_success'] else '❌'}</td>
                <td>{status_text}</td>
                <td>{result['device_info']['nickname'] if result['device_info'] else '-'}</td>
                <td>{result['device_info']['model'] if result['device_info'] else '-'}</td>
                <td>{result['error'] or '-'}</td>
            </tr>
        """
    
    html += f"""
        </table>
        
        <hr>
        <h2>📊 Zusammenfassung</h2>
        <p><strong>Gefundene Steckdosen:</strong> <span class="{'success' if found_count > 0 else 'error'}">{found_count}</span></p>
        <p><strong>Eingeschaltete Steckdosen:</strong> <span class="{'success' if online_count > 0 else 'warning'}">{online_count}</span></p>
        <p><strong>Ausgeschaltete Steckdosen:</strong> {found_count - online_count}</p>
        
        <hr>
        <h2>🔧 Nächste Schritte</h2>
        <ul>
            <li>Gefundene Steckdosen in der Datenbank als Drucker anlegen</li>
            <li>Plugin-IPs der vorhandenen Drucker auf die gefundenen IPs setzen</li>
            <li>Tapo-Anmeldedaten in den Drucker-Einstellungen speichern</li>
        </ul>
        
        <p><a href="/admin-dashboard">← Zurück zum Admin-Dashboard</a></p>
    </body>
    </html>
    """
    
    return html

# ===== STARTUP UND MAIN =====
if __name__ == "__main__":
    import sys
    import signal
    import os
    
    # Debug-Modus prüfen
    debug_mode = len(sys.argv) > 1 and sys.argv[1] == "--debug"
    
    # Windows-spezifische Umgebungsvariablen setzen für bessere Flask-Kompatibilität
    if os.name == 'nt' and debug_mode:
        # Entferne problematische Werkzeug-Variablen
        os.environ.pop('WERKZEUG_SERVER_FD', None)
        os.environ.pop('WERKZEUG_RUN_MAIN', None)
        
        # Setze saubere Umgebung
        os.environ['FLASK_ENV'] = 'development'
        os.environ['PYTHONIOENCODING'] = 'utf-8'
        os.environ['PYTHONUTF8'] = '1'
    
    # Windows-spezifisches Signal-Handling für ordnungsgemäßes Shutdown
    def signal_handler(sig, frame):
        """Signal-Handler für ordnungsgemäßes Shutdown."""
        app_logger.warning(f"🛑 Signal {sig} empfangen - fahre System herunter...")
        try:
            # Queue Manager stoppen
            app_logger.info("🔄 Beende Queue Manager...")
            stop_queue_manager()
            
            # Scheduler stoppen falls aktiviert
            if SCHEDULER_ENABLED and scheduler:
                try:
                    scheduler.stop()
                    app_logger.info("Job-Scheduler gestoppt")
                except Exception as e:
                    app_logger.error(f"Fehler beim Stoppen des Schedulers: {str(e)}")
            
            app_logger.info("✅ Shutdown abgeschlossen")
            sys.exit(0)
        except Exception as e:
            app_logger.error(f"❌ Fehler beim Shutdown: {str(e)}")
            sys.exit(1)
    
    
    # Signal-Handler registrieren (Windows-kompatibel)
    if os.name == 'nt':  # Windows
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)
        # Zusätzlich für Flask-Development-Server
        signal.signal(signal.SIGBREAK, signal_handler)
    else:  # Unix/Linux
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)
        signal.signal(signal.SIGHUP, signal_handler)
    
    try:
        # Datenbank initialisieren
        init_database()
        create_initial_admin()
        
        # Template-Hilfsfunktionen registrieren
        register_template_helpers(app)
        
        # Drucker-Monitor Steckdosen-Initialisierung beim Start
        try:
            app_logger.info("🖨️ Starte automatische Steckdosen-Initialisierung...")
            initialization_results = printer_monitor.initialize_all_outlets_on_startup()
            
            if initialization_results:
                success_count = sum(1 for success in initialization_results.values() if success)
                total_count = len(initialization_results)
                app_logger.info(f"✅ Steckdosen-Initialisierung: {success_count}/{total_count} Drucker erfolgreich")
                
                if success_count < total_count:
                    app_logger.warning(f"⚠️ {total_count - success_count} Drucker konnten nicht initialisiert werden")
            else:
                app_logger.info("ℹ️ Keine Drucker zur Initialisierung gefunden")
                
        except Exception as e:
            app_logger.error(f"❌ Fehler bei automatischer Steckdosen-Initialisierung: {str(e)}")
        
        # Queue-Manager für automatische Drucker-Überwachung starten
        # Nur im Produktionsmodus starten (nicht im Debug-Modus)
        if not debug_mode:
            try:
                queue_manager = start_queue_manager()
                app_logger.info("✅ Printer Queue Manager erfolgreich gestartet")
                
                # Verbesserte Shutdown-Handler registrieren
                def cleanup_queue_manager():
                    try:
                        app_logger.info("🔄 Beende Queue Manager...")
                        stop_queue_manager()
                    except Exception as e:
                        app_logger.error(f"❌ Fehler beim Queue Manager Cleanup: {str(e)}")
                    
                atexit.register(cleanup_queue_manager)
                
            except Exception as e:
                app_logger.error(f"❌ Fehler beim Starten des Queue-Managers: {str(e)}")
        else:
            app_logger.info("🔄 Debug-Modus: Queue Manager deaktiviert für Entwicklung")
        
        # Scheduler starten (falls aktiviert)
        if SCHEDULER_ENABLED:
            try:
                scheduler.start()
                app_logger.info("Job-Scheduler gestartet")
            except Exception as e:
                app_logger.error(f"Fehler beim Starten des Schedulers: {str(e)}")
        
        if debug_mode:
            # Debug-Modus: HTTP auf Port 5000
            app_logger.info("Starte Debug-Server auf 0.0.0.0:5000 (HTTP)")
            
            # Windows-spezifische Flask-Konfiguration
            run_kwargs = {
                "host": "0.0.0.0",
                "port": 5000,
                "debug": True,
                "threaded": True
            }
            
            if os.name == 'nt':
                # Windows: Deaktiviere Auto-Reload um WERKZEUG_SERVER_FD Fehler zu vermeiden
                run_kwargs["use_reloader"] = False
                run_kwargs["passthrough_errors"] = False
                app_logger.info("Windows-Debug-Modus: Auto-Reload deaktiviert")
            
            app.run(**run_kwargs)
        else:
            # Produktions-Modus: HTTPS auf Port 443
            ssl_context = get_ssl_context()
            
            if ssl_context:
                app_logger.info("Starte HTTPS-Server auf 0.0.0.0:443")
                app.run(
                    host="0.0.0.0",
                    port=443,
                    debug=False,
                    ssl_context=ssl_context,
                    threaded=True
                )
            else:
                app_logger.info("Starte HTTP-Server auf 0.0.0.0:8080")
                app.run(
                    host="0.0.0.0",
                    port=8080,
                    debug=False,
                    threaded=True
                )
            
    except KeyboardInterrupt:
        app_logger.info("🔄 Tastatur-Unterbrechung empfangen - beende Anwendung...")
        signal_handler(signal.SIGINT, None)
    except Exception as e:
        app_logger.error(f"Fehler beim Starten der Anwendung: {str(e)}")
        # Cleanup bei Fehler
        try:
            stop_queue_manager()
        except:
            pass
        sys.exit(1)