import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn import metrics
from sklearn.preprocessing import MinMaxScaler
class DiabetesClassifier:
    def __init__(self) -> None:
        self.col_names = ['pregnant', 'glucose', 'bp', 'skin', 'insulin', 'bmi', 'pedigree', 'age', 'label']
        self.pima = pd.read_csv('diabetes.csv', header=0, names=self.col_names, usecols=self.col_names)
        print(self.pima.head())
        self.X_test = None
        self.y_test = None
        

    def define_feature(self):
        feature_cols = ['pregnant', 'pedigree', 'bmi', 'age']
        X = self.pima[feature_cols]
        y = self.pima.label
        return X, y
    
    def train(self, cols):
        from sklearn.model_selection import train_test_split
        #Splitting the data into dependent and independent variables
        Y1 = self.pima.label
        #selecting all labels gives the score of . The score was  lower when the range of scaling was between (0,1 ). But since this cramping of all the features into such a short range was resulting in difficulty for the model to differentiate heavily between data points .
        #x1=self.pima[['pregnant', 'glucose', 'bp', 'skin', 'insulin', 'bmi', 'pedigree', 'age']]
        
        #selecting features with higher feature importance as calculated by the bargraph . This importance decided whether the feature is playing a main role in deciding the outcome of the label . 
        #x1=self.pima[['pregnant', 'glucose', 'bp', 'skin', 'bmi']]

        #selecting features which show high correlation with the important features . We also found out that when similar features (that are displaying higher correlation) with the entire set of features were contributing to better results .        
        #x1=self.pima[['pregnant', 'glucose', 'bp', 'insulin', 'bmi']] #best score
        x1=self.pima[cols] #best score
        columns = x1.columns
        data_x = pd.DataFrame(x1, columns = columns)
        #Splitting the data into training and test
        x_train, self.X_test, y_train, self.Y_test = train_test_split(data_x, Y1, random_state = 0)
        #print(self.Y_test.shape)
        #print(self.X_test.shape)

        x_train = self.perform_min_max_scaling(x_train,5)

      #tried balancing the samples by weighing on the less frequent samples 
        # from imblearn.over_sampling import SMOTE
        # smt = SMOTE()
        # x_train, y_train = smt.fit_sample(x_train, y_train)
        

        #training with Logistic Regression 
        logreg = LogisticRegression()
        logreg.fit(x_train, y_train)
        return logreg

    def perform_min_max_scaling(self, x_train,range_lim):
        scaler = MinMaxScaler(feature_range = (0,range_lim))
        scaler.fit(x_train)
        x_train = scaler.transform(x_train)
        self.X_test = scaler.transform(self.X_test)
        return x_train

    
    
    def predict(self, cols):
      model = self.train(cols)
      y_pred_class = model.predict(self.X_test)
      return y_pred_class


    def calculate_accuracy(self, result):
        return metrics.accuracy_score(self.Y_test, result)


    def examine(self):
        dist = self.y_test.value_counts()
        print(dist)
        percent_of_ones = self.y_test.mean()
        percent_of_zeros = 1 - self.y_test.mean()
        return self.y_test.mean()
    
    def confusion_matrix(self, result):
        return metrics.confusion_matrix(self.Y_test, result)

if __name__ == "__main__":
    allc=['pregnant', 'glucose', 'bp', 'skin', 'insulin', 'bmi', 'pedigree', 'age']
    classifer = DiabetesClassifier()
    # baseline + scaling
    result = classifer.predict(['pregnant', 'pedigree', 'bmi', 'age'])
    print(f"Predicition={result}")
    score = classifer.calculate_accuracy(result)
    print(f"score={score}")
    con_matrix = classifer.confusion_matrix(result)
    print(f"confusion_matrix=${con_matrix}")
    print("\n")
    classifer = DiabetesClassifier()
    result = classifer.predict(['pregnant', 'glucose', 'bp', 'skin', 'insulin', 'bmi', 'pedigree', 'age'])
    print(f"Predicition={result}")
    score = classifer.calculate_accuracy(result)
    print(f"score={score}")
    con_matrix = classifer.confusion_matrix(result)
    print(f"confusion_matrix=${con_matrix}")
    print("\n")
    classifer = DiabetesClassifier()
    result = classifer.predict(['pregnant', 'glucose', 'bp', 'skin', 'bmi'])
    print(f"Predicition={result}")
    score = classifer.calculate_accuracy(result)
    print(f"score={score}")
    con_matrix = classifer.confusion_matrix(result)
    print(f"confusion_matrix=${con_matrix}")
    print("\n")
    classifer = DiabetesClassifier()
    result = classifer.predict(['pregnant', 'glucose', 'bp', 'bmi'])
    print(f"Predicition={result}")
    score = classifer.calculate_accuracy(result)
    print(f"score={score}")
    con_matrix = classifer.confusion_matrix(result)
    print(f"confusion_matrix=${con_matrix}")
