# Import the necessary libraries:
# - Flask: for creating the Flask web server
# - request: to access incoming request data like form data, file uploads, etc.
# - jsonify: to convert Python dictionaries or lists to a JSON response which can be returned from Flask routes
# - CORS: to handle Cross-Origin Resource Sharing, allowing  to make
# requests from one website to another website in the browser
import traceback

from flask import Flask, request, jsonify
from math import ceil
from flask_cors import CORS
import json
import pickle
import numpy as np
from sklearn.preprocessing import LabelEncoder
from datetime import datetime
import os
# Initialize the Flask application
app = Flask(__name__)
# # Allow cross-origin requests
# CORS(app)
# CORS(app, resources={r"/*": {"origins": "*"}})


# Load the XGBoost model and the label encoder upon application start
with open('Models/xg_boost_classifier.pkl', 'rb') as XG_BOOST_MODEL:
    xg_boost_classifier = pickle.load(XG_BOOST_MODEL)

with open('Models/label_encoder.pkl', 'rb') as LABEL_ENCODER:
    label_encoder = pickle.load(LABEL_ENCODER)

# Define a route for the root URL ("/") of the API
# @app.route('/')
# def home():
#     return "Growth Monitoring API is up and running!"
@app.after_request
def after_request(response):
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers', 'Referer,Accept,Origin,User-Agent,Content-Type')
    response.headers.add('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS')
    return response
# Define a route for making predictions
@app.route('/predict_growth_monitoring', methods=['POST'])
def predict():
    try:
        # Extract data from the form of the incoming request
        data = request.get_json()
        print(data)

        # Extract individual feature values from the form data
        character_leaves = int(data['character_leaves'])
        average_current_height = float(data['average_current_height'])
        no_of_branches = int(data['no_of_branches'])
        planted_date = data['planted_date']
        checked_date = data['checked_date']
        container_size = data['container_size']
        color_data = data['current_leaf_colour']
        dominant_branch = data['dominant_branch']

        # Process the current_leaf_colour to match the model's expected format
        if color_data == 'bright_yellow':
            current_leaf_colour_bright_yellow = 1
            current_leaf_colour_bright_yellow_to_lime_green = 0
            current_leaf_colour_lime_green_with_yellow_undertones = 0
            current_leaf_colour_variegated_patterns = 0
            current_leaf_colour_yellowish_green = 0
        elif color_data == 'bright_yellow_to_lime_green':
            current_leaf_colour_bright_yellow = 0
            current_leaf_colour_bright_yellow_to_lime_green = 1
            current_leaf_colour_lime_green_with_yellow_undertones = 0
            current_leaf_colour_variegated_patterns = 0
            current_leaf_colour_yellowish_green = 0
        elif color_data == 'lime_green_with_yellow_undertones':
            current_leaf_colour_bright_yellow = 0
            current_leaf_colour_bright_yellow_to_lime_green = 0
            current_leaf_colour_lime_green_with_yellow_undertones = 1
            current_leaf_colour_variegated_patterns = 0
            current_leaf_colour_yellowish_green = 0
        elif color_data == 'variegated_patterns':
            current_leaf_colour_bright_yellow = 0
            current_leaf_colour_bright_yellow_to_lime_green = 0
            current_leaf_colour_lime_green_with_yellow_undertones = 0
            current_leaf_colour_variegated_patterns = 1
            current_leaf_colour_yellowish_green = 0
        else:
            current_leaf_colour_bright_yellow = 0
            current_leaf_colour_bright_yellow_to_lime_green = 0
            current_leaf_colour_lime_green_with_yellow_undertones = 0
            current_leaf_colour_variegated_patterns = 0
            current_leaf_colour_yellowish_green = 1

        # Convert strings to datetime objects and calculate the growth duration in days
        planted_date = datetime.strptime(planted_date, '%Y-%m-%d')
        checked_date = datetime.strptime(checked_date, '%Y-%m-%d')
        growth_duration = (checked_date - planted_date).days

        # Process container size information
        if container_size == 'full_not_crowded':
            container_size_full_not_crowded = 1
        else:
            container_size_full_not_crowded = 0

        # Process dominant branch information
        if dominant_branch == 'yes':
            dominant_branch_yes = 1
        else:
            dominant_branch_yes = 0

        # Construct the input array from the extracted values
        input_array = np.array([
            character_leaves,
            average_current_height,
            no_of_branches,
            growth_duration,
            current_leaf_colour_bright_yellow,
            current_leaf_colour_bright_yellow_to_lime_green,
            current_leaf_colour_lime_green_with_yellow_undertones,
            current_leaf_colour_variegated_patterns,
            current_leaf_colour_yellowish_green,
            container_size_full_not_crowded,
            dominant_branch_yes
        ])

        # Reshape the array to the expected input shape for the model
        input_array = input_array.reshape(1, -1)

        # Make a prediction using the XGBoost model
        predicted_label = xg_boost_classifier.predict(input_array)

        # Convert the encoded label back to its string representation
        predicted_class = label_encoder.inverse_transform(predicted_label)

        # Return the prediction as a JSON response
        return jsonify({'Predicted Growth Category': predicted_class[0]})

    except Exception as e:
        # Log the error for debugging purposes (print for this example)
        print(str(e))

        # Return an error response
        return jsonify({'error': 'An error occurred during prediction.', 'details': str(e)}), 500


# Load the XGBoost model for order prediction on application start
with open('Models/xg_boost_REGRESSOR.pkl', 'rb') as XG_BOOST_MODEL:
    xgb_order_model = pickle.load(XG_BOOST_MODEL)

# Route to predict order date based on given inputs
@app.route('/predict_order_date', methods=['POST'])
def predict_order_date():
    try:
        # Extract data from the incoming request
        data = request.get_json()

        # Extract values from the data
        fertilizer_ratio = int(data['FERTILZER_RATIO'])
        growth_duration = int(data['GROWTH_DURATION'])
        media_grown = data['MEDIA_GROWN']
        current_growth_category = data['CURRENT_GROWTH_CATEGORY']
        current_pot_type = data['CURRENT_POT_TYPE']
        shade_type = data['SHADE_TYPE']

        # Process the media_grown information
        if media_grown == 'coir_cowdung':
            media_grown_coir_cowdung = 1
            media_grown_coir_cowdung_coco_chips = 0
        else:
            media_grown_coir_cowdung = 0
            media_grown_coir_cowdung_coco_chips = 1

        # Process the current_growth_category information
        if current_growth_category == 'mature_well_grown':

            current_growth_category_mature_well_grown = 1
            current_growth_category_medium_level_poorly_growing = 0
            current_growth_category_medium_level_well_growing = 0
            current_growth_category_recently_planted_poorly_growing = 0
            current_growth_category_recently_planted_well_growing = 0
            current_growth_category_small_level_poorly_growing = 0
            current_growth_category_small_level_well_growing = 0

        elif current_growth_category == 'medium_level_poorly_growing':

            current_growth_category_mature_well_grown = 0
            current_growth_category_medium_level_poorly_growing = 1
            current_growth_category_medium_level_well_growing = 0
            current_growth_category_recently_planted_poorly_growing = 0
            current_growth_category_recently_planted_well_growing = 0
            current_growth_category_small_level_poorly_growing = 0
            current_growth_category_small_level_well_growing = 0
        elif current_growth_category == 'medium_level_well_growing':

            current_growth_category_mature_well_grown = 0
            current_growth_category_medium_level_poorly_growing = 0
            current_growth_category_medium_level_well_growing = 1
            current_growth_category_recently_planted_poorly_growing = 0
            current_growth_category_recently_planted_well_growing = 0
            current_growth_category_small_level_poorly_growing = 0
            current_growth_category_small_level_well_growing = 0
        elif current_growth_category == 'recently_planted_poorly_growing':

            current_growth_category_mature_well_grown = 0
            current_growth_category_medium_level_poorly_growing = 0
            current_growth_category_medium_level_well_growing = 0
            current_growth_category_recently_planted_poorly_growing = 1
            current_growth_category_recently_planted_well_growing = 0
            current_growth_category_small_level_poorly_growing = 0
            current_growth_category_small_level_well_growing = 0
        elif current_growth_category == 'recently_planted_well_growing':
            current_growth_category_mature_well_grown = 0
            current_growth_category_mature_well_grown = 0
            current_growth_category_medium_level_poorly_growing = 0
            current_growth_category_medium_level_well_growing = 0
            current_growth_category_recently_planted_poorly_growing = 0
            current_growth_category_recently_planted_well_growing = 1
            current_growth_category_small_level_poorly_growing = 0
            current_growth_category_small_level_well_growing = 0
        elif current_growth_category == 'small_level_poorly_growing':

            current_growth_category_mature_well_grown = 0
            current_growth_category_medium_level_poorly_growing = 0
            current_growth_category_medium_level_well_growing = 0
            current_growth_category_recently_planted_poorly_growing = 0
            current_growth_category_recently_planted_well_growing = 0
            current_growth_category_small_level_poorly_growing = 1
            current_growth_category_small_level_well_growing = 0
        else :


            current_growth_category_mature_well_grown = 0
            current_growth_category_medium_level_poorly_growing = 0
            current_growth_category_medium_level_well_growing = 0
            current_growth_category_recently_planted_poorly_growing = 0
            current_growth_category_recently_planted_well_growing = 0
            current_growth_category_small_level_poorly_growing = 0
            current_growth_category_small_level_well_growing = 1


        # Process current_pot_type
        if current_pot_type == '8cm_pot':
            current_pot_type_8cm_pot = 1
            current_pot_type_hanging_pot = 0
            current_pot_type_net_pot = 0
        elif current_pot_type == 'hanging_pot':
            current_pot_type_8cm_pot = 0
            current_pot_type_hanging_pot = 1
            current_pot_type_net_pot = 0
        else:
            current_pot_type_8cm_pot = 0
            current_pot_type_hanging_pot = 0
            current_pot_type_net_pot = 1


            # Process shade_type
        if shade_type == '70_shade_net':
            shade_type_70_shade_net = 1
        else:
            shade_type_70_shade_net = 0
            # Construct the input array from the processed values
        input_array = np.array([
            fertilizer_ratio,
            growth_duration,
            media_grown_coir_cowdung,
            media_grown_coir_cowdung_coco_chips,
            current_growth_category_mature_well_grown,
            current_growth_category_medium_level_poorly_growing,
            current_growth_category_medium_level_well_growing,
            current_growth_category_recently_planted_poorly_growing,
            current_growth_category_recently_planted_well_growing,
            current_growth_category_small_level_poorly_growing,
            current_growth_category_small_level_well_growing,
            current_pot_type_8cm_pot,
            current_pot_type_hanging_pot,
            current_pot_type_net_pot,
            shade_type_70_shade_net
        ])

        # Reshape the array to the expected input shape for the model
        input_array = input_array.reshape(1, -1)

        # Make a prediction using the XGBoost model
        predicted_order_date = xgb_order_model.predict(input_array)

        # Round the prediction to the nearest higher integer
        predicted_order_date = np.ceil(predicted_order_date[0])

        # Return the prediction as a JSON response
        # Round up the predicted value to the nearest whole number

        rounded_order_date = ceil(predicted_order_date)

        return jsonify({'Predicted Order Date': str(rounded_order_date) + " days"})

    except Exception as e:
        # Log the error for debugging purposes
        return jsonify({
            "error": "An error occurred during prediction.",
            "details": str(e),
            "trace": traceback.format_exc()  # Import traceback at the beginning of your file
        })

# Run the Flask app

if __name__ == '__main__':
 app.run(host='0.0.0.0', port=os.environ.get('PORT', 5000))

