import mysql.connector
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_squared_error

# Funzione per connettersi al database e recuperare i dati
def carica_dati_da_database():
    # Connessione al database MySQL
    conn = mysql.connector.connect(
        host="localhost",
        user="root",
        password="eledia77",
        database="FLORATECH"
    )
    cursor = conn.cursor()

    # Query per selezionare i dati di umidità e tempo
    query = "SELECT time, umidita FROM umidita_pianta ORDER BY time ASC"
    cursor.execute(query)

    # Recupera i risultati
    dati = cursor.fetchall()

    # Chiudi la connessione
    cursor.close()
    conn.close()

    # Converte i dati in un DataFrame pandas
    df = pd.DataFrame(dati, columns=["time", "umidita"])
    return df

# Funzione per creare il modello di regressione lineare
def crea_modello(X, y):
    model = LinearRegression()
    model.fit(X, y)
    return model

# Funzione per visualizzare i grafici
def visualizza_grafici(X, y, y_pred, nome_modello, affidabilita):
    plt.scatter(X, y, color='blue', label='Dati reali')
    plt.plot(X, y_pred, color='red', label='Previsioni')
    plt.title(f'Regressione Lineare ({nome_modello}) - Affidabilità: {affidabilita:.2f}%')
    plt.xlabel('Ora del giorno')
    plt.ylabel('Umidità')
    plt.legend()
    plt.show()

# Funzione principale
def main():
    # Caricamento dei dati dal database
    df = carica_dati_da_database()

    # Conversione del campo 'time' in ore del giorno
    df['time'] = pd.to_datetime(df['time'])
    df['hour'] = df['time'].dt.hour

    # Separazione tra caratteristiche (X) e target (y)
    X = df[['hour']]
    y = df['umidita']

    # Divisione in set di addestramento e test
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    # Creazione e addestramento del modello
    modello = crea_modello(X_train, y_train)

    # Previsioni per i dati di test
    y_pred_train = modello.predict(X_train)
    y_pred_test = modello.predict(X_test)

    # Calcolo dell'affidabilità e dell'errore
    affidabilita_train = r2_score(y_train, y_pred_train) * 100
    affidabilita_test = r2_score(y_test, y_pred_test) * 100
    errore_mse = mean_squared_error(y_test, y_pred_test)

    # Previsione per il giorno successivo (0-23 ore)
    ore_del_giorno = np.arange(0, 24).reshape(-1, 1)
    previsioni_giorno_successivo = modello.predict(ore_del_giorno)

    # Verifica se l'umidità scenderà sotto i 300
    ore_sotto_300 = [i for i, pred in enumerate(previsioni_giorno_successivo) if pred < 300]
    ora_sotto_300 = ore_sotto_300[0] if ore_sotto_300 else None

    # Output dei risultati
    print(f"Affidabilità sul set di addestramento: {affidabilita_train:.2f}%")
    print(f"Affidabilità sul set di test: {affidabilita_test:.2f}%")
    print(f"Errore Quadratico Medio (MSE) sul set di test: {errore_mse:.2f}")
    if ora_sotto_300 is not None:
        print(f"L'umidità scenderà sotto 300 alle ore: {ora_sotto_300}:00")
    else:
        print("L'umidità non scenderà sotto 300 nelle prossime 24 ore.")

    # Visualizzazione dei grafici
    visualizza_grafici(X_train, y_train, y_pred_train, "Set di Addestramento", affidabilita_train)
    visualizza_grafici(X_test, y_test, y_pred_test, "Set di Test", affidabilita_test)
    visualizza_grafici(ore_del_giorno, previsioni_giorno_successivo, previsioni_giorno_successivo, "Previsioni per il Giorno Successivo", affidabilita_test)

if __name__ == "__main__":
    main()
