#!/usr/bin/env python3

import paramiko
import mysql.connector
from mysql.connector import Error
from datetime import datetime, timedelta
import logging
import re
from dotenv import load_dotenv
import os

# Carica le variabili d'ambiente
load_dotenv()

# Configurazione del logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

# Configurazione del database
db_config = {
    'user': os.getenv('DB_USER'),
    'password': os.getenv('DB_PASSWORD'),
    'host': os.getenv('DB_HOST'),
    'database': os.getenv('DB_NAME'),
}

def connect_to_database():
    try:
        logging.info('🔗 Connessione al database...')
        db = mysql.connector.connect(**db_config)
        logging.info('✅ Connessione al database riuscita.')
        return db
    except Error as e:
        logging.error(f'❌ Errore di connessione al database: {e}')
        exit(1)

def get_routers(cursor):
    try:
        logging.info('📡 Recupero dell\'elenco dei router dal database...')
        cursor.execute("SELECT * FROM routers")
        routers = cursor.fetchall()
        if not routers:
            logging.warning('⚠️ Nessun router trovato nel database.')
            exit(0)
        logging.info(f'✅ Trovati {len(routers)} router nel database.')
        return routers
    except Error as e:
        logging.error(f'❌ Errore nel recupero dei router: {e}')
        exit(1)

def connect_to_router(router_host, ssh_username, ssh_password):
    try:
        logging.info(f'🔐 Connessione al router {router_host} via SSH...')
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(router_host, username=ssh_username, password=ssh_password, timeout=10)
        logging.info(f'✅ Connessione SSH al router {router_host} riuscita.')
        return ssh
    except paramiko.ssh_exception.AuthenticationException as e:
        logging.error(f'🔒 Autenticazione fallita per il router {router_host}: {e}')
    except paramiko.ssh_exception.SSHException as e:
        logging.error(f'📡 Errore SSH con il router {router_host}: {e}')
    except Exception as e:
        logging.error(f'❌ Errore nella connessione al router {router_host}: {e}')
    return None

def get_address_list(ssh, list_name):
    try:
        command = f"/ip firewall address-list print where list={list_name}"
        logging.info(f'⚙️ Esecuzione del comando sul router: {command}')
        stdin, stdout, stderr = ssh.exec_command(command)
        output = stdout.read().decode('utf-8', errors='ignore')
        error_output = stderr.read().decode('utf-8', errors='ignore')

        if error_output:
            logging.error(f'❌ Errore durante l\'esecuzione del comando: {error_output}')
            return []

        logging.debug(f'📋 Output del comando "{command}":\n{output}')
        return parse_address_list_output(output)
    except Exception as e:
        logging.error(f'❌ Errore nella get_address_list per {list_name}: {e}')
        return []

def add_ip_to_list(ssh, ip_address, list_name, timeout=None):
    """
    🆕 Aggiunge un IP alla address-list del router MikroTik
    🕐 Supporta timeout automatico per ddos_detect_v03 e whitelist (60 minuti)
    """
    try:
        # 🆕 Timeout automatico per ddos_detect_v03 E whitelist
        if list_name == 'ddos_detect_v03':
            timeout = '1h'  # 60 minuti per IP DDoS detection
            logging.info(f'⏰ Applicando timeout 60min per {ip_address} in {list_name}')
        elif list_name == 'whitelist':
            timeout = '1h'  # 🆕 60 minuti anche per whitelist (sicurezza)
            logging.info(f'⏰ Applicando timeout 60min per {ip_address} in whitelist (sicurezza)')
        
        # Costruzione comando con o senza timeout
        if timeout:
            command = f'/ip firewall address-list add list={list_name} address={ip_address} timeout={timeout} comment="Added by DDoS System - {datetime.now().strftime("%Y-%m-%d %H:%M")} - Timeout: {timeout}"'
        else:
            command = f'/ip firewall address-list add list={list_name} address={ip_address} comment="Added by DDoS System - {datetime.now().strftime("%Y-%m-%d %H:%M")}"'
            
        logging.info(f'➕ Aggiungendo {ip_address} alla lista {list_name}{"" if not timeout else f" con timeout {timeout}"}...')
        
        stdin, stdout, stderr = ssh.exec_command(command)
        error_output = stderr.read().decode('utf-8', errors='ignore')
        
        if error_output and 'already exists' not in error_output.lower():
            logging.error(f'❌ Errore aggiungendo {ip_address} a {list_name}: {error_output}')
            return False
        elif 'already exists' in error_output.lower():
            logging.debug(f'ℹ️ IP {ip_address} già presente in {list_name}')
            return True
            
        if timeout:
            logging.info(f'✅ IP {ip_address} aggiunto alla lista {list_name} con timeout {timeout}')
        else:
            logging.info(f'✅ IP {ip_address} aggiunto alla lista {list_name}')
        return True
        
    except Exception as e:
        logging.error(f'❌ Errore nella funzione add_ip_to_list: {e}')
        return False

def parse_address_list_output(output):
    ips = []
    lines = output.strip().split('\n')
    current_comment = ''
    
    for line in lines:
        line = line.strip()
        logging.debug(f'📝 Linea analizzata: {line}')
        
        # Salta le linee vuote
        if not line:
            continue
            
        # Salta le linee non pertinenti
        if line.startswith('Flags:') or line.startswith('Columns:') or line.startswith('#'):
            continue
            
        # Se la linea inizia con ';;;', è un commento
        if line.startswith(';;;'):
            current_comment = line[4:].strip()
            continue
            
        # Se la linea inizia con un numero, è un entry
        if re.match(r'^\d', line):
            parts = line.split()
            idx = 0
            
            if len(parts) < 3:  # Controllo minimo campi richiesti
                continue
                
            index = parts[idx]
            idx += 1
            
            # Controlla se il prossimo elemento è un flag
            flags = ''
            if idx < len(parts) and re.match(r'^[A-Z]+$', parts[idx]):
                flags = parts[idx]
                idx += 1
                
            # Nome della lista
            if idx < len(parts):
                list_name = parts[idx]
                idx += 1
            else:
                list_name = ''
                
            # Indirizzo IP
            if idx < len(parts):
                ip_address = parts[idx]
                idx += 1
            else:
                ip_address = ''
                
            # Creazione dell'entry solo se abbiamo dati validi
            if list_name and ip_address:
                entry = {
                    'list_name': list_name,
                    'ip_address': ip_address,
                    'comment': current_comment
                }
                ips.append(entry)
                logging.debug(f'✅ Aggiunta entry: {entry}')
                
            # Reset del commento corrente
            current_comment = ''
        else:
            # Linea non riconosciuta
            logging.warning(f'⚠️ Linea non riconosciuta: {line}')
            
    logging.debug(f'📊 IP estratti: {len(ips)} entries')
    return ips

def insert_ips_into_database(cursor, db, router_id, ips):
    if not ips:
        logging.info(f'ℹ️ Nessun IP da inserire per router ID {router_id}')
        return
        
    inserted_count = 0
    updated_count = 0
    
    for ip in ips:
        try:
            cursor.execute("""
                INSERT INTO router_data (router_id, list_name, ip_address, comment)
                VALUES (%s, %s, %s, %s)
                ON DUPLICATE KEY UPDATE comment=%s, retrieved_at=%s
            """, (router_id, ip['list_name'], ip['ip_address'], ip['comment'], ip['comment'], datetime.now()))
            
            if cursor.rowcount == 1:
                inserted_count += 1
            elif cursor.rowcount == 2:
                updated_count += 1
                
            db.commit()
            logging.debug(f'💾 Processato IP {ip["ip_address"]} nella lista {ip["list_name"]} per router ID {router_id}')
            
        except mysql.connector.Error as err:
            logging.error(f"❌ Errore nell'inserimento di {ip['ip_address']}: {err}")
            
    logging.info(f'📊 Router ID {router_id}: {inserted_count} IP inseriti, {updated_count} IP aggiornati')

def cleanup_old_ips(cursor, db):
    """
    🆕 Rimuove gli IP più vecchi delle soglie specificate 
    📊 AGGIORNATO: ddos_detect_v03 da ip_list, ddos2/ddos3-attackers da router_data
    """
    cleanup_stats = {}
    
    try:
        logging.info('🧹 === PULIZIA DATABASE ===')
        
        # 🆕 Pulizia tabella ip_list (solo ddos_detect_v03)
        logging.info('📋 Pulizia tabella ip_list...')
        list_name = 'ddos_detect_v03'
        days = 7
        
        logging.info(f'🧹 Pulizia lista {list_name} da ip_list (>{days} giorni)...')
        
        # Prima conta quanti record verranno eliminati
        cursor.execute("""
            SELECT COUNT(*) as count FROM ip_list 
            WHERE list_name = %s 
            AND retrieved_at < DATE_SUB(NOW(), INTERVAL %s DAY)
        """, (list_name, days))
        
        count_result = cursor.fetchone()
        records_to_delete = count_result['count'] if count_result else 0
        
        if records_to_delete == 0:
            logging.info(f'ℹ️ Nessun record da eliminare per {list_name} in ip_list')
            cleanup_stats[f'{list_name}_ip_list'] = 0
        else:
            # Esegui la pulizia
            cursor.execute("""
                DELETE FROM ip_list 
                WHERE list_name = %s 
                AND retrieved_at < DATE_SUB(NOW(), INTERVAL %s DAY)
            """, (list_name, days))
            
            deleted_count = cursor.rowcount
            cleanup_stats[f'{list_name}_ip_list'] = deleted_count
            logging.info(f'✅ ip_list {list_name}: eliminati {deleted_count} record più vecchi di {days} giorni')
        
        # 🆕 Pulizia tabella router_data (ddos2-attackers e ddos3-attackers)
        logging.info('🎯 Pulizia tabella router_data...')
        router_data_policies = [
            ('ddos2-attackers', 15),   # Lista attackers livello 2  
            ('ddos3-attackers', 20)    # Lista attackers livello 3
        ]
        
        for list_name, days in router_data_policies:
            logging.info(f'🧹 Pulizia lista {list_name} da router_data (>{days} giorni)...')
            
            # Prima conta quanti record verranno eliminati
            cursor.execute("""
                SELECT COUNT(*) as count FROM router_data 
                WHERE list_name = %s 
                AND retrieved_at < DATE_SUB(NOW(), INTERVAL %s DAY)
            """, (list_name, days))
            
            count_result = cursor.fetchone()
            records_to_delete = count_result['count'] if count_result else 0
            
            if records_to_delete == 0:
                logging.info(f'ℹ️ Nessun record da eliminare per {list_name} in router_data')
                cleanup_stats[f'{list_name}_router_data'] = 0
            else:
                # Esegui la pulizia
                cursor.execute("""
                    DELETE FROM router_data 
                    WHERE list_name = %s 
                    AND retrieved_at < DATE_SUB(NOW(), INTERVAL %s DAY)
                """, (list_name, days))
                
                deleted_count = cursor.rowcount
                cleanup_stats[f'{list_name}_router_data'] = deleted_count
                logging.info(f'✅ router_data {list_name}: eliminati {deleted_count} record più vecchi di {days} giorni')
        
        db.commit()
        
        # Statistiche finali
        total_deleted = sum(cleanup_stats.values())
        logging.info(f'🎯 Pulizia completata: {total_deleted} record totali eliminati')
        
        for key, count in cleanup_stats.items():
            if count > 0:
                logging.info(f'   └─ {key}: {count} record eliminati')
        
    except Error as e:
        logging.error(f"❌ Errore durante la pulizia degli IP vecchi: {e}")
        db.rollback()

def check_expired_ips_on_router(ssh, router_host):
    """
    🆕 Verifica IP scaduti sul router e fornisce statistiche
    📊 AGGIORNATO: liste corrette senza ddos_ia
    """
    try:
        logging.info(f'🕐 Verifica IP scaduti sul router {router_host}...')
        
        # 🆕 Lista delle liste da controllare (senza ddos_ia)
        lists_to_check = ['ddos_detect_v03', 'ddos2-attackers', 'ddos3-attackers', 'whitelist']
        
        total_active_ips = 0
        timeout_stats = {}
        
        for list_name in lists_to_check:
            current_ips = get_address_list(ssh, list_name)
            count = len([ip for ip in current_ips if 'ip_address' in ip])
            total_active_ips += count
            timeout_stats[list_name] = count
            
            if count > 0:
                logging.info(f'📊 Lista {list_name}: {count} IP attivi')
        
        logging.info(f'🎯 Router {router_host}: {total_active_ips} IP totali attivi')
        
        # Log specifico per ddos_detect_v03 con timeout
        if timeout_stats.get('ddos_detect_v03', 0) > 0:
            logging.info(f'⏰ Lista ddos_detect_v03: {timeout_stats["ddos_detect_v03"]} IP con timeout 60min attivi')
        
        return timeout_stats
        
    except Exception as e:
        logging.error(f'❌ Errore verifica IP scaduti su router {router_host}: {e}')
        return {}

def check_global_whitelist_conflicts(cursor, db):
    """
    🆕 Controlla e risolve conflitti tra whitelistGlobale e ddos_detect_v03
    """
    try:
        logging.info('🛡️ === CONTROLLO WHITELIST GLOBALE ===')
        
        # Trova IP che sono sia in whitelist globale che in ddos_detect_v03
        cursor.execute("""
            SELECT DISTINCT w.ip_address, w.comment, w.reason
            FROM whitelistGlobale w
            INNER JOIN ip_list i ON w.ip_address = i.ip_address
            WHERE w.active = 1 
            AND i.list_name = 'ddos_detect_v03'
        """)
        
        conflicts = cursor.fetchall()
        
        if not conflicts:
            logging.info('✅ Nessun conflitto trovato tra whitelist globale e ddos_detect_v03')
            return
        
        logging.info(f'⚠️ Trovati {len(conflicts)} IP in conflitto da risolvere')
        
        resolved_count = 0
        for conflict in conflicts:
            ip_address = conflict['ip_address']
            comment = conflict['comment'] or 'Whitelist globale'
            reason = conflict['reason'] or 'Risoluzione automatica conflitto'
            
            # Rimuovi da ddos_detect_v03
            cursor.execute("""
                DELETE FROM ip_list 
                WHERE ip_address = %s AND list_name = 'ddos_detect_v03'
            """, (ip_address,))
            
            if cursor.rowcount > 0:
                resolved_count += 1
                logging.info(f'✅ Rimosso {ip_address} da ddos_detect_v03 (motivo: {reason})')
        
        db.commit()
        logging.info(f'🎯 Risolti {resolved_count} conflitti whitelist vs blacklist')
        
    except Error as e:
        logging.error(f"❌ Errore controllo whitelist globale: {e}")
        db.rollback()

def sync_global_whitelist_to_routers(cursor, db, ssh, router_host):
    """
    🆕 Sincronizza whitelistGlobale con tutti i router
    🕐 AGGIORNATO: applica timeout 60min anche alla whitelist per sicurezza
    """
    try:
        logging.info(f'🌐 Sincronizzazione whitelist globale per router {router_host}...')
        
        # Recupera IP attivi dalla whitelist globale
        cursor.execute("""
            SELECT ip_address, comment, reason, last_sync
            FROM whitelistGlobale 
            WHERE active = 1
            ORDER BY created_at DESC
        """)
        
        global_whitelist = cursor.fetchall()
        
        if not global_whitelist:
            logging.info(f'ℹ️ Nessun IP nella whitelist globale')
            return 0, 0
        
        logging.info(f'📋 Trovati {len(global_whitelist)} IP nella whitelist globale')
        
        # Ottieni whitelist corrente dal router
        current_whitelist = get_address_list(ssh, 'whitelist')
        current_whitelist_set = {entry['ip_address'] for entry in current_whitelist if 'ip_address' in entry}
        
        added_count = 0
        updated_count = 0
        timeout_applied = 0
        
        for entry in global_whitelist:
            ip_address = entry['ip_address']
            comment = entry['comment'] or 'Whitelist globale'
            reason = entry['reason'] or 'IP fidato globale'
            
            if ip_address not in current_whitelist_set:
                # 🆕 Aggiungi alla whitelist del router CON TIMEOUT 60min
                if add_ip_to_list(ssh, ip_address, 'whitelist'):  # Timeout automatico applicato
                    added_count += 1
                    timeout_applied += 1  # 🆕 Conta timeout whitelist
                    
                    # Aggiorna last_sync
                    cursor.execute("""
                        UPDATE whitelistGlobale 
                        SET last_sync = NOW() 
                        WHERE ip_address = %s
                    """, (ip_address,))
                    updated_count += 1
                    
                    logging.info(f'✅ IP {ip_address} aggiunto alla whitelist router {router_host} con timeout 60min')
            else:
                logging.debug(f'➖ IP {ip_address} già presente nella whitelist router {router_host}')
        
        if updated_count > 0:
            db.commit()
        
        logging.info(f'🌐 Whitelist globale router {router_host}: {added_count} IP aggiunti, {timeout_applied} timeout applicati')
        return added_count, timeout_applied
        
    except Error as e:
        logging.error(f"❌ Errore sincronizzazione whitelist globale router {router_host}: {e}")
        return 0, 0

def sync_ip_list_to_routers(cursor, db, ssh, router_id, router_host):
    """
    🆕 Sincronizza SOLO ddos_detect_v03 dalla tabella ip_list con il router
    📊 AGGIORNATO: controlla whitelist globale prima di bloccare IP
    """
    try:
        # 🆕 Query ottimizzata per SOLO ddos_detect_v03 ESCLUDENDO whitelist globale
        logging.info(f'📊 Recupero IP ddos_detect_v03 (esclusi whitelist globale) per router {router_host}...')
        
        cursor.execute("""
            SELECT i.list_name, i.ip_address, i.retrieved_at 
            FROM ip_list i
            LEFT JOIN whitelistGlobale w ON i.ip_address = w.ip_address AND w.active = 1
            WHERE i.list_name = 'ddos_detect_v03'
            AND i.retrieved_at > DATE_SUB(NOW(), INTERVAL 3 DAY)
            AND w.ip_address IS NULL  -- 🆕 Escludi IP in whitelist globale
            ORDER BY i.retrieved_at DESC 
            LIMIT 3000
        """)
        
        ip_list_entries = cursor.fetchall()
        
        if not ip_list_entries:
            logging.info(f'ℹ️ Nessun IP ddos_detect_v03 da bloccare (whitelist globale applicata)')
            return
        
        logging.info(f'📋 Trovati {len(ip_list_entries)} IP ddos_detect_v03 da sincronizzare (dopo filtro whitelist)')
        
        # Ottieni la lista corrente dal router
        current_ips = get_address_list(ssh, 'ddos_detect_v03')
        current_ips_set = {entry['ip_address'] for entry in current_ips if 'ip_address' in entry}
        
        # 🆕 Ottieni anche whitelist corrente per doppio controllo
        current_whitelist = get_address_list(ssh, 'whitelist')
        current_whitelist_set = {entry['ip_address'] for entry in current_whitelist if 'ip_address' in entry}
        
        added_count = 0
        timeout_applied = 0
        skipped_whitelist = 0
        
        # Processa solo ddos_detect_v03
        for entry in ip_list_entries:
            ip_address = entry['ip_address']
            
            # 🆕 Doppio controllo: non bloccare IP in whitelist router
            if ip_address in current_whitelist_set:
                skipped_whitelist += 1
                logging.debug(f'🛡️ IP {ip_address} saltato - presente in whitelist router')
                continue
            
            if ip_address not in current_ips_set:
                if add_ip_to_list(ssh, ip_address, 'ddos_detect_v03'):  # Timeout automatico applicato
                    added_count += 1
                    timeout_applied += 1
                else:
                    logging.warning(f'⚠️ Fallita aggiunta {ip_address} a ddos_detect_v03')
            else:
                logging.debug(f'➖ IP {ip_address} già presente in ddos_detect_v03')
        
        # Statistiche
        logging.info(f'✅ Lista ddos_detect_v03: aggiunti {added_count} nuovi IP')
        logging.info(f'⏰ Timeout 60min applicati: {timeout_applied} IP in ddos_detect_v03')
        if skipped_whitelist > 0:
            logging.info(f'🛡️ IP saltati per whitelist: {skipped_whitelist}')
        logging.info(f'🎯 Sincronizzazione ddos_detect_v03 completata su router {router_host}')
        
    except Error as e:
        logging.error(f"❌ Errore durante la sincronizzazione ddos_detect_v03 con router {router_host}: {e}")

def sync_router_data_to_routers(cursor, db, ssh, router_id, router_host):
    """
    🆕 Sincronizza ddos2-attackers, ddos3-attackers e whitelist dalla tabella router_data
    📊 AGGIORNATO: gestione specifica per router e whitelist CON TIMEOUT
    """
    try:
        logging.info(f'🎯 Sincronizzazione dati router_data per router {router_host} (ID: {router_id})...')
        
        # 🆕 Query per ddos2-attackers e ddos3-attackers specifici del router
        cursor.execute("""
            SELECT list_name, ip_address, retrieved_at, whitelist, added_to_router
            FROM router_data 
            WHERE router_id = %s 
            AND list_name IN ('ddos2-attackers', 'ddos3-attackers')
            AND retrieved_at > DATE_SUB(NOW(), INTERVAL 7 DAY)
            ORDER BY retrieved_at DESC
            LIMIT 2000
        """, (router_id,))
        
        router_entries = cursor.fetchall()
        
        total_added = 0
        whitelist_timeout_applied = 0
        
        if not router_entries:
            logging.info(f'ℹ️ Nessun dato ddos2/ddos3-attackers recente per router {router_host}')
        else:
            logging.info(f'📋 Trovati {len(router_entries)} record ddos2/ddos3-attackers per router {router_host}')
            
            # Raggruppa per lista
            lists_data = {}
            whitelist_ips = []
            
            for entry in router_entries:
                list_name = entry['list_name']
                ip_address = entry['ip_address']
                is_whitelist = entry['whitelist'] == 1
                
                if is_whitelist:
                    whitelist_ips.append(entry)
                else:
                    if list_name not in lists_data:
                        lists_data[list_name] = []
                    lists_data[list_name].append(ip_address)
            
            # Processa liste ddos2/ddos3-attackers (SENZA timeout)
            for list_name, ip_addresses in lists_data.items():
                logging.info(f'🔄 Sincronizzazione lista {list_name} ({len(ip_addresses)} IP) per router {router_host}...')
                
                # Ottieni lista corrente dal router
                current_ips = get_address_list(ssh, list_name)
                current_ips_set = {entry['ip_address'] for entry in current_ips if 'ip_address' in entry}
                
                added_count = 0
                for ip_address in ip_addresses:
                    if ip_address not in current_ips_set:
                        if add_ip_to_list(ssh, ip_address, list_name):  # Nessun timeout per queste liste
                            added_count += 1
                            total_added += 1
                
                if added_count > 0:
                    logging.info(f'✅ Lista {list_name}: aggiunti {added_count} IP per router {router_host}')
            
            # 🆕 Gestione whitelist specifica CON TIMEOUT
            if whitelist_ips:
                logging.info(f'🛡️ Elaborazione {len(whitelist_ips)} IP per whitelist router {router_host} (CON TIMEOUT)...')
                whitelist_added = 0
                
                # Ottieni whitelist corrente
                current_whitelist = get_address_list(ssh, 'whitelist')
                current_whitelist_set = {entry['ip_address'] for entry in current_whitelist if 'ip_address' in entry}
                
                for entry in whitelist_ips:
                    ip_address = entry['ip_address']
                    
                    if ip_address not in current_whitelist_set:
                        if add_ip_to_list(ssh, ip_address, 'whitelist'):  # 🆕 CON TIMEOUT 60min
                            # Aggiorna il database: marca come aggiunto al router
                            cursor.execute("""
                                UPDATE router_data 
                                SET added_to_router = 1 
                                WHERE ip_address = %s AND router_id = %s AND whitelist = 1
                            """, (ip_address, router_id))
                            db.commit()
                            whitelist_added += 1
                            whitelist_timeout_applied += 1  # 🆕 Conta timeout whitelist
                            logging.info(f'✅ IP {ip_address} aggiunto alla whitelist router {router_host} con timeout 60min')
                
                logging.info(f'🛡️ Whitelist router {router_host}: aggiunti {whitelist_added} IP con timeout')
            
            logging.info(f'🎯 Sincronizzazione router_data completata: {total_added} IP ddos2/ddos3-attackers aggiunti')
        
        # 🆕 Gestione IP whitelist non ancora aggiunti (query separata per performance)
        cursor.execute("""
            SELECT ip_address FROM router_data
            WHERE whitelist = 1 AND router_id = %s AND added_to_router = 0
            AND retrieved_at > DATE_SUB(NOW(), INTERVAL 7 DAY)
        """, (router_id,))
        
        pending_whitelist = cursor.fetchall()
        
        if pending_whitelist:
            logging.info(f'🛡️ Trovati {len(pending_whitelist)} IP whitelist pending per router {router_host}...')
            
            current_whitelist = get_address_list(ssh, 'whitelist')
            current_whitelist_set = {entry['ip_address'] for entry in current_whitelist if 'ip_address' in entry}
            
            added_whitelist = 0
            for ip_entry in pending_whitelist:
                ip_address = ip_entry['ip_address']
                
                if ip_address not in current_whitelist_set:
                    if add_ip_to_list(ssh, ip_address, 'whitelist'):  # 🆕 CON TIMEOUT 60min
                        cursor.execute("""
                            UPDATE router_data 
                            SET added_to_router = 1 
                            WHERE ip_address = %s AND router_id = %s AND whitelist = 1
                        """, (ip_address, router_id))
                        db.commit()
                        added_whitelist += 1
                        whitelist_timeout_applied += 1  # 🆕 Conta timeout
            
            if added_whitelist > 0:
                logging.info(f'🛡️ Whitelist pending router {router_host}: aggiunti {added_whitelist} IP con timeout')
        
        return whitelist_timeout_applied
        
    except Error as e:
        logging.error(f"❌ Errore durante la sincronizzazione router_data per router {router_host}: {e}")
        return 0

def main():
    logging.info('🚀 === AVVIO SISTEMA CONTROLLO ROUTER MIKROTIK ===')
    
    db = connect_to_database()
    cursor = db.cursor(dictionary=True)

    try:
        # 🆕 FASE 0: Controllo whitelist globale e risoluzione conflitti
        logging.info('🛡️ === FASE 0: CONTROLLO WHITELIST GLOBALE ===')
        check_global_whitelist_conflicts(cursor, db)

        # 🆕 Pulizia IP vecchi (ora gestisce correttamente le tabelle separate)
        logging.info('🧹 === FASE 1: PULIZIA IP OBSOLETI ===')
        cleanup_old_ips(cursor, db)

        # Recupera i router dal database
        logging.info('📡 === FASE 2: RECUPERO ROUTER ===')
        routers = get_routers(cursor)

        logging.info('🔄 === FASE 3: SINCRONIZZAZIONE ROUTER ===')
        successful_syncs = 0
        failed_syncs = 0
        total_ddos_timeouts = 0
        total_whitelist_timeouts = 0

        for router in routers:
            router_id = router['id']
            router_host = router['ip_address']
            ssh_username = router['ssh_username']
            ssh_password = router['ssh_password']

            logging.info(f'🎯 Elaborazione router {router_host} (ID: {router_id})...')

            ssh = connect_to_router(router_host, ssh_username, ssh_password)
            if ssh is None:
                failed_syncs += 1
                logging.error(f'❌ Saltato router {router_host} - connessione fallita')
                continue

            try:
                # 🆕 Verifica IP scaduti prima della sincronizzazione
                current_stats = check_expired_ips_on_router(ssh, router_host)
                
                # 🆕 0. Sincronizza whitelist globale (PRIMA di tutto) CON TIMEOUT
                global_added, global_timeouts = sync_global_whitelist_to_routers(cursor, db, ssh, router_host)
                total_whitelist_timeouts += global_timeouts
                
                # 1. Sincronizza ddos_detect_v03 da ip_list (con filtro whitelist globale)
                sync_ip_list_to_routers(cursor, db, ssh, router_id, router_host)
                
                # 2. Sincronizza ddos2-attackers, ddos3-attackers e whitelist da router_data
                router_whitelist_timeouts = sync_router_data_to_routers(cursor, db, ssh, router_id, router_host)
                total_whitelist_timeouts += router_whitelist_timeouts
                
                # 🆕 Verifica finale per statistiche timeout
                final_stats = check_expired_ips_on_router(ssh, router_host)
                ddos_v03_count = final_stats.get('ddos_detect_v03', 0)
                if ddos_v03_count > 0:
                    total_ddos_timeouts += ddos_v03_count
                
                successful_syncs += 1
                logging.info(f'✅ Router {router_host} sincronizzato con successo')
                
            except Exception as e:
                failed_syncs += 1
                logging.error(f'❌ Errore durante elaborazione router {router_host}: {e}')
            finally:
                ssh.close()
                logging.info(f'🔐 Connessione SSH al router {router_host} chiusa.')

        # Statistiche finali
        logging.info('📊 === STATISTICHE FINALI ===')
        logging.info(f'✅ Router sincronizzati con successo: {successful_syncs}')
        logging.info(f'❌ Router falliti: {failed_syncs}')
        logging.info(f'📡 Router totali processati: {len(routers)}')
        logging.info(f'⏰ IP ddos_detect_v03 con timeout 60min attivi: {total_ddos_timeouts}')
        logging.info(f'🛡️ IP whitelist con timeout 60min applicati: {total_whitelist_timeouts}')
        logging.info('🎯 Gestione automatica whitelist tramite campo router_data.whitelist=1')
        logging.info('🛡️ Protezione automatica whitelist globale applicata')
        logging.info('⏰ NUOVO: Timeout 60min applicato anche alla whitelist per maggiore sicurezza')
        
    except Exception as e:
        logging.error(f'❌ Errore critico nel main: {e}')
    finally:
        cursor.close()
        db.close()
        logging.info('🔗 Connessione al database chiusa.')
        logging.info('🏁 === FINE ESECUZIONE SISTEMA CONTROLLO ROUTER ===')

if __name__ == '__main__':
    main()
