from flask import Flask, request, jsonify
import json
import os
import logging
from app.database.models.user_model import get_user_channels_config_by_whatsapp_bus_id_and_phone_number, User
from app.database.models.contact_model import Contact
from app.database.models.processing_result_model import ResultsModel
from send_msg import send_whatsapp_message, process_pending_unsent_communications
import threading
from logging.handlers import RotatingFileHandler
from werkzeug.utils import secure_filename
from werkzeug.exceptions import BadRequest
import requests
import re


handler = RotatingFileHandler("log.txt", maxBytes=1000000, backupCount=2)

app = Flask(__name__)

BASE_PATH = os.path.dirname(os.path.abspath(__file__))

logging.basicConfig(
    filename='log.txt',
    filemode='a',  # Append to the log file
    format='%(asctime)s - %(levelname)s - %(message)s',
    level=logging.INFO
)

# Configuration
UPLOAD_FOLDER = os.path.join('..', '..', 'uploaded_files')
ALLOWED_EXTENSIONS = {'pdf', 'xlsx', 'xls'}

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER


verify_token = os.getenv('WHATSAPP_VERIFY_TOKEN')

@app.route('/whatsapp-endpoint', methods=['GET'])
def verify():
    # Facebook sends a GET request to verify the webhook, including query parameters like "hub.challenge".
    mode = request.args.get('hub.mode')
    token = request.args.get('hub.verify_token')
    challenge = request.args.get('hub.challenge')

    # Check if mode and token are correct
    if mode == 'subscribe' and token == verify_token:
        print('WEBHOOK_VERIFIED')
        # Return the challenge back to complete verification
        return challenge, 200
    else:
        # Respond with '403 Forbidden' if the tokens do not match
        return 'Forbidden', 403


@app.route('/whatsapp-endpoint', methods=['POST'])
def whatsapp_endpoint():
    try:
        logging.info("Received POST request at /whatsapp-endpoint")

        payload = request.data
        logging.debug(f"Raw payload: {payload}")  # Log the raw payload

        data_array = request.get_json()
        with open('payload.txt', 'w') as f:
            f.write(str(data_array))  # Convert payload to string and write to file

        if not data_array:
            logging.warning("No JSON data provided in the request")
            return jsonify({"error": "No data provided"}), 400

        logging.info("JSON data successfully parsed")

        # Continue processing the payload...
        # Log any other critical steps in your processing
        # ...

        # Decode the JSON payload
        data_array = json.loads(payload)
        #logging.info(data_array)
        #with open("response.txt", 'r', encoding='utf-8') as file:
            # Read the file content and parse the JSON
           #data_array = json.load(file)

        #print(data_array)
        account_type = data_array['object']
        message_id = data_array['entry'][0]['changes'][0]['value']['messages'][0]['id']
        logging.info("JSON data successfully parsed" + message_id)

        if account_type != "whatsapp_business_account":
            logging.error("Unauthorized account, please contact system admin", None, None)
            return jsonify({"status": "success", "message": "Data processed successfully!"}), 200
        else:
            whats_business_id = data_array['entry'][0]['id']
            user_phone_number = data_array['entry'][0]['changes'][0]['value']['metadata']['display_phone_number']

            contact_phone_number = data_array['entry'][0]['changes'][0]['value']['messages'][0]['from']

            text_content = None
            if "text" in data_array['entry'][0]['changes'][0]['value']['messages'][0]:
                text_content = data_array['entry'][0]['changes'][0]['value']['messages'][0]['text']['body']

            media_id = None
            if "document" in data_array['entry'][0]['changes'][0]['value']['messages'][0]:
                media_id = data_array['entry'][0]['changes'][0]['value']['messages'][0]['document']['url']


            #find user by whatsapp business id and phone number
            user_channel_data = get_user_channels_config_by_whatsapp_bus_id_and_phone_number(whats_business_id,user_phone_number)

            filename = None
            if media_id is not None:
                # download media to folder
                temp_filename = data_array['entry'][0]['changes'][0]['value']['messages'][0]['document']['filename']
                if allowed_file(temp_filename):
                    filename = download_file(media_id, temp_filename, user_channel_data['user_whatsapp_bot_api_key'])
                else:
                    logging.info("Unacceptable File Format" + message_id)


            user_id = user_channel_data[0]['user_id']
            user_whatsapp_token = user_channel_data[0]['user_whatsapp_bot_api_key']
            user_whatsapp_phone_no_id = user_channel_data[0]['user_whatsapp_phone_no_id']
            user = User(user_id)
            user_data = user.get_user_data_by_id()
            user_name = user_data[0]['user_name']
            if user_channel_data not in (None, ""):
                #check if contact is in contact list and approved

                contact = Contact(user_id,None)
                contact_data = contact.get_contact_data_by_phone_number(contact_phone_number)

                contact_id = contact_data[0]['user_contact_id']
                contact_country_language_code = contact_data[0]['contact_default_language_country_code']
                contact_is_approved = contact.contact_has_been_approved_for_processing()

                if contact_is_approved:
                    #log text entry for processing
                    storage = ResultsModel(user_id, contact_id)
                    try:
                        # Attempt to store the communication log
                        storage.store_communication_log(text_content,None,1,contact_country_language_code,
                                                        1,message_id, filename)

                        # If successful, return the success message
                        success_msg = "Your message has been received by "+user_name+" and will be processed shortly"
                        send_whatsapp_message(user_whatsapp_phone_no_id,contact_phone_number,success_msg,user_whatsapp_token)
                        logging.error(success_msg + " %s: %s", contact_phone_number, None)
                        return jsonify({"status": "success", "message": "Data processed successfully!"}), 200

                    except Exception as e:
                        # Process the error and return an error message
                        error_message = f"Failed to store message: {str(e)}"
                        logging.error(error_message + " %s: %s", contact_phone_number, str(e))
                        send_whatsapp_message(user_whatsapp_phone_no_id,contact_phone_number,error_message,user_whatsapp_token)
                        return jsonify({"status": "success", "message": "Data processed successfully!"}), 200

            else:
                response = "Something is wrong with your account or you are not a registered contact at Proprocur, reach out on proprocur.com or email support@proprocur.com"
                send_whatsapp_message(user_whatsapp_phone_no_id,contact_phone_number,response,user_whatsapp_token)
                return jsonify({"status": "success", "message": "Data processed successfully!"}), 200


    except Exception as e:
        logging.error("Error processing the request:", None, str(e))
        return jsonify({"status": "error", "message": "Failed to process the message."}), 500

# Check if the file is allowed
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# Sanitize filenames and remove any harmful characters
def sanitize_filename(filename):
    return secure_filename(re.sub(r'[^a-zA-Z0-9_.-]', '_', filename))

# Scan file for viruses - placeholder for real scanning implementation
def scan_file(filepath):
    # Integrate with a virus scanning API/service or local tool here
    return True  # Assuming the file is clean for this example

# Function to download the file
def download_file(media_id, filename, access_token):
    #url = f"https://graph.facebook.com/v22.0/{media_id}"

    # Download the media file
    media_response = requests.get(media_id, headers={'Authorization': f'Bearer {access_token}'})

    if media_response.status_code == 200:
        sanitized_filename = sanitize_filename(filename)
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], sanitized_filename)
        with open(filepath, 'wb') as file:
            file.write(media_response.content)

        return sanitized_filename
    else:
        return None


if __name__ == '__main__':
    # Start the background thread
    communication_thread = threading.Thread(target=process_pending_unsent_communications)
    communication_thread.daemon = True  # Optional: Makes the thread exit when the main program exits
    communication_thread.start()

    # Start the Flask server
    app.run(debug=True)


