"""
API-Blueprint für das 3D-Druck-Management-System

Dieses Modul enthält allgemeine API-Endpunkte und WebSocket-Fallback-Funktionalität.
"""

import logging
from datetime import datetime, timedelta
from flask import Blueprint, jsonify, request, session
from flask_login import login_required, current_user
from models import get_db_session, User, Notification, Printer, Job, Stats
from utils.logging_config import get_logger
from utils.permissions import admin_required

# Blueprint erstellen
api_blueprint = Blueprint('api', __name__, url_prefix='/api')

# Logger initialisieren
api_logger = get_logger("api")

@api_blueprint.route('/ws-fallback', methods=['GET'])
@login_required
def ws_fallback():
    """WebSocket-Fallback für Browser ohne WebSocket-Unterstützung"""
    try:
        # Einfache Polling-Antwort für Clients ohne WebSocket
        return jsonify({
            'success': True,
            'timestamp': datetime.now().isoformat(),
            'user_id': current_user.id,
            'message': 'WebSocket-Fallback aktiv'
        })
    except Exception as e:
        api_logger.error(f"Fehler im WebSocket-Fallback: {str(e)}")
        return jsonify({'error': 'WebSocket-Fallback-Fehler'}), 500

@api_blueprint.route('/notifications', methods=['GET'])
@login_required
def get_notifications():
    """Abrufen der Benutzer-Benachrichtigungen"""
    try:
        db_session = get_db_session()
        
        # Benutzer-spezifische Benachrichtigungen
        notifications = db_session.query(Notification).filter(
            Notification.user_id == current_user.id,
            Notification.is_read == False
        ).order_by(Notification.created_at.desc()).limit(20).all()
        
        notification_list = []
        for notification in notifications:
            notification_list.append({
                'id': notification.id,
                'title': notification.title,
                'message': notification.message,
                'type': notification.type,
                'created_at': notification.created_at.isoformat(),
                'is_read': notification.is_read
            })
        
        db_session.close()
        
        return jsonify({
            'success': True,
            'notifications': notification_list,
            'count': len(notification_list)
        })
        
    except Exception as e:
        api_logger.error(f"Fehler beim Abrufen der Benachrichtigungen: {str(e)}")
        return jsonify({'error': 'Fehler beim Laden der Benachrichtigungen'}), 500

@api_blueprint.route('/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()
        
        # Benachrichtigung finden und prüfen ob sie dem aktuellen Benutzer gehört
        notification = db_session.query(Notification).filter(
            Notification.id == notification_id,
            Notification.user_id == current_user.id
        ).first()
        
        if not notification:
            return jsonify({'error': 'Benachrichtigung nicht gefunden'}), 404
        
        # Als gelesen markieren
        notification.is_read = True
        notification.read_at = datetime.now()
        
        db_session.commit()
        db_session.close()
        
        api_logger.info(f"Benachrichtigung {notification_id} als gelesen markiert von Benutzer {current_user.id}")
        
        return jsonify({
            'success': True,
            'message': 'Benachrichtigung als gelesen markiert'
        })
        
    except Exception as e:
        api_logger.error(f"Fehler beim Markieren der Benachrichtigung als gelesen: {str(e)}")
        return jsonify({'error': 'Fehler beim Markieren als gelesen'}), 500

@api_blueprint.route('/notifications/mark-all-read', methods=['POST'])
@login_required
def mark_all_notifications_read():
    """Markiert alle Benachrichtigungen des Benutzers als gelesen"""
    try:
        db_session = get_db_session()
        
        # Alle ungelesenen Benachrichtigungen des Benutzers finden
        unread_notifications = db_session.query(Notification).filter(
            Notification.user_id == current_user.id,
            Notification.is_read == False
        ).all()
        
        # Alle als gelesen markieren
        for notification in unread_notifications:
            notification.is_read = True
            notification.read_at = datetime.now()
        
        db_session.commit()
        
        count = len(unread_notifications)
        db_session.close()
        
        api_logger.info(f"{count} Benachrichtigungen als gelesen markiert von Benutzer {current_user.id}")
        
        return jsonify({
            'success': True,
            'message': f'{count} Benachrichtigungen als gelesen markiert',
            'count': count
        })
        
    except Exception as e:
        api_logger.error(f"Fehler beim Markieren aller Benachrichtigungen als gelesen: {str(e)}")
        return jsonify({'error': 'Fehler beim Markieren aller als gelesen'}), 500

@api_blueprint.route('/system/status', methods=['GET'])
@login_required
def system_status():
    """Gibt den System-Status zurück"""
    try:
        return jsonify({
            'success': True,
            'status': 'online',
            'timestamp': datetime.now().isoformat(),
            'user': {
                'id': current_user.id,
                'username': current_user.username,
                'is_admin': current_user.is_admin
            }
        })
    except Exception as e:
        api_logger.error(f"Fehler beim Abrufen des System-Status: {str(e)}")
        return jsonify({'error': 'System-Status nicht verfügbar'}), 500

@api_blueprint.route('/heartbeat', methods=['POST'])
@login_required  
def heartbeat():
    """Heartbeat-Endpunkt für Frontend-Verbindungsmonitoring"""
    try:
        # Session-Aktivität NICHT in Cookie speichern
        # session['last_heartbeat'] = datetime.now().strftime('%H:%M:%S')  # ENTFERNT
        session.permanent = True
        
        return jsonify({
            'success': True,
            'timestamp': datetime.now().isoformat(),
            'user_id': current_user.id
        })
    except Exception as e:
        api_logger.error(f"Fehler im Heartbeat: {str(e)}")
        return jsonify({'error': 'Heartbeat-Fehler'}), 500

@api_blueprint.route('/session/status', methods=['GET'])
def session_status():
    """Gibt den aktuellen Session-Status zurück"""
    try:
        # Prüfe ob Benutzer über Flask-Login authentifiziert ist
        if hasattr(current_user, 'is_authenticated') and current_user.is_authenticated:
            # Benutzer ist angemeldet
            from backend.config.settings import SESSION_LIFETIME
            
            # Session-Informationen sammeln
            session_start = session.get('session_start', datetime.now().isoformat())
            
            # Standard Session-Lifetime verwenden
            max_inactive_minutes = int(SESSION_LIFETIME.total_seconds() / 60)
            
            # Verbleibende Zeit berechnen (volle Session-Zeit wenn angemeldet)
            time_left_seconds = int(SESSION_LIFETIME.total_seconds())
            
            return jsonify({
                'success': True,
                'user': {
                    'id': current_user.id,
                    'username': current_user.username,
                    'email': current_user.email,
                    'is_admin': current_user.is_admin if hasattr(current_user, 'is_admin') else False
                },
                'session': {
                    'is_authenticated': True,
                    'max_inactive_minutes': max_inactive_minutes,
                    'time_left_seconds': time_left_seconds,
                    'last_activity': datetime.now().isoformat(),
                    'session_start': session_start
                },
                'timestamp': datetime.now().isoformat()
            })
        else:
            # Benutzer ist nicht angemeldet
            return jsonify({
                'success': True,
                'user': None,
                'session': {
                    'is_authenticated': False,
                    'max_inactive_minutes': 0,
                    'time_left_seconds': 0,
                    'last_activity': None,
                    'session_start': None
                },
                'timestamp': datetime.now().isoformat()
            })
    except Exception as e:
        api_logger.error(f"Fehler beim Abrufen des Session-Status: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Session-Status nicht verfügbar',
            'message': str(e)
        }), 500

@api_blueprint.route('/session/heartbeat', methods=['POST'])
@login_required
def session_heartbeat():
    """Session-Heartbeat für automatische Verlängerung"""
    try:
        # Letzte Aktivität NICHT in Cookie speichern (Cookie-Größe reduzieren)
        # session['last_activity'] = datetime.now().isoformat()  # ENTFERNT
        
        # Session als permanent markieren für Verlängerung
        session.permanent = True
        
        # Verbleibende Session-Zeit berechnen
        from backend.config.settings import SESSION_LIFETIME
        time_left_seconds = int(SESSION_LIFETIME.total_seconds())
        
        api_logger.debug(f"Session-Heartbeat von Benutzer {current_user.username}")
        
        return jsonify({
            'success': True,
            'message': 'Session aktualisiert',
            'time_left_seconds': time_left_seconds,
            'timestamp': datetime.now().isoformat()
        })
    except Exception as e:
        api_logger.error(f"Fehler beim Session-Heartbeat: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Session-Heartbeat fehlgeschlagen',
            'message': str(e)
        }), 500

@api_blueprint.route('/session/extend', methods=['POST'])
@login_required
def extend_session():
    """Verlängert die aktuelle Session"""
    try:
        data = request.get_json() or {}
        extend_minutes = data.get('extend_minutes', 30)
        
        # Session verlängern durch Markierung als permanent
        session.permanent = True
        
        # Neue Aktivitätszeit NICHT in Cookie speichern
        # session['last_activity'] = datetime.now().isoformat()  # ENTFERNT
        
        api_logger.info(f"Session für Benutzer {current_user.username} um {extend_minutes} Minuten verlängert")
        
        return jsonify({
            'success': True,
            'message': f'Session um {extend_minutes} Minuten verlängert',
            'extended_minutes': extend_minutes,
            'timestamp': datetime.now().isoformat()
        })
    except Exception as e:
        api_logger.error(f"Fehler beim Verlängern der Session: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Session-Verlängerung fehlgeschlagen',
            'message': str(e)
        }), 500

@api_blueprint.route('/stats', methods=['GET'])
@login_required
def get_stats():
    """
    Hauptstatistiken-Endpunkt für das System.
    
    Liefert umfassende Statistiken über Drucker, Jobs und Benutzer.
    """
    try:
        db_session = get_db_session()
        
        # Grundlegende Zählungen
        total_printers = db_session.query(Printer).count()
        active_printers = db_session.query(Printer).filter(Printer.active == True).count()
        total_jobs = db_session.query(Job).count()
        
        # Job-Status-Verteilung
        completed_jobs = db_session.query(Job).filter(Job.status == 'completed').count()
        running_jobs = db_session.query(Job).filter(Job.status == 'running').count()
        pending_jobs = db_session.query(Job).filter(Job.status == 'pending').count()
        failed_jobs = db_session.query(Job).filter(Job.status == 'failed').count()
        
        # Benutzer-Statistiken
        total_users = db_session.query(User).count()
        active_users = db_session.query(User).filter(User.active == True).count()
        
        # Zeitbasierte Statistiken (letzte 24 Stunden)
        yesterday = datetime.now() - timedelta(days=1)
        jobs_last_24h = db_session.query(Job).filter(Job.created_at >= yesterday).count()
        
        # Gesamtdruckzeit berechnen
        completed_jobs_with_duration = db_session.query(Job).filter(
            Job.status == 'completed', 
            Job.duration_minutes.isnot(None)
        ).all()
        
        total_print_hours = sum(job.duration_minutes for job in completed_jobs_with_duration) / 60.0
        
        db_session.close()
        
        stats_data = {
            'success': True,
            'timestamp': datetime.now().isoformat(),
            
            # Grundlegende Zählungen
            'total_printers': total_printers,
            'active_printers': active_printers,
            'total_jobs': total_jobs,
            'total_users': total_users,
            'active_users': active_users,
            
            # Job-Statistiken
            'completed_jobs': completed_jobs,
            'running_jobs': running_jobs,
            'pending_jobs': pending_jobs,
            'failed_jobs': failed_jobs,
            'jobs_last_24h': jobs_last_24h,
            
            # Druckzeit-Statistiken
            'total_print_hours': round(total_print_hours, 2),
            'completion_rate': round((completed_jobs / total_jobs * 100), 2) if total_jobs > 0 else 0
        }
        
        api_logger.info(f"Statistiken abgerufen von Benutzer {current_user.username}")
        return jsonify(stats_data)
        
    except Exception as e:
        api_logger.error(f"Fehler beim Abrufen der Statistiken: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Fehler beim Laden der Statistiken',
            'message': str(e)
        }), 500

@api_blueprint.route('/admin/system-health', methods=['GET'])
@admin_required
def get_system_health():
    """
    System-Gesundheitsstatus für Administratoren.
    
    Liefert detaillierte Informationen über den System-Zustand.
    """
    try:
        db_session = get_db_session()
        
        # Datenbankverbindung testen
        db_healthy = True
        try:
            db_session.execute("SELECT 1")
        except Exception as e:
            db_healthy = False
            api_logger.error(f"Datenbankfehler: {str(e)}")
        
        # Systemressourcen prüfen
        import psutil
        import os
        
        # CPU und Speicher
        cpu_usage = psutil.cpu_percent(interval=1)
        memory = psutil.virtual_memory()
        disk = psutil.disk_usage('/')
        
        # Aktive Drucker prüfen
        active_printers = db_session.query(Printer).filter(Printer.active == True).count()
        total_printers = db_session.query(Printer).count()
        
        # Laufende Jobs prüfen
        running_jobs = db_session.query(Job).filter(Job.status == 'running').count()
        
        db_session.close()
        
        # Gesamtstatus bestimmen
        overall_status = 'healthy'
        if not db_healthy or cpu_usage > 90 or memory.percent > 90:
            overall_status = 'warning'
        if not db_healthy or cpu_usage > 95 or memory.percent > 95:
            overall_status = 'critical'
        
        health_data = {
            'success': True,
            'timestamp': datetime.now().isoformat(),
            'overall_status': overall_status,
            
            # System-Status
            'database': {
                'status': 'healthy' if db_healthy else 'error',
                'connection': db_healthy
            },
            
            # Systemressourcen
            'system': {
                'cpu_usage': cpu_usage,
                'memory_usage': memory.percent,
                'memory_available_gb': round(memory.available / (1024**3), 2),
                'disk_usage': disk.percent,
                'disk_free_gb': round(disk.free / (1024**3), 2)
            },
            
            # Drucker-Status
            'printers': {
                'total': total_printers,
                'active': active_printers,
                'inactive': total_printers - active_printers
            },
            
            # Job-Status
            'jobs': {
                'running': running_jobs
            }
        }
        
        api_logger.info(f"System-Health abgerufen von Admin {current_user.username}")
        return jsonify(health_data)
        
    except ImportError:
        # Fallback ohne psutil
        health_data = {
            'success': True,
            'timestamp': datetime.now().isoformat(),
            'overall_status': 'healthy',
            'database': {'status': 'healthy', 'connection': True},
            'system': {'cpu_usage': 0, 'memory_usage': 0, 'disk_usage': 0},
            'printers': {'total': 0, 'active': 0, 'inactive': 0},
            'jobs': {'running': 0},
            'note': 'Eingeschränkte Systemüberwachung (psutil nicht verfügbar)'
        }
        return jsonify(health_data)
        
    except Exception as e:
        api_logger.error(f"Fehler beim Abrufen des System-Health: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Fehler beim Laden des System-Status',
            'message': str(e)
        }), 500

@api_blueprint.route('/admin/error-recovery/status', methods=['GET'])
@admin_required
def get_error_recovery_status():
    """
    Fehlerwiederherstellungs-Status für Administratoren.
    
    Liefert Informationen über System-Fehler und Wiederherstellungsoptionen.
    """
    try:
        db_session = get_db_session()
        
        # Fehlgeschlagene Jobs der letzten 24 Stunden
        yesterday = datetime.now() - timedelta(days=1)
        failed_jobs = db_session.query(Job).filter(
            Job.status == 'failed',
            Job.created_at >= yesterday
        ).all()
        
        # Inaktive Drucker
        inactive_printers = db_session.query(Printer).filter(Printer.active == False).all()
        
        # Hängende Jobs (länger als 6 Stunden im Status 'running')
        six_hours_ago = datetime.now() - timedelta(hours=6)
        stuck_jobs = db_session.query(Job).filter(
            Job.status == 'running',
            Job.start_time <= six_hours_ago
        ).all()
        
        db_session.close()
        
        # Wiederherstellungsaktionen bestimmen
        recovery_actions = []
        
        if failed_jobs:
            recovery_actions.append({
                'type': 'restart_failed_jobs',
                'count': len(failed_jobs),
                'description': f'{len(failed_jobs)} fehlgeschlagene Jobs neu starten'
            })
        
        if inactive_printers:
            recovery_actions.append({
                'type': 'reactivate_printers',
                'count': len(inactive_printers),
                'description': f'{len(inactive_printers)} inaktive Drucker reaktivieren'
            })
        
        if stuck_jobs:
            recovery_actions.append({
                'type': 'reset_stuck_jobs',
                'count': len(stuck_jobs),
                'description': f'{len(stuck_jobs)} hängende Jobs zurücksetzen'
            })
        
        # Gesamtstatus bestimmen
        status = 'healthy'
        if failed_jobs or inactive_printers:
            status = 'warning'
        if stuck_jobs:
            status = 'critical'
        
        recovery_data = {
            'success': True,
            'timestamp': datetime.now().isoformat(),
            'status': status,
            
            'issues': {
                'failed_jobs': len(failed_jobs),
                'inactive_printers': len(inactive_printers),
                'stuck_jobs': len(stuck_jobs)
            },
            
            'recovery_actions': recovery_actions,
            
            'last_check': datetime.now().isoformat()
        }
        
        api_logger.info(f"Error-Recovery-Status abgerufen von Admin {current_user.username}")
        return jsonify(recovery_data)
        
    except Exception as e:
        api_logger.error(f"Fehler beim Abrufen des Error-Recovery-Status: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Fehler beim Laden des Wiederherstellungs-Status',
            'message': str(e)
        }), 500

@api_blueprint.route('/admin/fix-permissions', methods=['POST'])
@admin_required
def fix_admin_permissions():
    """
    Korrigiert die Admin-Berechtigungen im System.
    
    Nur für Administratoren zugänglich.
    """
    try:
        from utils.permissions import fix_all_admin_permissions
        
        result = fix_all_admin_permissions()
        
        if result['success']:
            api_logger.info(f"Admin-Berechtigungen korrigiert von {current_user.username}: {result['created']} erstellt, {result['corrected']} aktualisiert")
            return jsonify({
                'success': True,
                'message': 'Admin-Berechtigungen erfolgreich korrigiert',
                'details': result
            })
        else:
            api_logger.error(f"Fehler beim Korrigieren der Admin-Berechtigungen: {result['error']}")
            return jsonify({
                'success': False,
                'error': 'Fehler beim Korrigieren der Berechtigungen',
                'message': result['error']
            }), 500
        
    except Exception as e:
        api_logger.error(f"Fehler beim Korrigieren der Admin-Berechtigungen: {str(e)}")
        return jsonify({
            'success': False,
            'error': 'Fehler beim Korrigieren der Berechtigungen',
            'message': str(e)
        }), 500 