import os
import logging
from datetime import datetime
from zoneinfo import ZoneInfo
from flask import Blueprint, render_template, request, redirect, session, url_for, flash, jsonify

import config
from auth.decorators import login_required
from utils.audit import log_audit
from db import get_connection, get_db_connection, get_db_cursor
from models import get_customers, get_customer_by_id

# Create Blueprint
customer_bp = Blueprint('customers', __name__)

# Test route
@customer_bp.route("/test-customers")
def test_customers():
    return "Customer blueprint is working!"


@customer_bp.route("/customers")
@login_required
def customers():
    show_fake = request.args.get('show_fake', 'false').lower() == 'true'
    search = request.args.get('search', '').strip()
    page = request.args.get('page', 1, type=int)
    per_page = 20
    sort = request.args.get('sort', 'name')
    order = request.args.get('order', 'asc')
    
    customers_list = get_customers(show_fake=show_fake, search=search)
    
    # Sortierung
    if sort == 'name':
        customers_list.sort(key=lambda x: x['name'].lower(), reverse=(order == 'desc'))
    elif sort == 'email':
        customers_list.sort(key=lambda x: x['email'].lower(), reverse=(order == 'desc'))
    elif sort == 'created_at':
        customers_list.sort(key=lambda x: x['created_at'], reverse=(order == 'desc'))
    
    # Paginierung
    total_customers = len(customers_list)
    total_pages = (total_customers + per_page - 1) // per_page
    start = (page - 1) * per_page
    end = start + per_page
    paginated_customers = customers_list[start:end]
    
    return render_template("customers.html", 
                         customers=paginated_customers,
                         show_fake=show_fake,
                         search=search,
                         page=page,
                         per_page=per_page,
                         total_pages=total_pages,
                         total_customers=total_customers,
                         sort=sort,
                         order=order,
                         current_order=order)


@customer_bp.route("/customer/edit/<int:customer_id>", methods=["GET", "POST"])
@login_required
def edit_customer(customer_id):
    if request.method == "POST":
        try:
            # Get current customer data for comparison
            current_customer = get_customer_by_id(customer_id)
            if not current_customer:
                flash('Kunde nicht gefunden!', 'error')
                return redirect(url_for('customers.customers_licenses'))
            
            with get_db_connection() as conn:
                cur = conn.cursor()
                try:
                    # Update customer data
                    new_values = {
                        'name': request.form['name'],
                        'email': request.form['email'],
                        'is_fake': 'is_fake' in request.form
                    }
                    
                    cur.execute("""
                        UPDATE customers 
                        SET name = %s, email = %s, is_fake = %s
                        WHERE id = %s
                    """, (
                        new_values['name'],
                        new_values['email'],
                        new_values['is_fake'],
                        customer_id
                    ))
                    
                    conn.commit()
                    
                    # Log changes
                    log_audit('UPDATE', 'customer', customer_id,
                             old_values={
                                 'name': current_customer['name'],
                                 'email': current_customer['email'],
                                 'is_fake': current_customer.get('is_fake', False)
                             },
                             new_values=new_values)
                    
                    flash('Kunde erfolgreich aktualisiert!', 'success')
                    
                    # Redirect mit show_fake Parameter wenn nötig
                    redirect_url = url_for('customers.customers_licenses')
                    if request.form.get('show_fake') == 'true':
                        redirect_url += '?show_fake=true'
                    return redirect(redirect_url)
                finally:
                    cur.close()
                    
        except Exception as e:
            logging.error(f"Fehler beim Aktualisieren des Kunden: {str(e)}")
            flash('Fehler beim Aktualisieren des Kunden!', 'error')
            return redirect(url_for('customers.customers_licenses'))

    # GET request
    customer_data = get_customer_by_id(customer_id)
    if not customer_data:
        flash('Kunde nicht gefunden!', 'error')
        return redirect(url_for('customers.customers_licenses'))
    
    return render_template("edit_customer.html", customer=customer_data)


@customer_bp.route("/customer/create", methods=["GET", "POST"])
@login_required
def create_customer():
    if request.method == "POST":
        conn = get_connection()
        cur = conn.cursor()
        
        try:
            # Insert new customer
            name = request.form['name']
            email = request.form['email']
            is_fake = 'is_fake' in request.form  # Checkbox ist nur vorhanden wenn angekreuzt
            
            cur.execute("""
                INSERT INTO customers (name, email, is_fake, created_at)
                VALUES (%s, %s, %s, %s)
                RETURNING id
            """, (name, email, is_fake, datetime.now()))
            
            customer_id = cur.fetchone()[0]
            conn.commit()
            
            # Log creation
            log_audit('CREATE', 'customer', customer_id,
                     new_values={
                         'name': name,
                         'email': email,
                         'is_fake': is_fake
                     })
            
            if is_fake:
                flash(f'Fake-Kunde {name} erfolgreich erstellt!', 'success')
            else:
                flash(f'Kunde {name} erfolgreich erstellt!', 'success')
            
            # Redirect mit show_fake=true wenn Fake-Kunde erstellt wurde
            if is_fake:
                return redirect(url_for('customers.customers_licenses', show_fake='true'))
            else:
                return redirect(url_for('customers.customers_licenses'))
            
        except Exception as e:
            conn.rollback()
            logging.error(f"Fehler beim Erstellen des Kunden: {str(e)}")
            flash('Fehler beim Erstellen des Kunden!', 'error')
        finally:
            cur.close()
            conn.close()
    
    return render_template("create_customer.html")


@customer_bp.route("/customer/delete/<int:customer_id>", methods=["POST"])
@login_required
def delete_customer(customer_id):
    conn = get_connection()
    cur = conn.cursor()

    try:
        # Get customer data before deletion
        customer_data = get_customer_by_id(customer_id)
        if not customer_data:
            flash('Kunde nicht gefunden!', 'error')
            return redirect(url_for('customers.customers_licenses'))
        
        # Check if customer has licenses
        cur.execute("SELECT COUNT(*) FROM licenses WHERE customer_id = %s", (customer_id,))
        license_count = cur.fetchone()[0]
        
        if license_count > 0:
            flash(f'Kunde kann nicht gelöscht werden - hat noch {license_count} Lizenz(en)!', 'error')
            return redirect(url_for('customers.customers_licenses'))
        
        # Delete the customer
        cur.execute("DELETE FROM customers WHERE id = %s", (customer_id,))
        
        conn.commit()
        
        # Log deletion
        log_audit('DELETE', 'customer', customer_id,
                 old_values={
                     'name': customer_data['name'],
                     'email': customer_data['email']
                 })
        
        flash(f'Kunde {customer_data["name"]} erfolgreich gelöscht!', 'success')
        
    except Exception as e:
        conn.rollback()
        logging.error(f"Fehler beim Löschen des Kunden: {str(e)}")
        flash('Fehler beim Löschen des Kunden!', 'error')
    finally:
        cur.close()
        conn.close()

    return redirect(url_for('customers.customers_licenses'))


@customer_bp.route("/customers-licenses")
@login_required
def customers_licenses():
    """Zeigt die Übersicht von Kunden und deren Lizenzen"""
    import logging
    import psycopg2
    logging.info("=== CUSTOMERS-LICENSES ROUTE CALLED ===")
    
    # Get show_fake parameter from URL
    show_fake = request.args.get('show_fake', 'false').lower() == 'true'
    logging.info(f"show_fake parameter: {show_fake}")
    
    try:
        # Direkte Verbindung ohne Helper-Funktionen
        conn = psycopg2.connect(
            host=os.getenv("POSTGRES_HOST", "postgres"),
            port=os.getenv("POSTGRES_PORT", "5432"),
            dbname=os.getenv("POSTGRES_DB"),
            user=os.getenv("POSTGRES_USER"),
            password=os.getenv("POSTGRES_PASSWORD")
        )
        conn.set_client_encoding('UTF8')
        cur = conn.cursor()
        
        try:
            # Hole alle Kunden mit ihren Lizenzen
            # Wenn show_fake=false, zeige nur Nicht-Test-Kunden
            query = """
                SELECT 
                    c.id,
                    c.name,
                    c.email,
                    c.created_at,
                    COUNT(l.id),
                    COUNT(CASE WHEN l.is_active = true THEN 1 END),
                    COUNT(CASE WHEN l.is_fake = true THEN 1 END),
                    MAX(l.created_at),
                    c.is_fake
                FROM customers c
                LEFT JOIN licenses l ON c.id = l.customer_id
                WHERE (%s OR c.is_fake = false)
                GROUP BY c.id, c.name, c.email, c.created_at, c.is_fake
                ORDER BY c.name
            """
            
            cur.execute(query, (show_fake,))
            
            customers = []
            results = cur.fetchall()
            logging.info(f"=== QUERY RETURNED {len(results)} ROWS ===")
            
            for idx, row in enumerate(results):
                logging.info(f"Row {idx}: Type={type(row)}, Length={len(row) if hasattr(row, '__len__') else 'N/A'}")
                customers.append({
                    'id': row[0],
                    'name': row[1],
                    'email': row[2],
                    'created_at': row[3],
                    'license_count': row[4],
                    'active_licenses': row[5],
                    'test_licenses': row[6],
                    'last_license_created': row[7],
                    'is_fake': row[8]
                })
            
            return render_template("customers_licenses.html", 
                                 customers=customers,
                                 show_fake=show_fake)
            
        finally:
            cur.close()
            conn.close()
        
    except Exception as e:
        import traceback
        error_details = f"Fehler beim Laden der Kunden-Lizenz-Übersicht: {str(e)}\nType: {type(e)}\nTraceback: {traceback.format_exc()}"
        logging.error(error_details)
        flash(f'Datenbankfehler: {str(e)}', 'error')
        return redirect(url_for('admin.dashboard'))


@customer_bp.route("/api/customer/<int:customer_id>/licenses")
@login_required
def api_customer_licenses(customer_id):
    """API-Endpunkt für die Lizenzen eines Kunden"""
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        # Hole Kundeninformationen
        customer = get_customer_by_id(customer_id)
        if not customer:
            return jsonify({'error': 'Kunde nicht gefunden'}), 404
        
        # Hole alle Lizenzen des Kunden - vereinfachte Version ohne komplexe Subqueries
        cur.execute("""
            SELECT 
                l.id,
                l.license_key,
                l.license_type,
                l.is_active,
                l.is_fake,
                l.valid_from,
                l.valid_until,
                l.device_limit,
                l.created_at,
                CASE 
                    WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
                    WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
                    WHEN l.is_active = false THEN 'inaktiv'
                    ELSE 'aktiv'
                END as status,
                COALESCE(l.domain_count, 0) as domain_count,
                COALESCE(l.ipv4_count, 0) as ipv4_count,
                COALESCE(l.phone_count, 0) as phone_count
            FROM licenses l
            WHERE l.customer_id = %s
            ORDER BY l.created_at DESC, l.id DESC
        """, (customer_id,))
        
        licenses = []
        for row in cur.fetchall():
            license_id = row[0]
            
            # Hole die konkreten zugewiesenen Ressourcen für diese Lizenz
            conn2 = get_connection()
            cur2 = conn2.cursor()
            cur2.execute("""
                SELECT rp.id, rp.resource_type, rp.resource_value, lr.assigned_at
                FROM resource_pools rp
                JOIN license_resources lr ON rp.id = lr.resource_id
                WHERE lr.license_id = %s AND lr.is_active = true
                ORDER BY rp.resource_type, rp.resource_value
            """, (license_id,))
            
            resources = {
                'domains': [],
                'ipv4s': [],
                'phones': []
            }
            
            for res_row in cur2.fetchall():
                resource_data = {
                    'id': res_row[0],
                    'value': res_row[2],
                    'assigned_at': res_row[3].strftime('%Y-%m-%d %H:%M:%S') if res_row[3] else None
                }
                
                if res_row[1] == 'domain':
                    resources['domains'].append(resource_data)
                elif res_row[1] == 'ipv4':
                    resources['ipv4s'].append(resource_data)
                elif res_row[1] == 'phone':
                    resources['phones'].append(resource_data)
            
            cur2.close()
            conn2.close()
            
            licenses.append({
                'id': row[0],
                'license_key': row[1],
                'license_type': row[2],
                'is_active': row[3],
                'is_fake': row[4],
                'valid_from': row[5].strftime('%Y-%m-%d') if row[5] else None,
                'valid_until': row[6].strftime('%Y-%m-%d') if row[6] else None,
                'device_limit': row[7],
                'created_at': row[8].strftime('%Y-%m-%d %H:%M:%S') if row[8] else None,
                'status': row[9],
                'domain_count': row[10],
                'ipv4_count': row[11],
                'phone_count': row[12],
                'active_sessions': 0,  # Platzhalter
                'registered_devices': 0,  # Platzhalter
                'active_devices': 0,  # Platzhalter
                'actual_domain_count': len(resources['domains']),
                'actual_ipv4_count': len(resources['ipv4s']),
                'actual_phone_count': len(resources['phones']),
                'resources': resources,
                # License Server Data (Platzhalter bis Implementation)
                'recent_heartbeats': 0,
                'last_heartbeat': None,
                'active_server_devices': 0,
                'unresolved_anomalies': 0
            })
        
        return jsonify({
            'success': True,  # Wichtig: Frontend erwartet dieses Feld
            'customer': {
                'id': customer['id'],
                'name': customer['name'],
                'email': customer['email'],
                'is_fake': customer.get('is_fake', False)  # Include the is_fake field
            },
            'licenses': licenses
        })
        
    except Exception as e:
        import traceback
        error_msg = f"Fehler beim Laden der Kundenlizenzen: {str(e)}\nTraceback: {traceback.format_exc()}"
        logging.error(error_msg)
        return jsonify({'error': f'Fehler beim Laden der Daten: {str(e)}', 'details': error_msg}), 500
    finally:
        cur.close()
        conn.close()


@customer_bp.route("/api/customer/<int:customer_id>/quick-stats")
@login_required
def api_customer_quick_stats(customer_id):
    """Schnelle Statistiken für einen Kunden"""
    conn = get_connection()
    cur = conn.cursor()
    
    try:
        cur.execute("""
            SELECT 
                COUNT(l.id) as total_licenses,
                COUNT(CASE WHEN l.is_active = true THEN 1 END) as active_licenses,
                COUNT(CASE WHEN l.is_fake = true THEN 1 END) as test_licenses,
                SUM(l.device_limit) as total_device_limit
            FROM licenses l
            WHERE l.customer_id = %s
        """, (customer_id,))
        
        row = cur.fetchone()
        
        return jsonify({
            'total_licenses': row[0] or 0,
            'active_licenses': row[1] or 0,
            'test_licenses': row[2] or 0,
            'total_device_limit': row[3] or 0
        })
        
    except Exception as e:
        logging.error(f"Fehler beim Laden der Kundenstatistiken: {str(e)}")
        return jsonify({'error': 'Fehler beim Laden der Daten'}), 500
    finally:
        cur.close()
        conn.close()