# Importa le librerie necessarie
import pandas as pd
import mysql.connector
from datetime import datetime, timedelta
import logging

# Configura il logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# Configura la connessione al database
db_config = {
    'user': 'root',
    'password': 'Hdgtejskjjc0-',
    'host': 'localhost',
    'database': 'LOG_MIKROTIK',
    'raise_on_warnings': True
}

# Funzione per estrarre i nuovi dati dal database
def estrai_nuovi_dati(ultimo_id):
    logging.info(f"Estrazione dei nuovi dati a partire da ID > {ultimo_id}...")
    cnx = mysql.connector.connect(**db_config)
    query = f"SELECT ID, Data, Ora, Host, IndirizzoIP, Messaggio1, Messaggio2, Messaggio3 FROM Esterna WHERE ID > {ultimo_id}"
    df = pd.read_sql(query, cnx)
    cnx.close()
    if not df.empty:
        df['Timestamp'] = pd.to_datetime(df['Data'] + ' ' + df['Ora'])
    logging.info(f"Dati estratti: {len(df)} record.")
    return df

# Funzione per pre-elaborare i dati e creare le nuove caratteristiche
def pre_elabora_dati(df):
    logging.info("Pre-elaborazione dei dati...")
    
    # Rinomina le colonne per chiarezza
    df.rename(columns={
        'Messaggio1': 'Protocollo',
        'Messaggio2': 'IP_Sorgente',
        'Messaggio3': 'IP_Destinazione'
    }, inplace=True)
    
    # Estrae indirizzi IP e porte
    df[['IP_Sorgente', 'Porta_Sorgente']] = df['IP_Sorgente'].str.split(':', expand=True)
    df[['IP_Destinazione', 'Porta_Destinazione']] = df['IP_Destinazione'].str.split(':', expand=True)
    
    # Converti le porte in numeri interi
    df['Porta_Sorgente'] = pd.to_numeric(df['Porta_Sorgente'], errors='coerce')
    df['Porta_Destinazione'] = pd.to_numeric(df['Porta_Destinazione'], errors='coerce')
    
    # Aggiungi una colonna per l'IP esterno (ipotizzando che l'IP esterno sia sempre l'IP di origine)
    df['IP_Esterno'] = df['IP_Sorgente']
    df['IP_Interno'] = df['IP_Destinazione']
    
    # Filtra i dati per l'intervallo di tempo desiderato (ad esempio, ultimi 5 minuti)
    tempo_iniziale = df['Timestamp'].max() - timedelta(minutes=5)
    df = df[df['Timestamp'] >= tempo_iniziale]
    
    return df

# Funzione per aggregare i dati e creare le nuove caratteristiche
def crea_caratteristiche(df):
    logging.info("Creazione delle nuove caratteristiche...")
    
    # Raggruppa per IP esterno nell'intervallo di tempo
    aggregated = df.groupby(['IP_Esterno']).agg(
        num_ip_interni_contattati=('IP_Interno', 'nunique'),
        num_connessioni=('IP_Interno', 'count'),
        num_porte_uniche=('Porta_Destinazione', 'nunique')
    ).reset_index()
    
    return aggregated

# Funzione principale
def main():
    # Leggi l'ultimo ID elaborato (puoi memorizzarlo in un file o database)
    ultimo_id = leggi_ultimo_id()
    
    # Estrai i nuovi dati
    df_nuovi = estrai_nuovi_dati(ultimo_id)
    
    if df_nuovi.empty:
        logging.info("Nessun nuovo dato da elaborare.")
        return
    
    # Pre-elabora i dati
    df_preparato = pre_elabora_dati(df_nuovi)
    
    # Crea le nuove caratteristiche
    df_caratteristiche = crea_caratteristiche(df_preparato)
    
    # Salva il nuovo ultimo ID
    salva_ultimo_id(df_nuovi['ID'].max())
    
    # Salva o restituisci il DataFrame delle caratteristiche per l'uso nel modello
    df_caratteristiche.to_csv('caratteristiche.csv', index=False)
    logging.info("Caratteristiche salvate nel file 'caratteristiche.csv'.")

# Funzioni per leggere e salvare l'ultimo ID elaborato
def leggi_ultimo_id():
    try:
        with open('ultimo_id.txt', 'r') as f:
            ultimo_id = int(f.read().strip())
    except FileNotFoundError:
        ultimo_id = 0
    return ultimo_id

def salva_ultimo_id(ultimo_id):
    with open('ultimo_id.txt', 'w') as f:
        f.write(str(ultimo_id))

if __name__ == "__main__":
    main()
