import os
import requests
from decouple import config
from flask import Flask, request, jsonify

app = Flask(__name__)


# Read WHATSAPP_TOKEN from the .env file with a default value
whatsapp_token= config("WHATSAPP_TOKEN", default="default_whatsapp_token", cast=str)
# Read VERIFY_TOKEN from the .env file with a default value
verify_token = config("VERIFY_TOKEN", default="default_verify_token", cast=str)
# Message log dictionary to enable conversation over multiple messages
message_log_dict = {}

# Set the homepage endpoint and a welcome message
@app.route("/", methods=["GET"])
def home():
    return "WhatsApp BOT Webhook is listening!"

# create a message log for each phone number and return the current message log
def update_message_log(message, phone_number, role):
    initial_log = {
        "role": "system",
        "content": "You are a helpful assistant named WhatsBot.",
    }
    if phone_number not in message_log_dict:
        message_log_dict[phone_number] = [initial_log]
    message_log = {"role": role, "content": message}
    message_log_dict[phone_number].append(message_log)
    return message_log_dict[phone_number]

# make  
def define_response(message, from_number):
    try:
        message_log = update_message_log(message, from_number, "user")
        if message == 1:
            response_message = "Welcome Back"
        if message == 2:
            response_message = "Salam"
        print(f"response: {response_message}")
        update_message_log(response_message, from_number, "assistant")
    except Exception as e:
        print(f"error: {e}")
        response_message = "Sorry, the API is currently overloaded or offline. Please try again later."
        remove_last_message_from_log(from_number)
    return response_message

# remove last message from log if request fails
def remove_last_message_from_log(phone_number):
    message_log_dict[phone_number].pop()

# send the response as a WhatsApp message back to the user
def send_whatsapp_message(body, message):
    value = body["entry"][0]["changes"][0]["value"]
    phone_number_id = value["metadata"]["phone_number_id"]
    from_number = value["messages"][0]["from"]
    headers = {
        "Authorization": f"Bearer {whatsapp_token}",
        "Content-Type": "application/json",
    }
    url = "https://graph.facebook.com/v15.0/" + phone_number_id + "/messages"
    data = {
        "messaging_product": "whatsapp",
        "to": from_number,
        "type": "text",
        "text": {"body": message},
    }
    response = requests.post(url, json=data, headers=headers)
    print(f"whatsapp message response: {response.json()}")
    response.raise_for_status()

# handle WhatsApp messages of different type
def handle_whatsapp_message(body):
    message = body["entry"][0]["changes"][0]["value"]["messages"][0]
    if message["type"] == "text":
        message_body = message["text"]["body"]
    elif message["type"] == "audio":
        audio_id = message["audio"]["id"]
        # message_body = handle_audio_message(audio_id)
    # response = make_openai_request(message_body, message["from"])
    response = define_response(message_body, message["from"])
    send_whatsapp_message(body, response)


# handle incoming webhook messages
def handle_message(request):
    # Parse Request body in json format
    body = request.get_json()
    print(f"request body: {body}")

    try:
        # info on WhatsApp text message payload:
        # https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/payload-examples#text-messages
        if body.get("object"):
            if (
                body.get("entry")
                and body["entry"][0].get("changes")
                and body["entry"][0]["changes"][0].get("value")
                and body["entry"][0]["changes"][0]["value"].get("messages")
                and body["entry"][0]["changes"][0]["value"]["messages"][0]
            ):
                handle_whatsapp_message(body)
            return jsonify({"status": "ok"}), 200
        else:
            # if the request is not a WhatsApp API event, return an error
            return (
                jsonify({"status": "error", "message": "Not a WhatsApp API event"}),
                404,
            )
    # catch all other errors and return an internal server error
    except Exception as e:
        print(f"unknown error: {e}")
        return jsonify({"status": "error", "message": str(e)}), 500
    
    
def verify(request):
    # Parse params from the webhook verification request
    mode = request.args.get("hub.mode")
    token = request.args.get("hub.verify_token")
    challenge = request.args.get("hub.challenge")
    # Check if a token and mode were sent
    if mode and token:
        # Check the mode and token sent are correct
        if mode == "subscribe" and token == verify_token:
            # Respond with 200 OK and challenge token from the request
            print("WEBHOOK_VERIFIED")
            return challenge, 200
        else:
            # Responds with '403 Forbidden' if verify tokens do not match
            print("VERIFICATION_FAILED")
            return jsonify({"status": "error", "message": "Verification failed"}), 403
    else:
        # Responds with '400 Bad Request' if verify tokens do not match
        print("MISSING_PARAMETER")
        return jsonify({"status": "error", "message": "Missing parameters"}), 400
    
# Accept POST requests at the /webhook endpoint
@app.route("/webhook", methods=["POST", "GET"])
def webhook():
    if request.method == "GET": 
        return verify(request)
    # Handle the incoming POST request here
    if request.method == "POST":
        # Get the JSON data from the request
        data = request.get_json()
        
        # Process the data and perform actions based on the WhatsApp bot's functionality
        response = process_data(data)
        
        # Return a response to the sender
        return jsonify(response)

def process_data(data): 
    user_message = data.get("user_message")
    response = {"reply": "Received message: " + user_message}
    return response

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5050, debug=True)
