

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression # for model
from sklearn.preprocessing import MinMaxScaler #sklearn better for regression, statsmodels better for time series 
import statsmodels.api as sm
from flask import Flask, render_template, request # webb app
import warnings

warnings.filterwarnings('ignore')

app = Flask(__name__)

print("models under construction")


 # build clone of modles for dashboard (not pullling models from testing)

# ==========================================
# load & train lcoal model (Linear Regression)
# ==========================================
df_local = pd.read_excel("delta_coffee_model_data~v1.xlsx", sheet_name=0)

# grab only the columns we need
df_local = df_local[['date.y', 'Median Price', 'milk', 'sugar', 'coco']]

# drop all  missing data
df_local = df_local.dropna()

# Calculate Deltas
df_local_delta = df_local.copy()
df_local_delta['Delta_Milk'] = df_local_delta['milk'].diff()
df_local_delta['Delta_Sugar'] = df_local_delta['sugar'].diff()
df_local_delta['Delta_Cocoa'] = df_local_delta['coco'].diff()
df_local_delta['Delta_Coffee'] = df_local_delta['Median Price'].diff()

# Drop the single NaN row created by the .diff() function
df_local_delta = df_local_delta.dropna()

# Train on 100% of data for production
X_local = df_local_delta[['Delta_Milk', 'Delta_Sugar', 'Delta_Cocoa']]
y_local = df_local_delta[['Delta_Coffee']]


##### scale using minmax: which means the highest price of sugar is a 1, and lowest is a 0. then every other price gets % inside
### where i found how to use minmaxscaler(): https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html 
scaler_X = MinMaxScaler()
scaler_y = MinMaxScaler()
X_scaled = scaler_X.fit_transform(X_local)
y_scaled = scaler_y.fit_transform(y_local)

#print(pd.DataFrame(X_scaled, columns=['Delta_Milk', 'Delta_Sugar', 'Delta_Cocoa'])) # print to veridy scaled correctly
# lm_model.coef_ # show coefs


lm_model = LinearRegression()
lm_model.fit(X_scaled, y_scaled) # learning historical data, so when user imput comes, model can explain
print("LM Micro model listo")

# Grab baseline data for dashboard
local_hist_dates = df_local['date.y'].astype(str).tolist()
local_hist_prices = df_local['Median Price'].tolist()
recent_local_price = local_hist_prices[-1]
recent_milk = df_local['milk'].iloc[-1] #grab last row in the data frame 
recent_sugar = df_local['sugar'].iloc[-1]
recent_cocoa = df_local['coco'].iloc[-1]

# ==========================================
# load and train (arima)
# ==========================================
df_global = pd.read_csv("master~global.csv").dropna()
df_global.columns = df_global.columns.str.strip()
df_global['Global_Arabica_Price'] = df_global['Global_Arabica_Price'] / 100 # Cents to Dollars

# Calculate Deltas
df_global_delta = df_global.copy()
df_global_delta['Delta_Sugar'] = df_global_delta['Global_Sugar_Price'].diff()
df_global_delta['Delta_Cocoa'] = df_global_delta['Global_Cocoa_Price'].diff()
df_global_delta['Delta_Arabica'] = df_global_delta['Global_Arabica_Price'].diff()
df_global_delta = df_global_delta.dropna()

X_global = df_global_delta[['Delta_Sugar', 'Delta_Cocoa']]
y_global = df_global_delta['Delta_Arabica']

# didnt scale arima data, because arima captures real-world price behavior. 

# arimax_model.params # show arima coefs

# Train arima on all data
arimax_model = sm.tsa.ARIMA(endog=y_global, exog=X_global, order=(1, 0, 0)).fit()#(1,0,0) only looking at prev 1 month
print("Global Mac listo")

global_hist_dates = df_global['observation_date'].astype(str).tolist()
global_hist_prices = df_global['Global_Arabica_Price'].tolist()
recent_global_price = global_hist_prices[-1]
recent_global_sugar = df_global['Global_Sugar_Price'].iloc[-1]
recent_global_cocoa = df_global['Global_Cocoa_Price'].iloc[-1]


# ==========================================
# web route, how live.html and app.py talk to eachother
# ==========================================
@app.route('/', methods=['GET', 'POST'])
def index():
    
    scroll_to = None # code from Dr.Mcvey
    # Set defaults for sliders
    milk_pct, local_sugar_pct, local_cocoa_pct = 0, 0, 0
    global_sugar_pct, global_cocoa_pct = 0, 0
    local_projections, global_projections = None, None
    
    if request.method == 'POST':
        # Grab from LOCAL sliders
        scroll_to = 'target-section' # code from Dr.Mcvey
        milk_pct = float(request.form.get('milk_shock', 0))
        local_sugar_pct = float(request.form.get('local_sugar_shock', 0))
        local_cocoa_pct = float(request.form.get('local_cocoa_shock', 0))
        
        # Grab from GLOBAL sliders
        global_sugar_pct = float(request.form.get('global_sugar_shock', 0))
        global_cocoa_pct = float(request.form.get('global_cocoa_shock', 0))
        
        # local predict
        local_milk_delta = recent_milk * (milk_pct / 100)
        local_sugar_delta = recent_sugar * (local_sugar_pct / 100)
        local_cocoa_delta = recent_cocoa * (local_cocoa_pct / 100)
        
        user_input_scaled = scaler_X.transform([[local_milk_delta, local_sugar_delta, local_cocoa_delta]])
        scaled_prediction = lm_model.predict(user_input_scaled)
        local_pred_change = scaler_y.inverse_transform(scaled_prediction)[0][0] #inverse_transformed is used to unscales and transforms to real usd
        
        # 3 month functions
        p3, p2, p1 = local_hist_prices[-3], local_hist_prices[-2], local_hist_prices[-1]
        pred_1 = np.median([p3, p2, p1]) + local_pred_change # median smoothing instead of true projecting ( 3 points)
        pred_2 = np.median([p2, p1, pred_1]) + local_pred_change
        pred_3 = np.median([p1, pred_1, pred_2]) + local_pred_change
        local_projections = [pred_1, pred_2, pred_3]

        # global predict
        global_sugar_delta = recent_global_sugar * (global_sugar_pct / 100)
        global_cocoa_delta = recent_global_cocoa * (global_cocoa_pct / 100)
        
        # Build exog data for future 3 points
        exog_future = pd.DataFrame({
            'Delta_Sugar': [global_sugar_delta, global_sugar_delta, global_sugar_delta],
            'Delta_Cocoa': [global_cocoa_delta, global_cocoa_delta, global_cocoa_delta]
        })
        
        # Forecast 3 steps out
        forecast = arimax_model.get_forecast(steps=3, exog=exog_future).predicted_mean.values
        # Add changes to the base price
        global_projections = [
            recent_global_price + forecast[0],
            recent_global_price + forecast[0] + forecast[1],
            recent_global_price + forecast[0] + forecast[1] + forecast[2]
        ]
        
   # get coeffs for Local Model
    coef_milk, coef_sugar, coef_cocoa = lm_model.coef_[0]

# going to pass the recent march 2026 data points to live.html front end so user knows what they are shocking...

    # get Coefficients for global
    # g the multipliers for the exog variables
    #g_coef_sugar = arimax_model.params['Delta_Sugar']
    #g_coef_cocoa = arimax_model.params['Delta_Cocoa']

    return render_template('live.html', 
                           scroll=scroll_to, # scroll method from Dr.Mcvey
                           milk_pct=milk_pct, local_sugar_pct=local_sugar_pct, local_cocoa_pct=local_cocoa_pct,
                           global_sugar_pct=global_sugar_pct, global_cocoa_pct=global_cocoa_pct,
                           local_projections=local_projections, local_dates=local_hist_dates, local_prices=local_hist_prices,
                           global_projections=global_projections, global_dates=global_hist_dates, global_prices=global_hist_prices,
                           recent_milk=recent_milk, recent_sugar=recent_sugar, recent_cocoa=recent_cocoa,
                           recent_global_sugar=recent_global_sugar, recent_global_cocoa=recent_global_cocoa,
                           coef_milk=coef_milk, coef_sugar=coef_sugar, coef_cocoa=coef_cocoa,
                           g_coef_sugar=g_coef_sugar, g_coef_cocoa=g_coef_cocoa)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=3923, debug=True) #5029 for local, 3923 for compsci
      
    
    
    
    

    