from datetime import datetime
from django.shortcuts import render, redirect, reverse
from django.template import loader
from django.http import HttpResponse
from sklearn.tree import DecisionTreeClassifier

from User.forms import MyForm,MyForm2,MyForm3,MyForm4,MyForm5
from django.contrib.auth import authenticate, login
from User import models as Umodels
from django.http import HttpResponseRedirect
from django.contrib import messages
import json

# -------------------   EF
import pandas as pd
import numpy as np
import math
import sklearn
import matplotlib.pyplot as plt
from datetime import datetime
from sklearn import metrics
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
# -------------------   EF

# Demand Forecast
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.arima.model import ARIMA
from pandas.tseries.offsets import DateOffset

import warnings
warnings.filterwarnings("ignore")

# Start  CompanyHome
def Homepage(request):
    return render(request, 'Admin/Homepage.html');
# End  CompanyHome

# Employee_Efficiency
def Employee_Efficiency(request):
    if request.method == 'POST':
        myForm = MyForm5(request.POST)
        if myForm.is_valid():
            workid = myForm.cleaned_data['customerid']
            DateSet = pd.read_csv("Data/WorkHistory.csv", skipinitialspace=True)

            DateSet['JobDone'].replace({'Engine Repairering': 1, 'Painting': 2, 'Oil Changing': 3,
                                        'Interior Cleaning': 4, 'Body Wash': 5, 'Under Wash': 6}, inplace=True)
            DateSet = DateSet[(DateSet.WorkQuality > 1)]  # search for job need to be done
            DateSet = DateSet.drop(columns=['WorkQuality'])
            x = DateSet[['JobDone', 'TakenTime']]
            y = DateSet[['StaffID']]
            grouped_df = DateSet[(DateSet["JobDone"] == workid)]  # get selected work
            grouped_df = grouped_df.groupby("StaffID")  # group job staff
            grouped_df = grouped_df['TakenTime']  # get only taken time to complete work
            mean_df = grouped_df.mean()  # avarage time to complete work
            min_df = mean_df.min()  # get less time taken to complete work

            # x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=2)
            # lm = LinearRegression()
            # lm.fit(x_train, y_train)
            #
            # new_input = [[workid, min_df]]  # Best WorkQuality Work
            # pred = lm.predict(new_input)
            # workid = (int(pred.round())) # final employee ID by ML
            #
            # print("--------------Accuracy-----------------")
            # accuracy = lm.score(x_test, y_test)
            # print(accuracy)

            X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=2)

            clf = DecisionTreeClassifier()
            clf = clf.fit(X_train, y_train)
            y_pred = clf.predict(X_test)

            new_input = [[workid, min_df]]  # Best WorkQuality Work
            pred = clf.predict(new_input)
            workid = (int(pred.round()))  # final employee ID by ML

            print("Accuracy:", metrics.accuracy_score(y_test, y_pred))

            DateSetLoad = pd.read_csv("Data/WorkHistory.csv", skipinitialspace=True)

            data2 = pd.read_csv('Data/EmployeeStatus.csv')

            # using merge function by setting how='inner'
            output1 = pd.merge(DateSetLoad, data2,
                               on='StaffID',
                               how='inner')

            DateSetResult = DateSetLoad[(output1.StaffID == workid) & (output1.Availability == "Yes")]

            df = DateSetResult[:1]
            # data = data.to_html()

            # -----------------------------------------------------------------------  aaAccuracy section

            # -----------------------------------------------------------------------  aaAccuracy section
            json_records = df.reset_index().to_json(orient='records')
            arr = []
            arr = json.loads(json_records)
            if (arr == [] ):
                DateSetResult = DateSetLoad[(output1.Availability == "Yes")]
                df = DateSetResult[:1]
                # data = data.to_html()
                json_records = df.reset_index().to_json(orient='records')
                arr = []
                arr = json.loads(json_records)

            else:
                a = 2

            form = MyForm5()
            context = { 'form': form, 'd': arr}
            return render(request, 'Admin/Employee_Efficiency.html', context)

    else:
        form = MyForm5()
    return render(request, 'Admin/Employee_Efficiency.html', {'form': form});


def Employee_Data(request):
    data1 = pd.read_csv('Data/WorkHistory.csv')
    data2 = pd.read_csv('Data/EmployeeStatus.csv')
    DateSet = pd.merge(data1, data2,  on='StaffID',   how='inner')
    grouped_df = DateSet.groupby("StaffID" )  # group job staff
    finalpt = grouped_df.head(10) # date from two datasets
    json_records = finalpt.reset_index().to_json(orient='records')
    arr = []
    arr = json.loads(json_records)
    context = {'d': arr}
    return render(request, 'Admin/Employee_Data.html',context);

def EmployeeStatus_Update(request):
    if request.method == 'POST':
        myForm = MyForm3(request.POST)
        if myForm.is_valid():
            StaffID = myForm.cleaned_data['StaffID']
            Availability = myForm.cleaned_data['Availability']
            DateSet = pd.read_csv("Data/EmployeeStatus.csv")
            StaffID = (int(StaffID) - 1)
            DateSet.at[StaffID,'Availability']= Availability
            DateSet.to_csv("Data/EmployeeStatus.csv", index=False)
            messages.success(request, 'Employee status successfully! Updated.')
            return HttpResponseRedirect(request.path_info)
        else:
            form = MyForm3()
            return render(request, 'Admin/EmployeeStatus_Update.html', {'form':form});

    else:
        form = MyForm3()
    return render(request, 'Admin/EmployeeStatus_Update.html', {'form':form});

# Demand Forecasting History
def PurchaseHistory(request):
    data = pd.read_csv('Data/Purchasefile.csv')
    finalpt = data.head(121)
    json_records = finalpt.reset_index().to_json(orient='records')
    arr = []
    arr = json.loads(json_records)
    context = {'d': arr}
    return render(request, 'Admin/PurchaseHistory.html',context);

# start Demand Forecasting Machine Learning Model
def Forecasting(request):
     if request.method == 'POST':
        myForm = MyForm4(request.POST)
        if myForm.is_valid():
            Productid = myForm.cleaned_data['Productid']
            inputdate = myForm.cleaned_data['inputdate']


            ProductName = "CALTEX Delo Gold Ultra"
            if (ProductName == "CALTEX Delo Gold Ultra"):  # load first product budget
                df = pd.read_csv('Data/Purchasefile.csv')
                df.head()

                df.columns = ["Month", "CALTEX Delo Gold Ultra", "Price1"]
                rrr = df.head()

                # Convert Month into Datetime
                df['Month'] = pd.to_datetime(df['Month'])
                df.set_index('Month', inplace=True)
                df.describe()

                adfuller(df['CALTEX Delo Gold Ultra'])
                test_result2 = adfuller(df['Price1'])

                def adfuller_test(Product1):
                    result = adfuller(Product1)
                    labels = ['ADF Test Statistic', 'p-value', '#Lags Used', 'Number of Observations Used']
                    for value, label in zip(result, labels):
                        print(label + ' : ' + str(value))

                def adfuller_test2(Price1):
                    result2 = adfuller(Price1)
                adfuller_test(df['CALTEX Delo Gold Ultra'])
                adfuller_test2(df['Price1'])
                ##Differencing
                df['Product1 First Difference'] = df['CALTEX Delo Gold Ultra'] - df['CALTEX Delo Gold Ultra'].shift(1)
                df['Product1 First Difference2'] = df['Price1'] - df['Price1'].shift(1)
                #  df['Sales'].shift(1)
                df['Seasonal First Difference'] = df['CALTEX Delo Gold Ultra'] - df['CALTEX Delo Gold Ultra'].shift(12)
                df['Seasonal First Difference2'] = df['Price1'] - df['Price1'].shift(12)
                # df.head(14)

                ## Again test dickey fuller test
                adfuller_test(df['Seasonal First Difference'].dropna())
                adfuller_test2(df['Seasonal First Difference2'].dropna())

                # ARIMA
                model = ARIMA(df['CALTEX Delo Gold Ultra'], order=(1, 0, 0))
                model2 = ARIMA(df['Price1'], order=(1, 0, 0))
                model_fit = model.fit()
                model_fit2 = model2.fit()
                # model_fit.summary()
                df['forecast'] = model_fit.predict(start=104, end=120, dynamic=True)
                df['forecastPrice'] = model_fit2.predict(start=104, end=120, dynamic=True)
                # df[['Product1','forecast']].plot(figsize=(12,8))
                model = sm.tsa.statespace.SARIMAX(df['CALTEX Delo Gold Ultra'], order=(1, 1, 1),
                                                  seasonal_order=(1, 1, 1, 12))
                model2 = sm.tsa.statespace.SARIMAX(df['Price1'], order=(1, 1, 1), seasonal_order=(1, 1, 1, 12))

                results = model.fit()
                results2 = model2.fit()

                future_dates = [df.index[-1] + DateOffset(months=x) for x in range(0, 150)]
                future_datest_df = pd.DataFrame(index=future_dates[1:], columns=df.columns)
                # future_datest_df.tail()
                future_df = pd.concat([df, future_datest_df])


                inputdatex = inputdate
                inputdate = datetime.strftime(inputdatex, "%m/%d/%Y")

                # 10/01/2025

                lastDate = '10/01/2021'

                inputdate = inputdate
                date_format = "%m/%d/%Y"
                a = datetime.strptime(lastDate, date_format)  # user input date
                b = datetime.strptime(inputdate, date_format)
                delta = b - a
                delta2 = delta.days
                # print(delta2)
                forcasting_date = int(delta2 / 30)
                newDate = forcasting_date + 121  # ending number

                #   print(forcasting_date)
                forecast = future_df['forecast'] = results.predict(start=119, end=newDate, dynamic=True)
                #    future_df[['Sales', 'forecast']].plot(figsize=(12, 8))

                forecastPrice = future_df['forecastPrice'] = results2.predict(start=119, end=newDate, dynamic=True)
                #   future_df[['Price1', 'forecastPrice']].plot(figsize=(12, 8))

                df3 = forecast[-1]
                df4 = forecastPrice[-1]

                PredictedDemand = int(df3)
                PredictedPrice = int(df4)
                PredictedBudget = PredictedDemand * PredictedPrice


                context = { 'arz': PredictedDemand , 'arz2': PredictedPrice , 'arz3': PredictedBudget , 'datagot': inputdate }
                template = loader.get_template('Admin/Result.html')
                return HttpResponse(template.render(context, request))
     else:
         form = MyForm4()
     #returning form
     return render(request, 'Admin/Forecasting.html', {'form':form});
# End Demand Forecasting Machine Learning Model


def AdminLogin(request):
    if request.method == 'POST':
        myForm = MyForm2(request.POST)
        if myForm.is_valid():
            UserName = myForm.cleaned_data['UserName']
            Password = myForm.cleaned_data['Password']
            gotdata = Umodels.loginDataAdmin.objects.all().filter(UserName=UserName , Password=Password).count()
            if gotdata > 0:
                return render(request, 'Admin/AdminHome.html');
            else:
                messages.success(request, 'Login Info Not Found  , Please Check Your UserName and Password')
                return HttpResponseRedirect(request.path_info)
    else:
        form = MyForm2()
    return render(request, 'Admin/AdminLogin.html', {'form':form});

# Customer Data
def Customer_Data(request):
    data = pd.read_csv('Data/CustomerDataset.csv')
    finalpt = data.head(500)
    json_records = finalpt.reset_index().to_json(orient='records')
    arr = []
    arr = json.loads(json_records)
    context = {'d': arr}
    return render(request, 'Admin/Customer_Data.html',context);

# Customer Frequency
def Customer_Frequency(request):
    if request.method == 'POST':
        myForm = MyForm(request.POST)
        if myForm.is_valid():
            # Loading the data
            df = pd.read_csv('Data/CustomerDatasetNew_4.csv')

            # Drop the missing data in dataframe
            df_data = df.dropna()

            # Convert the date field, InvoiceDate to datetime object
            df_data.InvoiceDate = pd.to_datetime(df_data.InvoiceDate)

            ctm_bhvr_dt = df_data[(df_data.InvoiceDate < pd.Timestamp(2021, 12, 1))  # dataset End date
                                  & (df_data.InvoiceDate >= pd.Timestamp(2021, 5, 1))].reset_index(
                drop=True)  # dataset start date

            ctm_next_quarter = df_data[(df_data.InvoiceDate < pd.Timestamp(2022, 3, 1))  # predict date Till
                                       & (df_data.InvoiceDate >= pd.Timestamp(2021, 12, 1))].reset_index(
                drop=True)  # dataset End date

            # Get the distinct customers in the dataframe ctm_bhvr_dt
            ctm_dt = pd.DataFrame(ctm_bhvr_dt['CustomerID'].unique())

            # Rename the column to CustomerID.
            ctm_dt.columns = ['CustomerID']

            # Create a dataframe with CustomerID and customers first purchase
            ctm_1st_purchase_in_next_quarter = ctm_next_quarter.groupby('CustomerID').InvoiceDate.min().reset_index()
            ctm_1st_purchase_in_next_quarter.columns = ['CustomerID', 'MinPurchaseDate']

            # Create a dataframe with CustomerID and customers last purchase
            ctm_last_purchase_bhvr_dt = ctm_bhvr_dt.groupby('CustomerID').InvoiceDate.max().reset_index()
            ctm_last_purchase_bhvr_dt.columns = ['CustomerID', 'MaxPurchaseDate']

            # Merge two dataframes
            ctm_purchase_dates = pd.merge(ctm_last_purchase_bhvr_dt, ctm_1st_purchase_in_next_quarter, on='CustomerID',
                                          how='left')

            # Get the difference in days from MinPurchaseDate and MaxPurchaseDate for each customer
            ctm_purchase_dates['NextPurchaseDay'] = (
                    ctm_purchase_dates['MinPurchaseDate'] - ctm_purchase_dates['MaxPurchaseDate']).dt.days

            # Update the dataframe ctm_dt by merging it with the NextPurchaseDay column of the dataframe ctm_purchase_dates
            ctm_dt = pd.merge(ctm_dt, ctm_purchase_dates[['CustomerID', 'NextPurchaseDay']], on='CustomerID',
                              how='left')
            # Fill all missing values in the dataset ctm_dt with the number 9999
            ctm_dt = ctm_dt.fillna('Will not return')

            # Feature Engineering
            # Recency
            # Get the maximum purchase date of each customer and create a dataframe with it together with the customer's id.
            ctm_max_purchase = ctm_bhvr_dt.groupby('CustomerID').InvoiceDate.max().reset_index()
            ctm_max_purchase.columns = ['CustomerID', 'MaxPurchaseDate']

            # Find the recency of each customer in days
            ctm_max_purchase['Recency'] = (
                    ctm_max_purchase['MaxPurchaseDate'].max() - ctm_max_purchase['MaxPurchaseDate']).dt.days

            # Find the recency in days
            ctm_max_purchase['Recency'] = (
                    ctm_max_purchase['MaxPurchaseDate'].max() - ctm_max_purchase['MaxPurchaseDate']).dt.days

            # Merge the dataframes ctm_dt and ctm_max_purchase[['CustomerID', 'Recency']] on the CustomerID column.
            ctm_dt = pd.merge(ctm_dt, ctm_max_purchase[['CustomerID', 'Recency']], on='CustomerID')
            Recency = ctm_dt.head()

            # Frequency
            # Get order counts for each user and create a dataframe with it
            ctm_frequency = df_data.groupby('CustomerID').InvoiceDate.count().reset_index()
            ctm_frequency.columns = ['CustomerID', 'Frequency']

            # Update the dataframe ctm_dt by merging it with the dataframe ctm_frequency
            ctm_dt = pd.merge(ctm_dt, ctm_frequency, on='CustomerID')
            Frequency = ctm_dt.head()
            print(Frequency)
            df_data['Revenue'] = df_data.ServicePrice

            # df_data['Revenue'] = df_data.UnitPrice * df_data.Quantity
            # Get the revenue from each customer and sum them.
            ctm_revenue = df_data.groupby('CustomerID').Revenue.sum() / df_data.groupby(
                'CustomerID').InvoiceDate.count()
            totalALlcustomervalue = ctm_revenue.sum()
            singlecustoemrvalue = ctm_revenue

            # ML Section Start
            pntge = (singlecustoemrvalue / totalALlcustomervalue) * 100
            sss = pd.DataFrame(pntge, columns=['persontageImpact'])
            xxx = sss.head()
            print(xxx)
            ctm_dt = pd.merge(ctm_dt, sss, on='CustomerID')
            Frequency = ctm_dt.head()
            df2 = pd.read_csv('Data/CustomerDatasetNew_4.csv')
            ctm_dt = pd.merge(ctm_dt, df2, on='CustomerID')

            df0 = pd.read_csv('Data/CustomerDatasetNew_4.csv')
            df0 = df0.groupby('CustomerID')[
                'ServicePrice', 'ServiceQualityRating', 'ResponseTimeRating', 'CustomerServiceRating'].sum()
            df0 = pd.merge(df0, Frequency, on='CustomerID')
            print(df0)
            x = df0[['ServicePrice', 'ServiceQualityRating', 'ResponseTimeRating', 'CustomerServiceRating']]
            y = df0[['Frequency']]
            # split dataset for train and test
            x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=2)
            # user LinearRegression

            from sklearn.linear_model import LinearRegression
            lm = LinearRegression()
            lm.fit(x_train, y_train)

            customerid = myForm.cleaned_data['customerid']
            dfz = ctm_dt[(ctm_dt["CustomerID"] == customerid)]
            Frequency = dfz.head(1)
            print(Frequency)
            df = Frequency
            json_records = df.reset_index().to_json(orient='records')
            arr = json.loads(json_records)
            form = MyForm()
            context = {'form': form, 'd': arr}
            return render(request, 'Admin/Customer_Frequency.html', context)

    else:
        form = MyForm()
    return render(request, 'Admin/Customer_Frequency.html', {'form': form});

def AdminHome(request):
    return render(request,'Admin/AdminHome.html')




