import gspread
from oauth2client.service_account import ServiceAccountCredentials
import tensorflow as tf
tf.config.run_functions_eagerly(True)
tf.data.experimental.enable_debug_mode()
from tensorflow import keras
from tensorflow.keras.utils import to_categorical
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.utils import shuffle
import matplotlib.pyplot as plt
from sklearn.metrics import classification_report

# Set up credentials and connect to Google Sheets
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
creds = ServiceAccountCredentials.from_json_keyfile_name('/home/credentials.json', scope)
client = gspread.authorize(creds)

# Open the sheet and get the data
sheet = client.open("Projectdata").sheet1
data = sheet.get_all_records()
df = pd.DataFrame(data)


# Data Preprocessing: Clean the data by converting columns to numeric and removing invalid values
df['GSRdata'] = pd.to_numeric(df['GSRdata'], errors='coerce')
df['EMGdata'] = pd.to_numeric(df['EMGdata'], errors='coerce')
df['Soreness'] = pd.to_numeric(df['Soreness'], errors='coerce')

# Print the number of rows with missing values
print(df.isnull().any(axis=1).sum())

# Fill missing values with the mean value of the column
df.fillna(df.mean(), inplace=True)

# Separate the data into inputs (GSR and EMG sensor data) and outputs (relaxed, tense, exhausted)
inputs = df[['GSRdata', 'EMGdata']].values
outputs = df[['Soreness']].values

# KNN Imputation for missing values in inputs
knn_imputer = KNNImputer(n_neighbors=5)
inputs_imputed = knn_imputer.fit_transform(inputs)

# Data Scaling (Normalizing)
scaler = MinMaxScaler()
inputs = scaler.fit_transform(inputs)

# Data Splitting: Split the data into training and validation sets
x_train, x_val, y_train, y_val = train_test_split(inputs, outputs, test_size=0.2)

# Further split the validation set into validation and test sets
x_val, x_test, y_val, y_test = train_test_split(x_val, y_val, test_size=0.5)

# Convert the outputs to a numeric data type and one-hot encode them
y_train = to_categorical(y_train.astype(np.float32))
y_val = to_categorical(y_val.astype(np.float32))
y_test = to_categorical(y_test.astype(np.float32))

# Create a neural network model
model = keras.Sequential([
    keras.layers.Dense(32, input_shape=(2,), activation='relu'),
    keras.layers.Dense(16, activation='relu'),
    keras.layers.Dense(8, activation='relu'),
    keras.layers.Dense(3, activation='softmax')
])

# Compile the model with eager execution enabled
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'], run_eagerly=True)

# Train the model on the training data and validate on the validation data
history = model.fit(x_train, y_train, epochs=200, validation_data=(x_val, y_val))

# Evaluate the model on the test data
test_loss, test_acc = model.evaluate(x_test, y_test)
print('Test accuracy:', test_acc)

# Get the predicted labels and true labels for the test data
y_pred = model.predict(x_test)
y_pred_labels = np.argmax(y_pred, axis=1)
y_test_labels = np.argmax(y_test, axis=1)

# Calculate the precision, recall, and F1-score of the model
report = classification_report(y_test_labels, y_pred_labels)
print("Classification Report:\n", report)

# Save the model to use with TensorFlow Lite
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
open("/home/model.tflite", "wb").write(tflite_model)

#Plot the training and validation accuracy
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()