from flask import Blueprint, render_template, jsonify, request, session, redirect, url_for
from functools import wraps
import psycopg2
from psycopg2.extras import RealDictCursor
import os
import requests
from datetime import datetime, timedelta
import logging
from utils.partition_helper import ensure_partition_exists, check_table_exists

# Configure logging
logger = logging.getLogger(__name__)

# Create a function to get database connection
def get_db_connection():
    return psycopg2.connect(
        host=os.environ.get('POSTGRES_HOST', 'postgres'),
        database=os.environ.get('POSTGRES_DB', 'v2_adminpanel'),
        user=os.environ.get('POSTGRES_USER', 'postgres'),
        password=os.environ.get('POSTGRES_PASSWORD', 'postgres')
    )

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'user_id' not in session:
            return redirect(url_for('auth.login'))
        return f(*args, **kwargs)
    return decorated_function

# Create Blueprint
monitoring_bp = Blueprint('monitoring', __name__)

@monitoring_bp.route('/monitoring')
@login_required
def unified_monitoring():
    """Unified monitoring dashboard combining live activity and anomaly detection"""
    try:
        conn = get_db_connection()
        cur = conn.cursor(cursor_factory=RealDictCursor)
        
        # Initialize default values
        system_status = 'normal'
        status_color = 'success'
        active_alerts = 0
        live_metrics = {
            'active_licenses': 0,
            'total_validations': 0,
            'unique_devices': 0,
            'unique_ips': 0,
            'avg_response_time': 0
        }
        trend_data = []
        activity_stream = []
        geo_data = []
        top_licenses = []
        anomaly_distribution = []
        performance_data = []
        
        # Check if tables exist before querying
        has_heartbeats = check_table_exists(conn, 'license_heartbeats')
        has_anomalies = check_table_exists(conn, 'anomaly_detections')
        
        if has_anomalies:
            # Get active alerts count
            cur.execute("""
                SELECT COUNT(*) as count
                FROM anomaly_detections
                WHERE resolved = false
                AND detected_at > NOW() - INTERVAL '24 hours'
            """)
            active_alerts = cur.fetchone()['count'] or 0
            
            # Determine system status based on alerts
            if active_alerts == 0:
                system_status = 'normal'
                status_color = 'success'
            elif active_alerts < 5:
                system_status = 'warning'
                status_color = 'warning'
            else:
                system_status = 'critical'
                status_color = 'danger'
        
        if has_heartbeats:
            # Ensure current month partition exists
            ensure_partition_exists(conn, 'license_heartbeats', datetime.now())
            
            # Executive summary metrics
            cur.execute("""
                SELECT 
                    COUNT(DISTINCT license_id) as active_licenses,
                    COUNT(*) as total_validations,
                    COUNT(DISTINCT hardware_id) as unique_devices,
                    COUNT(DISTINCT ip_address) as unique_ips,
                    0 as avg_response_time
                FROM license_heartbeats
                WHERE timestamp > NOW() - INTERVAL '5 minutes'
            """)
            result = cur.fetchone()
            if result:
                live_metrics = result
            
            # Get 24h trend data for metrics
            cur.execute("""
                SELECT 
                    DATE_TRUNC('hour', timestamp) as hour,
                    COUNT(DISTINCT license_id) as licenses,
                    COUNT(*) as validations
                FROM license_heartbeats
                WHERE timestamp > NOW() - INTERVAL '24 hours'
                GROUP BY hour
                ORDER BY hour
            """)
            trend_data = cur.fetchall()
            
            # Activity stream - just validations if no anomalies table
            if has_anomalies:
                cur.execute("""
                    WITH combined_events AS (
                        -- Normal validations
                        SELECT 
                            lh.timestamp,
                            'validation' as event_type,
                            'normal' as severity,
                            l.license_key,
                            c.name as customer_name,
                            lh.ip_address,
                            lh.hardware_id,
                            NULL as anomaly_type,
                            NULL as description
                        FROM license_heartbeats lh
                        JOIN licenses l ON l.id = lh.license_id
                        JOIN customers c ON c.id = l.customer_id
                        WHERE lh.timestamp > NOW() - INTERVAL '1 hour'
                        
                        UNION ALL
                        
                        -- Anomalies
                        SELECT 
                            ad.detected_at as timestamp,
                            'anomaly' as event_type,
                            ad.severity,
                            l.license_key,
                            c.name as customer_name,
                            ad.ip_address,
                            ad.hardware_id,
                            ad.anomaly_type,
                            ad.description
                        FROM anomaly_detections ad
                        LEFT JOIN licenses l ON l.id = ad.license_id
                        LEFT JOIN customers c ON c.id = l.customer_id
                        WHERE ad.detected_at > NOW() - INTERVAL '1 hour'
                    )
                    SELECT * FROM combined_events
                    ORDER BY timestamp DESC
                    LIMIT 100
                """)
            else:
                # Just show validations
                cur.execute("""
                    SELECT 
                        lh.timestamp,
                        'validation' as event_type,
                        'normal' as severity,
                        l.license_key,
                        c.name as customer_name,
                        lh.ip_address,
                        lh.hardware_id,
                        NULL as anomaly_type,
                        NULL as description
                    FROM license_heartbeats lh
                    JOIN licenses l ON l.id = lh.license_id
                    JOIN customers c ON c.id = l.customer_id
                    WHERE lh.timestamp > NOW() - INTERVAL '1 hour'
                    ORDER BY lh.timestamp DESC
                    LIMIT 100
                """)
            activity_stream = cur.fetchall()
            
            # Geographic distribution
            cur.execute("""
                SELECT 
                    ip_address,
                    COUNT(*) as request_count,
                    COUNT(DISTINCT license_id) as license_count
                FROM license_heartbeats
                WHERE timestamp > NOW() - INTERVAL '1 hour'
                GROUP BY ip_address
                ORDER BY request_count DESC
                LIMIT 20
            """)
            geo_data = cur.fetchall()
            
            # Top active licenses
            if has_anomalies:
                cur.execute("""
                    SELECT 
                        l.id,
                        l.license_key,
                        c.name as customer_name,
                        COUNT(DISTINCT lh.hardware_id) as device_count,
                        COUNT(lh.*) as validation_count,
                        MAX(lh.timestamp) as last_seen,
                        COUNT(DISTINCT ad.id) as anomaly_count
                    FROM licenses l
                    JOIN customers c ON c.id = l.customer_id
                    LEFT JOIN license_heartbeats lh ON l.id = lh.license_id 
                        AND lh.timestamp > NOW() - INTERVAL '1 hour'
                    LEFT JOIN anomaly_detections ad ON l.id = ad.license_id 
                        AND ad.detected_at > NOW() - INTERVAL '24 hours'
                    WHERE lh.license_id IS NOT NULL
                    GROUP BY l.id, l.license_key, c.name
                    ORDER BY validation_count DESC
                    LIMIT 10
                """)
            else:
                cur.execute("""
                    SELECT 
                        l.id,
                        l.license_key,
                        c.name as customer_name,
                        COUNT(DISTINCT lh.hardware_id) as device_count,
                        COUNT(lh.*) as validation_count,
                        MAX(lh.timestamp) as last_seen,
                        0 as anomaly_count
                    FROM licenses l
                    JOIN customers c ON c.id = l.customer_id
                    LEFT JOIN license_heartbeats lh ON l.id = lh.license_id 
                        AND lh.timestamp > NOW() - INTERVAL '1 hour'
                    WHERE lh.license_id IS NOT NULL
                    GROUP BY l.id, l.license_key, c.name
                    ORDER BY validation_count DESC
                    LIMIT 10
                """)
            top_licenses = cur.fetchall()
            
            # Performance metrics
            cur.execute("""
                SELECT 
                    DATE_TRUNC('minute', timestamp) as minute,
                    0 as avg_response_time,
                    0 as max_response_time,
                    COUNT(*) as request_count
                FROM license_heartbeats
                WHERE timestamp > NOW() - INTERVAL '30 minutes'
                GROUP BY minute
                ORDER BY minute DESC
            """)
            performance_data = cur.fetchall()
        
        if has_anomalies:
            # Anomaly distribution
            cur.execute("""
                SELECT 
                    anomaly_type,
                    COUNT(*) as count,
                    MAX(severity) as max_severity
                FROM anomaly_detections
                WHERE detected_at > NOW() - INTERVAL '24 hours'
                GROUP BY anomaly_type
                ORDER BY count DESC
            """)
            anomaly_distribution = cur.fetchall()
        
        cur.close()
        conn.close()
        
        return render_template('monitoring/unified_monitoring.html',
                             system_status=system_status,
                             status_color=status_color,
                             active_alerts=active_alerts,
                             live_metrics=live_metrics,
                             trend_data=trend_data,
                             activity_stream=activity_stream,
                             geo_data=geo_data,
                             top_licenses=top_licenses,
                             anomaly_distribution=anomaly_distribution,
                             performance_data=performance_data)
                             
    except Exception as e:
        logger.error(f"Error in unified monitoring: {str(e)}")
        return render_template('error.html', 
                             error='Fehler beim Laden des Monitorings',
                             details=str(e))

@monitoring_bp.route('/live-dashboard')
@login_required
def live_dashboard():
    """Redirect to unified monitoring dashboard"""
    return redirect(url_for('monitoring.unified_monitoring'))


@monitoring_bp.route('/alerts')
@login_required
def alerts():
    """Show active alerts from Alertmanager"""
    alerts = []
    
    try:
        # Get alerts from Alertmanager
        response = requests.get('http://alertmanager:9093/api/v1/alerts', timeout=2)
        if response.status_code == 200:
            alerts = response.json()
    except:
        # Fallback to database anomalies if table exists
        conn = get_db_connection()
        if check_table_exists(conn, 'anomaly_detections'):
            cur = conn.cursor(cursor_factory=RealDictCursor)
            
            cur.execute("""
                SELECT 
                    ad.*,
                    l.license_key,
                    c.name as company_name
                FROM anomaly_detections ad
                LEFT JOIN licenses l ON l.id = ad.license_id
                LEFT JOIN customers c ON c.id = l.customer_id
                WHERE ad.resolved = false
                ORDER BY ad.detected_at DESC
                LIMIT 50
            """)
            alerts = cur.fetchall()
            
            cur.close()
        conn.close()
    
    return render_template('monitoring/alerts.html', alerts=alerts)

@monitoring_bp.route('/analytics')
@login_required
def analytics():
    """Combined analytics and license server status page"""
    try:
        conn = get_db_connection()
        cur = conn.cursor(cursor_factory=RealDictCursor)
        
        # Initialize default values
        live_stats = [0, 0, 0, 0]
        validation_rates = []
        
        if check_table_exists(conn, 'license_heartbeats'):
            # Get live statistics for the top cards
            cur.execute("""
                SELECT 
                    COUNT(DISTINCT license_id) as active_licenses,
                    COUNT(*) as total_validations,
                    COUNT(DISTINCT hardware_id) as unique_devices,
                    COUNT(DISTINCT ip_address) as unique_ips
                FROM license_heartbeats
                WHERE timestamp > NOW() - INTERVAL '5 minutes'
            """)
            live_stats_data = cur.fetchone()
            live_stats = [
                live_stats_data['active_licenses'] or 0,
                live_stats_data['total_validations'] or 0,
                live_stats_data['unique_devices'] or 0,
                live_stats_data['unique_ips'] or 0
            ]
            
            # Get validation rates for the chart (last 30 minutes, aggregated by minute)
            cur.execute("""
                SELECT 
                    DATE_TRUNC('minute', timestamp) as minute,
                    COUNT(*) as count
                FROM license_heartbeats
                WHERE timestamp > NOW() - INTERVAL '30 minutes'
                GROUP BY minute
                ORDER BY minute DESC
                LIMIT 30
            """)
            validation_rates = [(row['minute'].isoformat(), row['count']) for row in cur.fetchall()]
        
        cur.close()
        conn.close()
        
        return render_template('monitoring/analytics.html', 
                             live_stats=live_stats,
                             validation_rates=validation_rates)
        
    except Exception as e:
        logger.error(f"Error in analytics: {str(e)}")
        return render_template('error.html', 
                             error='Fehler beim Laden der Analytics',
                             details=str(e))


@monitoring_bp.route('/analytics/stream')
@login_required
def analytics_stream():
    """Server-sent event stream for live analytics updates"""
    def generate():
        while True:
            try:
                conn = get_db_connection()
                cur = conn.cursor(cursor_factory=RealDictCursor)
                
                data = {'active_licenses': 0, 'total_validations': 0, 
                        'unique_devices': 0, 'unique_ips': 0}
                
                if check_table_exists(conn, 'license_heartbeats'):
                    cur.execute("""
                        SELECT 
                            COUNT(DISTINCT license_id) as active_licenses,
                            COUNT(*) as total_validations,
                            COUNT(DISTINCT hardware_id) as unique_devices,
                            COUNT(DISTINCT ip_address) as unique_ips
                        FROM license_heartbeats
                        WHERE timestamp > NOW() - INTERVAL '5 minutes'
                    """)
                    result = cur.fetchone()
                    if result:
                        data = dict(result)
                
                cur.close()
                conn.close()
                
                yield f"data: {jsonify(data).get_data(as_text=True)}\n\n"
                
            except Exception as e:
                logger.error(f"Error in analytics stream: {str(e)}")
                yield f"data: {jsonify({'error': str(e)}).get_data(as_text=True)}\n\n"
            
            import time
            time.sleep(5)  # Update every 5 seconds
    
    from flask import Response
    return Response(generate(), mimetype="text/event-stream")