import os
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from pathlib import Path
from flask import Blueprint, render_template, request, redirect, session, url_for, flash, send_file, jsonify, current_app
import requests

import config
from config import DATABASE_CONFIG
from auth.decorators import login_required
from utils.audit import log_audit
from utils.backup import create_backup, restore_backup
from utils.network import get_client_ip
from db import get_connection, get_db_connection, get_db_cursor, execute_query
from utils.export import create_excel_export, prepare_audit_export_data

# Create Blueprint
admin_bp = Blueprint('admin', __name__)


def check_service_health():
    """Check health status of critical services"""
    services = []
    
    # License Server Health Check
    license_server = {
        'name': 'License Server',
        'status': 'unknown',
        'response_time': None,
        'icon': '🔐',
        'details': None
    }
    
    try:
        start_time = datetime.now()
        response = requests.get('http://license-server:8443/health', timeout=2)
        response_time = (datetime.now() - start_time).total_seconds() * 1000
        
        if response.status_code == 200:
            license_server['status'] = 'healthy'
            license_server['response_time'] = round(response_time, 1)
            license_server['details'] = 'Betriebsbereit'
        else:
            license_server['status'] = 'unhealthy'
            license_server['details'] = f'HTTP {response.status_code}'
    except requests.exceptions.Timeout:
        license_server['status'] = 'down'
        license_server['details'] = 'Timeout - Server antwortet nicht'
    except requests.exceptions.ConnectionError:
        license_server['status'] = 'down'
        license_server['details'] = 'Verbindung fehlgeschlagen'
    except Exception as e:
        license_server['status'] = 'down'
        license_server['details'] = f'Fehler: {str(e)}'
    
    services.append(license_server)
    
    # PostgreSQL Health Check
    postgresql = {
        'name': 'PostgreSQL',
        'status': 'unknown',
        'response_time': None,
        'icon': '🗄️',
        'details': None
    }
    
    try:
        start_time = datetime.now()
        with get_db_connection() as conn:
            cur = conn.cursor()
            cur.execute('SELECT 1')
            cur.close()
        response_time = (datetime.now() - start_time).total_seconds() * 1000
        
        postgresql['status'] = 'healthy'
        postgresql['response_time'] = round(response_time, 1)
        postgresql['details'] = 'Datenbankverbindung aktiv'
    except Exception as e:
        postgresql['status'] = 'down'
        postgresql['details'] = f'Verbindungsfehler: {str(e)}'
    
    services.append(postgresql)
    
    # Calculate overall health
    healthy_count = sum(1 for s in services if s['status'] == 'healthy')
    total_count = len(services)
    
    return {
        'services': services,
        'healthy_count': healthy_count,
        'total_count': total_count,
        'overall_status': 'healthy' if healthy_count == total_count else ('partial' if healthy_count > 0 else 'down')
    }


@admin_bp.route("/")
@login_required
def dashboard():
    try:
        conn = get_connection()
        cur = conn.cursor()
        try:
                # Hole Statistiken mit sicheren Defaults
                # Anzahl aktiver Lizenzen (nur echte Daten, keine Testdaten)
                cur.execute("SELECT COUNT(*) FROM licenses WHERE is_active = true AND is_fake = false")
                active_licenses = cur.fetchone()[0] if cur.rowcount > 0 else 0
                
                # Anzahl Kunden (nur echte Kunden, keine Fake-Kunden)
                cur.execute("SELECT COUNT(*) FROM customers WHERE is_fake = false")
                total_customers = cur.fetchone()[0] if cur.rowcount > 0 else 0
                
                # Testdaten separat zählen für optionale Anzeige
                cur.execute("SELECT COUNT(*) FROM customers WHERE is_fake = true")
                fake_customers_count = cur.fetchone()[0] if cur.rowcount > 0 else 0
                
                cur.execute("SELECT COUNT(*) FROM licenses WHERE is_fake = true")
                test_licenses_count = cur.fetchone()[0] if cur.rowcount > 0 else 0
                
                # Anzahl aktiver Sessions (Admin-Panel)
                cur.execute("SELECT COUNT(*) FROM sessions WHERE is_active = true")
                active_sessions = cur.fetchone()[0] if cur.rowcount > 0 else 0
                
                # Aktive Nutzung (Kunden-Software) - Lizenzen mit Heartbeats in den letzten 15 Minuten
                active_usage = 0
                try:
                    # Prüfe ob Tabelle existiert
                    cur.execute("""
                        SELECT EXISTS (
                            SELECT FROM information_schema.tables 
                            WHERE table_name = 'license_heartbeats'
                        )
                    """)
                    table_exists = cur.fetchone()[0]
                    
                    if table_exists:
                        cur.execute("""
                            SELECT COUNT(DISTINCT lh.license_id) 
                            FROM license_heartbeats lh
                            JOIN licenses l ON l.id = lh.license_id
                            WHERE lh.timestamp > NOW() - INTERVAL '15 minutes'
                            AND l.is_fake = false
                        """)
                        active_usage = cur.fetchone()[0] if cur.rowcount > 0 else 0
                except Exception as e:
                    # Bei Fehler einfach 0 verwenden
                    current_app.logger.warning(f"Could not get active usage: {str(e)}")
                    # Rollback der fehlgeschlagenen Transaktion
                    conn.rollback()
                    # Neue Transaktion starten
                    conn = get_connection()
                    cur = conn.cursor()
                
                # Top 10 Lizenzen - nur echte Lizenzen
                cur.execute("""
                    SELECT 
                        l.license_key,
                        c.name as customer_name,
                        COUNT(s.id) as session_count
                    FROM licenses l
                    LEFT JOIN customers c ON l.customer_id = c.id
                    LEFT JOIN sessions s ON l.id = s.license_id
                    WHERE l.is_fake = false AND c.is_fake = false
                    GROUP BY l.license_key, c.name
                    ORDER BY session_count DESC
                    LIMIT 10
                """)
                top_licenses = cur.fetchall() if cur.rowcount > 0 else []
                
                # Letzte Aktivitäten - vereinfacht
                cur.execute("""
                    SELECT 
                        id,
                        timestamp,
                        username,
                        action,
                        additional_info
                    FROM audit_log
                    ORDER BY timestamp DESC
                    LIMIT 10
                """)
                recent_activities = cur.fetchall() if cur.rowcount > 0 else []
                
                # Lizenztypen zählen (nur echte Lizenzen)
                cur.execute("""
                    SELECT 
                        COUNT(CASE WHEN license_type = 'full' THEN 1 END) as full_licenses,
                        COUNT(CASE WHEN license_type = 'test' THEN 1 END) as test_licenses
                    FROM licenses 
                    WHERE is_fake = false
                """)
                license_types = cur.fetchone()
                full_licenses = license_types[0] if license_types and license_types[0] is not None else 0
                test_version_licenses = license_types[1] if license_types and license_types[1] is not None else 0
                
                # Lizenzstatus zählen (nur echte Lizenzen)
                cur.execute("""
                    SELECT 
                        COUNT(CASE WHEN is_active = true AND (valid_until IS NULL OR valid_until > NOW()) THEN 1 END) as active,
                        COUNT(CASE WHEN valid_until < NOW() THEN 1 END) as expired,
                        COUNT(CASE WHEN is_active = false THEN 1 END) as inactive
                    FROM licenses
                    WHERE is_fake = false
                """)
                license_status = cur.fetchone()
                active_licenses_count = license_status[0] if license_status and license_status[0] else 0
                expired_licenses = license_status[1] if license_status and license_status[1] else 0
                inactive_licenses = license_status[2] if license_status and license_status[2] else 0
                
                # Bald ablaufende Lizenzen (nur echte Lizenzen)
                cur.execute("""
                    SELECT 
                        l.id,
                        l.license_key,
                        c.name as customer_name,
                        l.valid_until,
                        EXTRACT(DAY FROM (l.valid_until - NOW())) as days_remaining
                    FROM licenses l
                    JOIN customers c ON l.customer_id = c.id
                    WHERE l.is_fake = false 
                    AND c.is_fake = false
                    AND l.is_active = true
                    AND l.valid_until IS NOT NULL
                    AND l.valid_until > NOW()
                    AND l.valid_until < NOW() + INTERVAL '30 days'
                    ORDER BY l.valid_until ASC
                    LIMIT 10
                """)
                expiring_licenses = cur.fetchall() if cur.rowcount > 0 else []
                
                # Zuletzt erstellte Lizenzen (nur echte Lizenzen)
                cur.execute("""
                    SELECT 
                        l.id,
                        l.license_key,
                        c.name as customer_name,
                        l.created_at,
                        CASE 
                            WHEN l.is_active = false THEN 'deaktiviert'
                            WHEN l.valid_until < NOW() THEN 'abgelaufen'
                            WHEN l.valid_until < NOW() + INTERVAL '30 days' THEN 'läuft bald ab'
                            ELSE 'aktiv'
                        END as status
                    FROM licenses l
                    JOIN customers c ON l.customer_id = c.id
                    WHERE l.is_fake = false 
                    AND c.is_fake = false
                    ORDER BY l.created_at DESC
                    LIMIT 5
                """)
                recent_licenses = cur.fetchall() if cur.rowcount > 0 else []
                
                # Stats Objekt für Template erstellen
                stats = {
                    'total_customers': total_customers,
                    'total_licenses': active_licenses,  # This was already filtered for is_fake = false
                    'active_sessions': active_sessions,  # Admin-Panel Sessions
                    'active_usage': active_usage,  # Aktive Kunden-Nutzung
                    'active_licenses': active_licenses_count,
                    'full_licenses': full_licenses or 0,
                    'fake_licenses': test_version_licenses or 0,  # Test versions (license_type='test'), not fake data
                    'fake_data_count': test_licenses_count,  # Actual test data count (is_fake=true)
                    'fake_customers_count': fake_customers_count,
                    'fake_resources_count': 0,
                    'expired_licenses': expired_licenses,
                    'inactive_licenses': inactive_licenses,
                    'last_backup': None,
                    'security_level': 'success',
                    'security_level_text': 'Sicher',
                    'blocked_ips_count': 0,
                    'failed_attempts_today': 0,
                    'recent_security_events': [],
                    'expiring_licenses': expiring_licenses,
                    'recent_licenses': recent_licenses
                }
                
                # Resource Pool Statistics (nur echte Ressourcen, keine Testdaten)
                resource_stats = {}
                resource_types = ['domain', 'ipv4', 'phone']
                
                for resource_type in resource_types:
                    try:
                        cur.execute("""
                            SELECT 
                                COUNT(CASE WHEN status = 'available' THEN 1 END) as available,
                                COUNT(CASE WHEN status = 'allocated' THEN 1 END) as allocated,
                                COUNT(CASE WHEN status = 'quarantine' THEN 1 END) as quarantine,
                                COUNT(*) as total
                            FROM resource_pools
                            WHERE resource_type = %s AND is_fake = false
                        """, (resource_type,))
                        
                        result = cur.fetchone()
                        if result:
                            available = result[0] or 0
                            allocated = result[1] or 0
                            quarantine = result[2] or 0
                            total = result[3] or 0
                            available_percent = int((available / total * 100)) if total > 0 else 0
                            
                            resource_stats[resource_type] = {
                                'available': available,
                                'allocated': allocated,
                                'quarantine': quarantine,
                                'total': total,
                                'available_percent': available_percent
                            }
                        else:
                            resource_stats[resource_type] = {
                                'available': 0,
                                'allocated': 0,
                                'quarantine': 0,
                                'total': 0,
                                'available_percent': 0
                            }
                    except Exception as e:
                        # Falls die Tabelle nicht existiert
                        current_app.logger.warning(f"Could not get resource stats for {resource_type}: {str(e)}")
                        resource_stats[resource_type] = {
                            'available': 0,
                            'allocated': 0,
                            'quarantine': 0,
                            'total': 0,
                            'available_percent': 0
                        }
                        # Reset the connection after error
                        conn.rollback()
                
                # Count test resources separately
                try:
                    cur.execute("SELECT COUNT(*) FROM resource_pools WHERE is_fake = true")
                    fake_resources_count = cur.fetchone()[0] if cur.rowcount > 0 else 0
                    stats['fake_resources_count'] = fake_resources_count
                except:
                    pass
                
                license_distribution = []
                hourly_sessions = []
                
                # Get service health status
                service_health = check_service_health()
                
                return render_template('dashboard.html',
                                     stats=stats,
                                     top_licenses=top_licenses,
                                     recent_activities=recent_activities,
                                     license_distribution=license_distribution,
                                     hourly_sessions=hourly_sessions,
                                     resource_stats=resource_stats,
                                     service_health=service_health,
                                     username=session.get('username'))
        finally:
            cur.close()
            conn.close()
                                     
    except Exception as e:
        current_app.logger.error(f"Dashboard error: {str(e)}")
        current_app.logger.error(f"Error type: {type(e).__name__}")
        import traceback
        current_app.logger.error(f"Traceback: {traceback.format_exc()}")
        flash(f'Dashboard-Fehler: {str(e)}', 'error')
        return redirect(url_for('auth.login'))


@admin_bp.route("/audit")
@login_required
def audit_log():
    page = request.args.get('page', 1, type=int)
    per_page = 50
    search = request.args.get('search', '')
    filter_user = request.args.get('user', '')
    action_filter = request.args.get('action', '')
    entity_filter = request.args.get('entity', '')
    
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        # Base query
        query = """
            SELECT 
                id,
                timestamp AT TIME ZONE 'Europe/Berlin' as timestamp,
                username,
                action,
                entity_type,
                entity_id,
                old_values::text,
                new_values::text,
                ip_address,
                user_agent,
                additional_info
            FROM audit_log
            WHERE 1=1
        """
        params = []
        
        # Suchfilter
        if search:
            query += """ AND (
                username ILIKE %s OR 
                action ILIKE %s OR 
                entity_type ILIKE %s OR
                additional_info ILIKE %s OR
                ip_address ILIKE %s
            )"""
            search_param = f"%{search}%"
            params.extend([search_param] * 5)
        
        # Action Filter
        if action_filter:
            query += " AND action = %s"
            params.append(action_filter)
        
        # Entity Filter  
        if entity_filter:
            query += " AND entity_type = %s"
            params.append(entity_filter)
        
        # User Filter
        if filter_user:
            query += " AND username = %s"
            params.append(filter_user)
        
        # Count total
        count_query = f"SELECT COUNT(*) FROM ({query}) as filtered"
        cur.execute(count_query, params)
        total_count = cur.fetchone()[0]
        
        # Add pagination
        query += " ORDER BY timestamp DESC LIMIT %s OFFSET %s"
        params.extend([per_page, (page - 1) * per_page])
        
        cur.execute(query, params)
        logs = cur.fetchall()
        
        # Get unique actions and entities for filters
        cur.execute("SELECT DISTINCT action FROM audit_log ORDER BY action")
        actions = [row[0] for row in cur.fetchall()]
        
        cur.execute("SELECT DISTINCT entity_type FROM audit_log ORDER BY entity_type")
        entities = [row[0] for row in cur.fetchall()]
        
        # Pagination info
        total_pages = (total_count + per_page - 1) // per_page
        
        # Convert to dictionaries for easier template access
        audit_logs = []
        for log in logs:
            # Parse JSON strings for old_values and new_values
            old_values = None
            new_values = None
            try:
                if log[6]:
                    import json
                    old_values = json.loads(log[6])
            except:
                old_values = log[6]
            try:
                if log[7]:
                    import json
                    new_values = json.loads(log[7])
            except:
                new_values = log[7]
                
            audit_logs.append({
                'id': log[0],
                'timestamp': log[1],
                'username': log[2],
                'action': log[3],
                'entity_type': log[4],
                'entity_id': log[5],
                'old_values': old_values,
                'new_values': new_values,
                'ip_address': log[8],
                'user_agent': log[9],
                'additional_info': log[10]
            })
        
        return render_template('audit_log.html',
                             logs=audit_logs,
                             page=page,
                             total_pages=total_pages,
                             total=total_count,
                             search=search,
                             filter_user=filter_user,
                             action_filter=action_filter,
                             entity_filter=entity_filter,
                             actions=actions,
                             entities=entities,
                             username=session.get('username'))
                             
    finally:
        cur.close()
        conn.close()


@admin_bp.route("/backups")
@login_required  
def backups():
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        # Hole alle Backups
        cur.execute("""
            SELECT 
                id,
                filename,
                created_at AT TIME ZONE 'Europe/Berlin' as created_at,
                filesize,
                backup_type,
                status,
                created_by,
                duration_seconds,
                tables_count,
                records_count,
                error_message,
                is_encrypted
            FROM backup_history
            ORDER BY created_at DESC
        """)
        backups = cur.fetchall()
        
        # Prüfe ob Dateien noch existieren
        backups_with_status = []
        for backup in backups:
            backup_dict = {
                'id': backup[0],
                'filename': backup[1],
                'created_at': backup[2],
                'filesize': backup[3],
                'backup_type': backup[4],
                'status': backup[5],
                'created_by': backup[6],
                'duration_seconds': backup[7],
                'tables_count': backup[8],
                'records_count': backup[9],
                'error_message': backup[10],
                'is_encrypted': backup[11],
                'file_exists': False
            }
            
            # Prüfe ob Datei existiert
            if backup[1]:  # filename
                filepath = config.BACKUP_DIR / backup[1]
                backup_dict['file_exists'] = filepath.exists()
            
            backups_with_status.append(backup_dict)
        
        return render_template('backups.html',
                             backups=backups_with_status,
                             username=session.get('username'))
    
    finally:
        cur.close()
        conn.close()


@admin_bp.route("/backup/create", methods=["POST"])
@login_required
def create_backup_route():
    """Manuelles Backup erstellen"""
    from flask import jsonify
    success, result = create_backup(backup_type="manual", created_by=session.get('username'))
    
    if success:
        return jsonify({
            'success': True,
            'message': f'Backup erfolgreich erstellt: {result}'
        })
    else:
        return jsonify({
            'success': False,
            'message': f'Backup fehlgeschlagen: {result}'
        }), 500


@admin_bp.route("/backup/restore/<int:backup_id>", methods=["POST"])
@login_required
def restore_backup_route(backup_id):
    """Backup wiederherstellen"""
    from flask import jsonify
    encryption_key = request.form.get('encryption_key')
    
    success, message = restore_backup(backup_id, encryption_key)
    
    if success:
        return jsonify({
            'success': True,
            'message': message
        })
    else:
        return jsonify({
            'success': False,
            'message': f'Wiederherstellung fehlgeschlagen: {message}'
        }), 500


@admin_bp.route("/backup/download/<int:backup_id>")
@login_required
def download_backup(backup_id):
    """Backup herunterladen"""
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        # Hole Backup-Info
        cur.execute("SELECT filename, filepath FROM backup_history WHERE id = %s", (backup_id,))
        result = cur.fetchone()
        
        if not result:
            flash('Backup nicht gefunden', 'error')
            return redirect(url_for('admin.backups'))
        
        filename, filepath = result
        filepath = Path(filepath)
        
        if not filepath.exists():
            flash('Backup-Datei nicht gefunden', 'error')
            return redirect(url_for('admin.backups'))
        
        # Audit-Log
        log_audit('BACKUP_DOWNLOAD', 'backup', backup_id,
                 additional_info=f"Backup heruntergeladen: {filename}")
        
        return send_file(filepath, as_attachment=True, download_name=filename)
        
    finally:
        cur.close()
        conn.close()


@admin_bp.route("/backup/delete/<int:backup_id>", methods=["DELETE"])
@login_required
def delete_backup(backup_id):
    """Backup löschen"""
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        # Hole Backup-Info
        cur.execute("SELECT filename, filepath FROM backup_history WHERE id = %s", (backup_id,))
        result = cur.fetchone()
        
        if not result:
            return jsonify({'success': False, 'message': 'Backup nicht gefunden'}), 404
        
        filename, filepath = result
        filepath = Path(filepath)
        
        # Lösche Datei wenn vorhanden
        if filepath.exists():
            try:
                filepath.unlink()
            except Exception as e:
                return jsonify({'success': False, 'message': f'Fehler beim Löschen der Datei: {str(e)}'}), 500
        
        # Lösche Datenbank-Eintrag
        cur.execute("DELETE FROM backup_history WHERE id = %s", (backup_id,))
        conn.commit()
        
        # Audit-Log
        log_audit('BACKUP_DELETE', 'backup', backup_id,
                 additional_info=f"Backup gelöscht: {filename}")
        
        return jsonify({'success': True, 'message': 'Backup erfolgreich gelöscht'})
        
    except Exception as e:
        conn.rollback()
        return jsonify({'success': False, 'message': str(e)}), 500
        
    finally:
        cur.close()
        conn.close()


@admin_bp.route("/security/blocked-ips")
@login_required
def blocked_ips():
    """Zeigt gesperrte IP-Adressen"""
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        cur.execute("""
            SELECT 
                ip_address,
                attempt_count,
                last_attempt AT TIME ZONE 'Europe/Berlin' as last_attempt,
                blocked_until AT TIME ZONE 'Europe/Berlin' as blocked_until,
                last_username_tried,
                last_error_message
            FROM login_attempts
            WHERE blocked_until IS NOT NULL AND blocked_until > CURRENT_TIMESTAMP
            ORDER BY blocked_until DESC
        """)
        blocked = cur.fetchall()
        
        # Alle Login-Versuche (auch nicht gesperrte)
        cur.execute("""
            SELECT 
                ip_address,
                attempt_count,
                last_attempt AT TIME ZONE 'Europe/Berlin' as last_attempt,
                blocked_until AT TIME ZONE 'Europe/Berlin' as blocked_until,
                last_username_tried,
                last_error_message
            FROM login_attempts
            ORDER BY last_attempt DESC
            LIMIT 100
        """)
        all_attempts = cur.fetchall()
        
        return render_template('blocked_ips.html',
                             blocked_ips=blocked,
                             all_attempts=all_attempts,
                             username=session.get('username'))
                             
    finally:
        cur.close()
        conn.close()


@admin_bp.route("/security/unblock-ip", methods=["POST"])
@login_required
def unblock_ip():
    """Entsperrt eine IP-Adresse"""
    ip_address = request.form.get('ip_address')
    
    if not ip_address:
        flash('Keine IP-Adresse angegeben', 'error')
        return redirect(url_for('admin.blocked_ips'))
    
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        cur.execute("""
            UPDATE login_attempts 
            SET blocked_until = NULL 
            WHERE ip_address = %s
        """, (ip_address,))
        
        if cur.rowcount > 0:
            conn.commit()
            flash(f'IP-Adresse {ip_address} wurde entsperrt', 'success')
            log_audit('UNBLOCK_IP', 'security', 
                     additional_info=f"IP-Adresse entsperrt: {ip_address}")
        else:
            flash(f'IP-Adresse {ip_address} nicht gefunden', 'warning')
            
    except Exception as e:
        conn.rollback()
        flash(f'Fehler beim Entsperren: {str(e)}', 'error')
        
    finally:
        cur.close()
        conn.close()
        
    return redirect(url_for('admin.blocked_ips'))


@admin_bp.route("/security/clear-attempts", methods=["POST"])
@login_required
def clear_attempts():
    """Löscht alle Login-Versuche"""
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        cur.execute("DELETE FROM login_attempts")
        count = cur.rowcount
        conn.commit()
        
        flash(f'{count} Login-Versuche wurden gelöscht', 'success')
        log_audit('CLEAR_LOGIN_ATTEMPTS', 'security',
                 additional_info=f"{count} Login-Versuche gelöscht")
        
    except Exception as e:
        conn.rollback()
        flash(f'Fehler beim Löschen: {str(e)}', 'error')
        
    finally:
        cur.close()
        conn.close()
        
    return redirect(url_for('admin.blocked_ips'))


# ===================== LICENSE SERVER MONITORING ROUTES =====================

@admin_bp.route("/lizenzserver/monitor")
@login_required
def license_monitor():
    """Redirect to new analytics page"""
    return redirect(url_for('monitoring.analytics'))


@admin_bp.route("/lizenzserver/analytics")
@login_required
def license_analytics():
    """License usage analytics"""
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        # Time range from query params
        days = int(request.args.get('days', 30))
        
        # Usage trends over time
        cur.execute("""
            SELECT DATE(timestamp) as date,
                   COUNT(DISTINCT license_id) as unique_licenses,
                   COUNT(DISTINCT hardware_id) as unique_devices,
                   COUNT(*) as total_validations
            FROM license_heartbeats
            WHERE timestamp > NOW() - INTERVAL '%s days'
            GROUP BY date
            ORDER BY date
        """, (days,))
        usage_trends = cur.fetchall()
        
        # License performance metrics
        cur.execute("""
            SELECT l.id, l.license_key, c.name as customer_name,
                   COUNT(DISTINCT lh.hardware_id) as device_count,
                   l.max_devices,
                   COUNT(*) as total_validations,
                   COUNT(DISTINCT DATE(lh.timestamp)) as active_days,
                   MIN(lh.timestamp) as first_seen,
                   MAX(lh.timestamp) as last_seen
            FROM licenses l
            JOIN customers c ON l.customer_id = c.id
            LEFT JOIN license_heartbeats lh ON l.id = lh.license_id
            WHERE lh.timestamp > NOW() - INTERVAL '%s days'
            GROUP BY l.id, l.license_key, c.name, l.max_devices
            ORDER BY total_validations DESC
        """, (days,))
        license_metrics = cur.fetchall()
        
        # Device distribution
        cur.execute("""
            SELECT l.max_devices as limit,
                   COUNT(*) as license_count,
                   AVG(device_count) as avg_usage
            FROM licenses l
            LEFT JOIN (
                SELECT license_id, COUNT(DISTINCT hardware_id) as device_count
                FROM license_heartbeats
                WHERE timestamp > NOW() - INTERVAL '30 days'
                GROUP BY license_id
            ) usage ON l.id = usage.license_id
            WHERE l.is_active = true
            GROUP BY l.max_devices
            ORDER BY l.max_devices
        """)
        device_distribution = cur.fetchall()
        
        # Revenue analysis
        cur.execute("""
            SELECT l.license_type,
                   COUNT(DISTINCT l.id) as license_count,
                   COUNT(DISTINCT CASE WHEN lh.license_id IS NOT NULL THEN l.id END) as active_licenses,
                   COUNT(DISTINCT lh.hardware_id) as total_devices
            FROM licenses l
            LEFT JOIN license_heartbeats lh ON l.id = lh.license_id
                AND lh.timestamp > NOW() - INTERVAL '%s days'
            GROUP BY l.license_type
        """, (days,))
        revenue_analysis = cur.fetchall()
        
        return render_template('license_analytics.html',
            days=days,
            usage_trends=usage_trends,
            license_metrics=license_metrics,
            device_distribution=device_distribution,
            revenue_analysis=revenue_analysis
        )
        
    except Exception as e:
        flash(f'Fehler beim Laden der Analytics-Daten: {str(e)}', 'error')
        return render_template('license_analytics.html', days=30)
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()


@admin_bp.route("/lizenzserver/anomalies")
@login_required
def license_anomalies():
    """Redirect to unified monitoring page"""
    return redirect(url_for('monitoring.unified_monitoring'))


@admin_bp.route("/lizenzserver/anomaly/<anomaly_id>/resolve", methods=["POST"])
@login_required
def resolve_anomaly(anomaly_id):
    """Resolve an anomaly"""
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        action_taken = request.form.get('action_taken', '')
        
        cur.execute("""
            UPDATE anomaly_detections
            SET resolved = true,
                resolved_at = NOW(),
                resolved_by = %s,
                action_taken = %s
            WHERE id = %s
        """, (session.get('username'), action_taken, str(anomaly_id)))
        
        conn.commit()
        
        flash('Anomalie wurde als behoben markiert', 'success')
        log_audit('RESOLVE_ANOMALY', 'license_server', entity_id=str(anomaly_id),
                 additional_info=f"Action: {action_taken}")
        
    except Exception as e:
        if 'conn' in locals():
            conn.rollback()
        flash(f'Fehler beim Beheben der Anomalie: {str(e)}', 'error')
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()
    
    return redirect(url_for('admin.license_anomalies'))


@admin_bp.route("/lizenzserver/config")
@login_required
def license_config():
    """License server configuration"""
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        # Get client configuration
        cur.execute("""
            SELECT id, client_name, heartbeat_interval, session_timeout,
                   current_version, minimum_version, created_at, updated_at
            FROM client_configs
            WHERE client_name = 'Account Forger'
        """)
        client_config = cur.fetchone()
        
        # Get active sessions - table doesn't exist, use empty list
        active_sessions = []
        
        # Get feature flags - table doesn't exist, use empty list
        feature_flags = []
        
        # Get rate limits - table doesn't exist, use empty list
        rate_limits = []
        
        # Get system API key
        cur.execute("""
            SELECT api_key, created_at, regenerated_at, last_used_at, 
                   usage_count, created_by, regenerated_by
            FROM system_api_key
            WHERE id = 1
        """)
        api_key_data = cur.fetchone()
        
        if api_key_data:
            system_api_key = {
                'api_key': api_key_data[0],
                'created_at': api_key_data[1],
                'regenerated_at': api_key_data[2],
                'last_used_at': api_key_data[3],
                'usage_count': api_key_data[4],
                'created_by': api_key_data[5],
                'regenerated_by': api_key_data[6]
            }
        else:
            system_api_key = None
        
        return render_template('license_config.html',
            client_config=client_config,
            active_sessions=active_sessions,
            feature_flags=feature_flags,
            rate_limits=rate_limits,
            system_api_key=system_api_key
        )
        
    except Exception as e:
        import traceback
        current_app.logger.error(f"Error in license_config: {str(e)}")
        current_app.logger.error(traceback.format_exc())
        flash(f'Fehler beim Laden der Konfiguration: {str(e)}', 'error')
        return render_template('license_config.html')
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()


@admin_bp.route("/lizenzserver/config/feature-flag/<int:flag_id>", methods=["POST"])
@login_required
def update_feature_flag(flag_id):
    """Update feature flag settings"""
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        is_enabled = request.form.get('is_enabled') == 'on'
        rollout_percentage = int(request.form.get('rollout_percentage', 0))
        
        cur.execute("""
            UPDATE feature_flags
            SET is_enabled = %s,
                rollout_percentage = %s,
                updated_at = NOW()
            WHERE id = %s
        """, (is_enabled, rollout_percentage, flag_id))
        
        conn.commit()
        
        flash('Feature Flag wurde aktualisiert', 'success')
        log_audit('UPDATE_FEATURE_FLAG', 'license_server', entity_id=flag_id)
        
    except Exception as e:
        if 'conn' in locals():
            conn.rollback()
        flash(f'Fehler beim Aktualisieren: {str(e)}', 'error')
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()
    
    return redirect(url_for('admin.license_config'))



@admin_bp.route("/lizenzserver/config/update", methods=["POST"])
@login_required
def update_client_config():
    """Update client configuration"""
    if session.get('username') not in ['rac00n', 'w@rh@mm3r']:
        flash('Zugriff verweigert', 'error')
        return redirect(url_for('admin.dashboard'))
    
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        # Update configuration
        cur.execute("""
            UPDATE client_configs
            SET current_version = %s,
                minimum_version = %s,
                heartbeat_interval = %s,
                session_timeout = %s,
                updated_at = CURRENT_TIMESTAMP
            WHERE client_name = 'Account Forger'
        """, (
            request.form.get('current_version'),
            request.form.get('minimum_version'),
            30,  # heartbeat_interval - fixed
            60   # session_timeout - fixed
        ))
        
        conn.commit()
        flash('Client-Konfiguration wurde aktualisiert', 'success')
        
        # Log action
        log_action(
            username=session.get('username'),
            action='UPDATE',
            entity_type='client_config',
            entity_id=1,
            new_values={
                'current_version': request.form.get('current_version'),
                'minimum_version': request.form.get('minimum_version')
            }
        )
        
    except Exception as e:
        flash(f'Fehler beim Aktualisieren: {str(e)}', 'error')
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()
    
    return redirect(url_for('admin.license_config'))


@admin_bp.route("/lizenzserver/sessions")
@login_required
def license_sessions():
    """Show active license sessions"""
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        # Get active sessions
        cur.execute("""
            SELECT ls.id, ls.session_token, l.license_key, c.name as customer_name,
                   ls.hardware_id, ls.ip_address, ls.client_version,
                   ls.started_at AT TIME ZONE 'Europe/Berlin' as started_at,
                   ls.last_heartbeat AT TIME ZONE 'Europe/Berlin' as last_heartbeat,
                   EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - ls.last_heartbeat)) as seconds_since_heartbeat
            FROM license_sessions ls
            JOIN licenses l ON ls.license_id = l.id
            LEFT JOIN customers c ON l.customer_id = c.id
            ORDER BY ls.last_heartbeat DESC
        """)
        sessions = cur.fetchall()
        
        # Get session history (last 24h)
        cur.execute("""
            SELECT sh.id, l.license_key, c.name as customer_name,
                   sh.hardware_id, sh.ip_address, sh.client_version,
                   sh.started_at AT TIME ZONE 'Europe/Berlin' as started_at,
                   sh.ended_at AT TIME ZONE 'Europe/Berlin' as ended_at,
                   sh.end_reason,
                   EXTRACT(EPOCH FROM (sh.ended_at - sh.started_at)) as duration_seconds
            FROM session_history sh
            JOIN licenses l ON sh.license_id = l.id
            LEFT JOIN customers c ON l.customer_id = c.id
            WHERE sh.ended_at > CURRENT_TIMESTAMP - INTERVAL '24 hours'
            ORDER BY sh.ended_at DESC
            LIMIT 100
        """)
        history = cur.fetchall()
        
        return render_template('license_sessions.html', 
                               active_sessions=sessions,
                               session_history=history)
        
    except Exception as e:
        flash(f'Fehler beim Laden der Sessions: {str(e)}', 'error')
        return render_template('license_sessions.html')
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()


@admin_bp.route("/lizenzserver/sessions/<int:session_id>/terminate", methods=["POST"])
@login_required
def terminate_session(session_id):
    """Force terminate a session"""
    if session.get('username') not in ['rac00n', 'w@rh@mm3r']:
        flash('Zugriff verweigert', 'error')
        return redirect(url_for('admin.license_sessions'))
    
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        # Get session info
        cur.execute("""
            SELECT license_id, hardware_id, ip_address, client_version, started_at
            FROM license_sessions
            WHERE id = %s
        """, (session_id,))
        session_info = cur.fetchone()
        
        if session_info:
            # Log to history
            cur.execute("""
                INSERT INTO session_history 
                (license_id, hardware_id, ip_address, client_version, started_at, ended_at, end_reason)
                VALUES (%s, %s, %s, %s, %s, CURRENT_TIMESTAMP, 'forced')
            """, session_info)
            
            # Delete session
            cur.execute("DELETE FROM license_sessions WHERE id = %s", (session_id,))
            
            conn.commit()
            flash('Session wurde beendet', 'success')
            
            # Log action
            log_action(
                username=session.get('username'),
                action='TERMINATE_SESSION',
                entity_type='license_session',
                entity_id=session_id,
                additional_info={'hardware_id': session_info[1]}
            )
        else:
            flash('Session nicht gefunden', 'error')
        
    except Exception as e:
        flash(f'Fehler beim Beenden der Session: {str(e)}', 'error')
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()
    
    return redirect(url_for('admin.license_sessions'))


@admin_bp.route("/api/admin/lizenzserver/live-stats")
@login_required
def license_live_stats():
    """API endpoint for live statistics (for AJAX updates)"""
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        # Get real-time stats
        cur.execute("""
            SELECT COUNT(DISTINCT license_id) as active_licenses,
                   COUNT(*) as validations_per_minute,
                   COUNT(DISTINCT hardware_id) as active_devices
            FROM license_heartbeats
            WHERE timestamp > NOW() - INTERVAL '1 minute'
        """)
        stats = cur.fetchone()
        
        # Get active sessions count
        cur.execute("""
            SELECT COUNT(*) FROM license_sessions
        """)
        active_count = cur.fetchone()[0]
        
        # Get latest sessions
        cur.execute("""
            SELECT ls.id, l.license_key, c.name as customer_name,
                   ls.client_version, ls.last_heartbeat AT TIME ZONE 'Europe/Berlin' as last_heartbeat,
                   EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - ls.last_heartbeat)) as seconds_since
            FROM license_sessions ls
            JOIN licenses l ON ls.license_id = l.id
            LEFT JOIN customers c ON l.customer_id = c.id
            ORDER BY ls.last_heartbeat DESC
            LIMIT 5
        """)
        latest_sessions = cur.fetchall()
        
        return jsonify({
            'active_licenses': active_count,
            'validations_per_minute': stats[1] or 0,
            'active_devices': stats[2] or 0,
            'latest_sessions': [
                {
                    'customer_name': s[2],
                    'version': s[3],
                    'last_heartbeat': s[4].strftime('%H:%M:%S'),
                    'seconds_since': int(s[5])
                } for s in latest_sessions
            ]
        })
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()


@admin_bp.route("/api/admin/license/auth-token")
@login_required
def get_analytics_token():
    """Get JWT token for accessing Analytics Service"""
    import jwt
    from datetime import datetime, timedelta
    
    # Generate a short-lived token for the analytics service
    payload = {
        'sub': session.get('user_id', 'admin'),
        'type': 'analytics_access',
        'exp': datetime.utcnow() + timedelta(hours=1),
        'iat': datetime.utcnow()
    }
    
    # Use the same secret as configured in the analytics service
    jwt_secret = os.environ.get('JWT_SECRET', 'your-secret-key')
    token = jwt.encode(payload, jwt_secret, algorithm='HS256')
    
    return jsonify({'token': token})


# ===================== API KEY MANAGEMENT =====================

@admin_bp.route("/api-key/regenerate", methods=["POST"])
@login_required
def regenerate_api_key():
    """Regenerate the system API key"""
    import string
    import random
    
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        # Generate new API key
        year_part = datetime.now().strftime('%Y')
        random_part = ''.join(random.choices(string.ascii_uppercase + string.digits, k=32))
        new_api_key = f"AF-{year_part}-{random_part}"
        
        # Update the API key
        cur.execute("""
            UPDATE system_api_key
            SET api_key = %s,
                regenerated_at = CURRENT_TIMESTAMP,
                regenerated_by = %s
            WHERE id = 1
        """, (new_api_key, session.get('username')))
        
        conn.commit()
        
        flash('API Key wurde erfolgreich regeneriert', 'success')
        
        # Log action
        log_audit('API_KEY_REGENERATED', 'system_api_key', 1,
                 additional_info="API Key regenerated")
        
    except Exception as e:
        conn.rollback()
        flash(f'Fehler beim Regenerieren des API Keys: {str(e)}', 'error')
        
    finally:
        cur.close()
        conn.close()
        
    return redirect(url_for('admin.license_config'))


@admin_bp.route("/test-api-key")
@login_required
def test_api_key():
    """Test route to check API key in database"""
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        # Test if table exists
        cur.execute("""
            SELECT EXISTS (
                SELECT FROM information_schema.tables 
                WHERE table_name = 'system_api_key'
            );
        """)
        table_exists = cur.fetchone()[0]
        
        # Get API key if table exists
        api_key = None
        if table_exists:
            cur.execute("SELECT api_key FROM system_api_key WHERE id = 1;")
            result = cur.fetchone()
            if result:
                api_key = result[0]
        
        return jsonify({
            'table_exists': table_exists,
            'api_key': api_key,
            'database': DATABASE_CONFIG['dbname']
        })
        
    except Exception as e:
        return jsonify({
            'error': str(e),
            'database': DATABASE_CONFIG.get('dbname', 'unknown')
        })
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()


@admin_bp.route("/test-license-types")
@login_required
def test_license_types():
    """Test route to check license type counts"""
    try:
        conn = get_connection()
        cur = conn.cursor()
        
        # Count license types
        cur.execute("""
            SELECT 
                COUNT(CASE WHEN license_type = 'full' THEN 1 END) as full_licenses,
                COUNT(CASE WHEN license_type = 'test' THEN 1 END) as test_licenses,
                COUNT(*) as total_licenses
            FROM licenses 
            WHERE is_fake = false
        """)
        result = cur.fetchone()
        
        # Count all licenses by type
        cur.execute("""
            SELECT license_type, COUNT(*) as count
            FROM licenses
            GROUP BY license_type
            ORDER BY license_type
        """)
        all_types = cur.fetchall()
        
        return jsonify({
            'full_licenses': result[0] if result and result[0] is not None else 0,
            'test_licenses': result[1] if result and result[1] is not None else 0,
            'total_non_fake': result[2] if result and result[2] is not None else 0,
            'all_license_types': [{'type': row[0], 'count': row[1]} for row in all_types] if all_types else []
        })
        
    except Exception as e:
        return jsonify({
            'error': str(e)
        })
    finally:
        if 'cur' in locals():
            cur.close()
        if 'conn' in locals():
            conn.close()


@admin_bp.route("/admin/licenses/check-expiration", methods=["POST"])
@login_required
def check_license_expiration():
    """Manually trigger license expiration check"""
    if session.get('username') not in ['rac00n', 'w@rh@mm3r']:
        return jsonify({'error': 'Zugriff verweigert'}), 403
    
    try:
        from scheduler import deactivate_expired_licenses
        deactivate_expired_licenses()
        
        flash('License expiration check completed successfully', 'success')
        log_audit('MANUAL_LICENSE_EXPIRATION_CHECK', 'system', 
                 additional_info="Manual license expiration check triggered")
        
        return jsonify({'success': True, 'message': 'License expiration check completed'})
        
    except Exception as e:
        current_app.logger.error(f"Error in manual license expiration check: {str(e)}")
        return jsonify({'error': str(e)}), 500
