import pandas as pd # data processing
import numpy as np # working with arrays
import itertools # construct specialized tools
import matplotlib.pyplot as plt # visualizations
from matplotlib import rcParams # plot size customization
from termcolor import colored as cl # text customization
from sklearn.model_selection import train_test_split # splitting the data
from sklearn.linear_model import LogisticRegression # model algorithm
from sklearn.preprocessing import StandardScaler # data normalization
# from sklearn.metrics import jaccard_similarity_score as jss # evaluation metric
from sklearn.metrics import precision_score # evaluation metric
from sklearn.metrics import classification_report # evaluation metric
from sklearn.metrics import confusion_matrix # evaluation metric
from sklearn.metrics import log_loss # evaluation metric
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics

# Starting with imports
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
import statsmodels.api as sm

data_type = {
    "customer_id": "string",
    "gender": "string",
    "senior_citizen": "string",
    "partner": "string",
    "dependents": "string",
    "tenure": "string",
    "phone_service": "string",
    "multiple_lines": "string",
    "internet_service": "string",
    "online_security": "string",
    "online_backup": "string",
    "device_protection": "string",
    "tech_support": "string",
    "streaming_service": "string",
    "streaming_movies": "string",
    "contract": "string",
    "paperless_billing": "string",
    "payment_method": "string",
    "monthly_charges": "string",
    "total_charges": "string",
    "churn": "string"
}
filepath = "data/Data_Formatted.csv"

data = pd.read_csv(filepath_or_buffer=filepath, dtype=data_type)

# Following columns have categorical data types and they need to be converted to dummy variables
dummy_variable_columns = [
                          'Churn','Area','Marital','Gender','Techie','Contract','Port_modem','Tablet',
                         'InternetService','Phone', 'Multiple','OnlineSecurity','OnlineBackup',
                          'DeviceProtection','TechSupport', 'StreamingTV','StreamingMovies',
                          'PaperlessBilling','PaymentMethod'
                         ]


dummy_data_file_index = 0

def get_dummy_data_with_output_no_drop_first(dummy_variable_columns, data):
    global dummy_data_file_index
    dummy_data = pd.get_dummies(data, prefix=dummy_variable_columns, columns=dummy_variable_columns, drop_first= False)
    dummy_data = column_name_remove_space(dummy_data)
    dummy_data.to_csv('dummy_var_data'+str(dummy_data_file_index)+'.csv', index=False)
    y = dummy_data['MonthlyCharge']
    dummy_data.drop(columns=['MonthlyCharge'], inplace=True)
    dummy_data_file_index += 1
    return y, dummy_data

def get_dummy_data_with_output(dummy_variable_columns, data):
    global dummy_data_file_index
    dummy_data = pd.get_dummies(data, prefix=dummy_variable_columns, columns=dummy_variable_columns, drop_first= True)
    dummy_data = column_name_remove_space(dummy_data)
    dummy_data.to_csv('dummy_var_data'+str(dummy_data_file_index)+'.csv', index=False)
    y = dummy_data['MonthlyCharge']
    dummy_data.drop(columns=['MonthlyCharge'], inplace=True)
    dummy_data_file_index += 1
    return y, dummy_data

# Split the training and test set 7:3
X_train, X_test, y_train, y_test = train_test_split(dummy_data, y, test_size=.3, random_state=0)
# Splitting data for random forest (dummy variable , without drop first)
X_train_, X_test_, y_train_, y_test_ = train_test_split(dummy_data_, y_, test_size=.3, random_state=0)
# Creating a function to create Random Forest Model
figsize=(8,5)

def get_rf_model(y_train,X_train, X_test):
    rf = RandomForestRegressor()
    model=rf.fit(X_train, y_train)
    for i, item in enumerate(rf.feature_importances_):
        print("{0:s}: {1:.2f}".format(X_train.columns[i], item))
    y_hat = model.predict(X_test)
    arr = np.c_[y_hat, y_test]
    print('\nPrinting predicted and actual values:\n',arr)
    print('\nPrinting Mean Squared Error:\n',(np.sqrt(mean_squared_error(y_test, y_hat))))
    print('\nR2 Score:\n',r2_score(y_test, y_hat))
    fix, ax = plt.subplots(figsize=figsize)
    g = sns.regplot(y=y_test,x=y_hat, ax = ax)
    g.set_xlabel("Predictions",fontsize=15)
    g.set_ylabel("Test",fontsize=15)
    plt.show()
    #plt.scatter(y_pred,y_test-y_pred)
    fix, ax = plt.subplots(figsize=figsize)
    g = sns.regplot(x=y_hat,y=y_test-y_hat,color="red", ax = ax)
    g.set_xlabel("Predictions",fontsize=15)
    g.set_ylabel("Residual",fontsize=15)
    plt.show()
    return model, arr

# Creating a function to create Multiple Linear Regression Model

def get_lr_model(y_train,X_train, X_test):
    model = LinearRegression()
    model.fit(X_train, y_train)
    arr = np.c_[X_train.columns.tolist(),model.coef_]
    intercept = model.intercept_
    print('\nPrinting model coefficients and intercept summary for sklearn model:\n',arr, model.intercept_)
    y_pred = model.predict(X_test)
    print('\nPrinting predicted and actual values from sklearn:\n',np.c_[y_pred, y_test])
    print('\nPrinting Mean Squared Error from sklearn:\n',(np.sqrt(mean_squared_error(y_test, y_pred))))
    print('\nR2 Score  from sklearn:\n',r2_score(y_test, y_pred))
    fix, ax = plt.subplots(figsize=figsize)
    g = sns.regplot(y=y_test,x=y_pred,color="g", ax = ax)
    g.set_xlabel("Predictions",fontsize=15)
    g.set_ylabel("Test",fontsize=15)
    plt.show()
    #plt.scatter(y_pred,y_test-y_pred)
    fix, ax = plt.subplots(figsize=figsize)
    g = sns.regplot(x=y_pred,y=y_test-y_pred,color="red", ax = ax)
    g.set_xlabel("Predictions",fontsize=15)
    g.set_ylabel("Residual",fontsize=15)
    plt.show()

    return model, arr, intercept

# Run random forect model function
model_rf, arr_sm = get_rf_model(y_train_,X_train_, X_test_);
# Run linear regression model
model_lr, arr, intercept = get_lr_model(y_train,X_train, X_test);







