from flask import Flask, render_template, request, redirect, url_for
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import joblib 
from sklearn.preprocessing import MinMaxScaler
from sklearn.neighbors import LocalOutlierFactor
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
import os
from sklearn.metrics import mean_squared_error, mean_absolute_percentage_error, r2_score, mean_absolute_error

app = Flask(__name__)

history_data = pd.read_csv('./datasets/HistoricalCardano.csv')
history_data = history_data.reindex(index=history_data.index[::-1])
history_data = history_data.reset_index(drop=True)

history_data['Tanggal'] = pd.to_datetime(history_data['Tanggal'], dayfirst=True)
history_data['Perubahan%'] = history_data['Perubahan%'].str.replace('%', '').str.replace(',', '.').astype(float)
history_data['Perubahan%'] = history_data['Perubahan%'].astype(float)
history_data['Vol.'] = history_data['Vol.'].str.replace('M', 'e6').str.replace('B', 'e9').str.replace(',', '.').astype(float)
history_data['Terakhir'] = history_data['Terakhir'].str.replace(',', '.').astype(float)
history_data['Pembukaan'] = history_data['Pembukaan'].str.replace(',', '.').astype(float)
history_data['Tertinggi'] = history_data['Tertinggi'].str.replace(',', '.').astype(float)
history_data['Terendah'] = history_data['Terendah'].str.replace(',', '.').astype(float)

history_data = history_data.set_index('Tanggal')

# Calculate 30-day moving average
history_data['MA30'] = history_data['Terakhir'].rolling(window=30).mean()

plt.figure(figsize=(10, 6))
plt.plot(history_data['Pembukaan'], label='Harga Pembukaan')
plt.plot(history_data['Terakhir'], label='Harga Terakhir')
plt.plot(history_data['MA30'], label='MA 30', linestyle='--', color='red')
plt.xlabel('Tanggal')
plt.ylabel('Harga')
plt.title('Pergerakan Harga Pembukaan dan Terakhir dengan MA 30')
plt.legend()

plot_ma_a = os.path.join('static', 'ma_a.png')
plt.savefig(plot_ma_a)
plt.close()

# Calculate 30-day moving average
history_data['MA30'] = history_data['Terakhir'].rolling(window=30).mean()

plt.figure(figsize=(10, 6))
plt.plot(history_data['Tertinggi'], label='Harga Tertinggi')
plt.plot(history_data['Terendah'], label='Harga Terendah')
plt.plot(history_data['MA30'], label='MA 30', linestyle='--', color='red')
plt.xlabel('Tanggal')
plt.ylabel('Harga')
plt.title('Pergerakan Harga Tertinggi dan Terendah dengan MA 30')
plt.legend()

plot_ma_b = os.path.join('static', 'ma_b.png')
plt.savefig(plot_ma_b)
plt.close()

history_data = history_data.drop(columns=['MA30'])

def create_lagged_features(data, lags=3):
    lagged_data = data.copy()
    for lag in range(1, lags + 1):
        lagged_data[[f"{col}_lag{lag}" for col in data.columns]] = data.shift(lag)
    lagged_data.dropna(inplace=True)
    return lagged_data

lags = 30 * 24

# Load the model
model = joblib.load('./models/random_forest_model.pkl')
lagged_data = create_lagged_features(history_data.drop(['Vol.', 'Perubahan%'], axis=1), lags)

X = lagged_data.drop(columns=['Pembukaan', 'Terakhir', 'Tertinggi', 'Terendah'])
y = lagged_data["Pembukaan"]

def multistep_forecast(model, data, n_steps):
  forecast = []
  last_observation = data.iloc[-1].values.reshape(1, -1)
  
  for _ in range(n_steps):
    next_step = model.predict(last_observation)
    forecast.append(next_step[0])
    
    # Update the last observation with the new prediction
    last_observation = np.roll(last_observation, -1)
    last_observation[0, -1] = next_step[0]
  
  return forecast

@app.route('/')
def index():
    table_html = history_data.to_html(classes='table table-striped', index=True)

    return render_template('index.html', table_html=table_html, plot_ma_a=plot_ma_a, plot_ma_b=plot_ma_b)

@app.route('/predict', methods=['GET', 'POST'])
def predict():
  n_steps = 0
  
  if request.method == 'POST':
    if request.form['waktu'] == '1 bulan':
      n_steps = 30
    elif request.form['waktu'] == '3 bulan':
      n_steps = 30 * 3
    elif request.form['waktu'] == '6 bulan':
      n_steps = 30 * 6
    elif request.form['waktu'] == '1 tahun':
      n_steps = 30 * 12
    elif request.form['waktu'] == '2 tahun':
      n_steps = 30 * 24

    # Perform the forecast
    forecasted_values = multistep_forecast(model, X, n_steps)

    # Combine past and forecasted values
    combined_values = np.concatenate([y.values, forecasted_values])

    # Create a time index for the combined values
    time_index = pd.date_range(start=y.index[0], periods=len(combined_values), freq='D')

    plt.figure(figsize=(12, 6))
    plt.plot(history_data.index, history_data['Pembukaan'], label="Past Data", linestyle="-", color="blue")
    plt.plot(time_index[len(y):], forecasted_values, label="Forecasted Values", linestyle="-", color="green")
    plt.title("All Past Data and Forecasted Future Values")
    plt.xlabel("Date")
    plt.ylabel("Values")
    plt.legend()
    plt.grid()

    result_img = os.path.join('static', 'result.png')
    plt.savefig(result_img)
    plt.close()

    forecasted_df = pd.DataFrame({
      'Tanggal': time_index[len(y):],
      'Forecasted_Pembukaan': forecasted_values
    })

    forecasted_df.to_csv('./datasets/forecasted_values.csv', index=False)

    return render_template('predict.html', result_img=result_img, forecasted_table=forecasted_df.to_html(classes='table table-striped', index=False))
  else:
    return redirect(url_for('index'))

if __name__ == '__main__':
    app.run(debug=True)