from flask import Flask, request, jsonify, render_template, redirect, url_for, flash
from flask_cors import CORS
import openai
import mysql.connector
import smtplib
import re
from email.mime.text import MIMEText
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField
from wtforms.validators import DataRequired
from flask import Markup
import logging
import time
import requests
from requests.exceptions import ConnectionError
from urllib.parse import unquote


# Para las variables de entorno
from dotenv import load_dotenv
import os
logging.basicConfig(level=logging.DEBUG)

# 2. Configura las variables de entorno
load_dotenv()

userdbent = os.environ.get('userdbent')
passdbent = os.environ.get('passdbent')
databasedbent = os.environ.get('databasedbent')
apisecret = os.environ.get('apisecret')
emailsend= os.environ.get('emailsend')
emailsendname= os.environ.get('emailsendname')
emailpass= os.environ.get('emailpass')
emailsmtp= os.environ.get('emailsmtp')
emailrespuesta= os.environ.get('emailrespuesta')

application = Flask(__name__)
CORS(application, resources={r"/get-response-by-token/*": {"origins": "https://cursos.entrenador.ai"}})
CORS(application, resources={r"/get-latest-webhook-token": {"origins": "https://cursos.entrenador.ai"}})
# Configura tu clave API de OpenAI
openai.api_key = apisecret



# Configuracin de la base de datos MariaDB
DB_CONFIG = {
    'user': userdbent,
    'password': passdbent,
    'host': 'localhost',
    'database': databasedbent,
    'raise_on_warnings': False
}

@application.route('/')
def redirect_to_cursos():
    return redirect('https://inteliventa.ai')

def db_connection():
    return mysql.connector.connect(**DB_CONFIG)



def send_email(recipient_email, subject, body, bcc=None):
    sender_name = emailsendname
    sender_email = emailsend
    sender_password = emailpass

    # MIMEText para HTML
    msg = MIMEText(body, 'html', _charset='utf-8')
    msg["From"] = f"{sender_name} <{sender_email}>"  # Cambio realizado aquí
    msg["To"] = recipient_email
    msg["Subject"] = subject

    recipients = [recipient_email]
    if bcc:
        recipients.append(bcc)

    try:
        server = smtplib.SMTP_SSL(emailsmtp, 465)
        server.login(sender_email, sender_password)
        server.sendmail(sender_email, recipients, msg.as_string())
        server.quit()
    except Exception as e:
        print(f"Error al enviar correo: {e}")

        
        
def text_to_html_table(input_text):
    segments = input_text.split('\n\n')  # Divide el texto en segmentos basados en dos saltos de línea consecutivos
    
    output = ""
    
    for segment in segments:
        # Si el segmento contiene el carácter '|', conviértelo en una tabla
        if '|' in segment:
            rows = segment.split('\n')  # Divide el segmento en filas basado en saltos de línea

            # Inicia la tabla HTML
            html_table = '<table border="1">'

            for row in rows:
                cells = row.split('|')  # Divide cada fila en celdas basado en el carácter '|'
                cells = [cell.strip() for cell in cells]  # Limpia los espacios en blanco alrededor de cada celda
                if 'Pregunta de verificacion' in row:  # Si es la cabecera
                    html_table += '<tr>' + ''.join(f'<th>{cell}</th>' for cell in cells) + '</tr>'
                else:
                    html_table += '<tr>' + ''.join(f'<td>{cell}</td>' for cell in cells) + '</tr>'

            # Finaliza la tabla HTML
            html_table += '</table>'
            
            output += html_table + "<br>"
        else:
            # Si el segmento no contiene '|', simplemente añádelo al output con saltos de línea convertidos a <br>
            output += segment.replace('\n', '<br>') + "<br><br>"
    
    return output
    


latest_token = None

@application.route('/videoask-webhook', methods=['POST'])
def handle_webhook():
    global latest_token
    data = request.json
    contact_id = data.get("contact")["contact_id"]
    name = data.get("contact")["name"]
    email = data.get("contact")["email"]
    token = data.get("contact", {}).get("variables", {}).get("token", None)
    latest_token = token

    cnx = db_connection()
    cursor = cnx.cursor()
    try:
        # Insertar datos de contacto
        contact_values = (
            contact_id,
            data.get("contact").get("organization_id", None),
            data.get("contact").get("respondent_id", None),
            name,
            data.get("contact").get("product_name", ""),
            email,
            data.get("contact").get("phone_number", ""),
            data.get("contact").get("thumbnail", ""),
            data.get("contact").get("status", ""),
            data.get("contact").get("created_at", None),
            data.get("contact").get("updated_at", None)
        )
        cursor.execute("""
            INSERT INTO contacto (contact_id, organization_id, respondent_id, name, product_name, email, phone_number, thumbnail, status, created_at, updated_at)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        """, contact_values)

        # Insertar datos iniciales de answers y procesar con ChatGPT
        for answer in data.get("contact", {}).get("answers", []):
            answer_values = (
                answer.get("answer_id", None),
                contact_id,
                answer.get("contact_product_name", ""),
                answer.get("created_at", None),
                answer.get("gif", ""),
                answer.get("is_public", None),
                answer.get("media_duration", None),
                answer.get("media_id", None),
                answer.get("media_url", ""),
                answer.get("question_id", ""),
                answer.get("share_id", ""),
                answer.get("share_url", ""),
                answer.get("thumbnail", ""),
                answer.get("transcode_status", ""),
                answer.get("transcribe_status", ""),
                answer.get("transcription", ""),
                token
            )
            cursor.execute("""
                INSERT INTO answers (answer_id, contact_id, contact_product_name, created_at, gif, is_public, media_duration, media_id, media_url, question_id, share_id, share_url, thumbnail, transcode_status, transcribe_status, transcription, token) 
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            """, answer_values)
            cnx.commit()

            # Procesar con re_run_chatgpt y enviar email
            answer_id = answer.get("answer_id", None)
            if answer_id:
                chat_response = run_chatgpt(answer_id)
                if chat_response:
                    # Actualizar la respuesta en la base de datos solo si run_chatgpt fue exitoso
                    cursor.execute("""
                        UPDATE answers 
                        SET chatgpt_response = %s
                        WHERE answer_id = %s
                    """, (chat_response, answer_id))
                    cnx.commit()
                else:
                    # Manejar el caso en que run_chatgpt no devolvió una respuesta válida
                    print(f"No se pudo obtener respuesta de ChatGPT para el answer_id: {answer_id}")
                send_email_with_answer(answer_id, email)

        return jsonify({"status": "success"})

    except Exception as e:
        print(f"Error: {e}")
        cnx.rollback()
        return jsonify({"status": "failed", "error": str(e)}), 500

    finally:
        cursor.close()
        cnx.close()



@application.route('/get-latest-webhook-token', methods=['GET'])
def get_latest_webhook_token():
    if latest_token:
        return jsonify({"token": latest_token})
    else:
        return jsonify({"error": "No hay tokens recientes"}), 404
        
        

def text_to_html(text):
    return Markup(text.replace("\n", "<br>"))

@application.route('/get-response/<answer_id>', methods=['GET'])
def get_response(answer_id):
    cnx = db_connection()
    cursor = cnx.cursor()
    try:
        cursor.execute("SELECT chatgpt_response FROM answers WHERE answer_id = %s", (answer_id,))
        response = cursor.fetchone()
        if response:
            html_response = text_to_html(response[0])
            return render_template("response.html", response=html_response)  # Asumiendo que tienes una plantilla HTML llamada "response.html"
        else:
            return jsonify({"status": "no response found for given answer_id"}), 404
    finally:
        cursor.close()
        cnx.close()
# fin funcion para ver la respuesta de la AI con el asnwer_id
#aca funciones para enviar respuesta por mail a la solicitud de answer_id
        
        
@application.route('/get-resultado/<answer_id>', methods=['GET'])
def get_resultado(answer_id):
    cnx = db_connection()
    cursor = cnx.cursor()
    try:
        cursor.execute("SELECT chatgpt_response FROM answers WHERE answer_id = %s", (answer_id,))
        response = cursor.fetchone()
        if response:
            # Buscar "Resultado: " seguido de cualquier palabra (\w+ significa una o más letras/dígitos)
            match = re.search(r"Resultado: (\w+)", response[0])
            if match:
                # Devolver la palabra que sigue a "Resultado: "
                result_word = match.group(1)
                return result_word
            else:
                return jsonify({"status": "Resultado no encontrado en la respuesta"}), 404
        else:
            return jsonify({"status": "no response found for given answer_id"}), 404
    finally:
        cursor.close()
        cnx.close()
# fin funcion para ver la respuesta de la AI con el asnwer_id
#aca funciones para enviar respuesta por mail a la solicitud de answer_id

def get_chatgpt_response(answer_id):
    cnx = db_connection()
    cursor = cnx.cursor()
    try:
        cursor.execute("SELECT chatgpt_response FROM answers WHERE answer_id = %s", (answer_id,))
        response = cursor.fetchone()
        if response:
            return response[0]
        else:
            return None
    finally:
        cursor.close()
        cnx.close()        
        
def send_email_with_answer(answer_id, recipient_email):
    chatgpt_response = get_chatgpt_response(answer_id)
    if chatgpt_response:
        html_content = text_to_html_table(chatgpt_response)
        
        # Añadir enlaces para la evaluación
        evaluation_links = f'''
        <br><br>
        <h3>Por favor evalúa la respuesta:</h3>
        <ul>
            <li><a href="https://entrenador.ai/update-response/{answer_id}/1">Muy Mal</a></li>
            <li><a href="https://entrenador.ai/update-response/{answer_id}/2">Mal</a></li>
            <li><a href="https://entrenador.ai/update-response/{answer_id}/3">Regular</a></li>
            <li><a href="https://entrenador.ai/update-response/{answer_id}/4">Bien</a></li>
            <li><a href="https://entrenador.ai/update-response/{answer_id}/5">Muy Bien</a></li>
        </ul>
        '''
        
        # Concatenar el contenido HTML con los enlaces de evaluación
        html_content += evaluation_links
        
        # Enviar el correo electrónico
        send_email(recipient_email, "Respuesta de Entrenamiento", html_content, bcc="rodolfocooper@gmail.com")
    else:
        print(f"No se encontró chatgpt_response para el answer_id: {answer_id}")

        


@application.route('/send-email/<answer_id>/<recipient_email>', methods=['GET'])
def send_email_route(answer_id, recipient_email):
    send_email_with_answer(answer_id, recipient_email)
    return jsonify({"status": "Correo enviado"})


#fin funciones para enviar respuesta por mail a la solicitud de answer_id
#aca funciones para reprocesar el paso por chatgpt


def run_chatgpt(answer_id):
    cnx = db_connection()
    cursor = cnx.cursor()
    max_retries = 3  # Número máximo de reintentos
    for attempt in range(max_retries):
        try:
            # Obtener los datos de la respuesta original para este answer_id
            cursor.execute("SELECT question_id, transcription, contact_id FROM answers WHERE answer_id = %s", (answer_id,))
            original_answer = cursor.fetchone()
            if original_answer:
                question_id, transcription, contact_id = original_answer
                
                # Obtener el campo name desde la tabla contacto
                cursor.execute("SELECT name FROM contacto WHERE contact_id = %s", (contact_id,))
                contact_data = cursor.fetchone()
                if contact_data:
                    name = contact_data[0]

                    # Obtener el prompt asociado a este question_id
                    cursor.execute("SELECT prompts FROM los_promts WHERE question_id = %s", (question_id,))
                    result = cursor.fetchone()
                    if result:
                        prompts_value = result[0]

                        # Enviar solicitud a ChatGPT
                        chatgpt_response = openai.ChatCompletion.create(
                            model="gpt-4",
                            messages=[
                                {
                                    "role": "system",
                                    "content": "El nombre del vendedor es:" + name + " " + prompts_value
                                },
                                {
                                    "role": "user",
                                    "content": transcription
                                }
                            ],
                            temperature=1,
                            max_tokens=3000,
                            top_p=1,
                            frequency_penalty=0,
                            presence_penalty=0
                        )
                        chat_response = chatgpt_response.choices[0]['message']['content'].strip()
                        
                        return chat_response  # Devuelve la respuesta de ChatGPT si tiene éxito
                    else:
                        return None  # prompt no encontrado para question_id
                else:
                    return None  # contact data no encontrado para contact_id
            else:
                return None  # answer no encontrado para answer_id

        except Exception as e:
            print(f"Error en intento {attempt + 1} en run_chatgpt:", e)
            if attempt < max_retries - 1:
                time.sleep(2)  # Espera antes de reintentar
                continue  # Reintenta
            else:
                # Mensaje en caso de fallas reiteradas
                return "Tu respuesta será analizada por nuestro equipo, tu feedback llegará vía email, gracias."

        finally:
            cursor.close()
            cnx.close()

    # Mensaje en caso de fallas reiteradas (fuera del bucle, si se alcanza el máximo de reintentos)
    return "Tu respuesta será analizada por nuestro equipo, tu feedback llegará vía email, gracias."


# En la función handle_webhook (o donde sea que llames a run_chatgpt):

# ...




@application.route('/re-run-chatgpt/<answer_id>', methods=['GET'])
def re_run_chatgpt(answer_id):
    cnx = db_connection()
    cursor = cnx.cursor()
    try:
        # Obtener los datos de la respuesta original para este answer_id
        cursor.execute("SELECT question_id, transcription, contact_id FROM answers WHERE answer_id = %s", (answer_id,))
        original_answer = cursor.fetchone()
        if original_answer:
            question_id, transcription, contact_id = original_answer
            
            # Obtener el campo name desde la tabla contacto
            cursor.execute("SELECT name FROM contacto WHERE contact_id = %s", (contact_id,))
            contact_data = cursor.fetchone()
            if contact_data:
                name = contact_data[0]

                # Aquí puedes utilizar 'name' como una variable
            
            # Obtener el prompt asociado a este question_id
            cursor.execute("SELECT prompts FROM los_promts WHERE question_id = %s", (question_id,))
            result = cursor.fetchone()
            if result:
                prompts_value = result[0]

                # Enviar solicitud a ChatGPT
                chatgpt_response = openai.ChatCompletion.create(
                    model="gpt-4",
                    messages=[
                        {
                            "role": "system",
                            "content": "El nombre del vendedor es:" + name + " " + prompts_value
                        },
                        {
                            "role": "user",
                            "content": transcription
                        }
                    ],
                    temperature=1,
                    max_tokens=3000,
                    top_p=1,
                    frequency_penalty=0,
                    presence_penalty=0
                )
                chat_response = chatgpt_response.choices[0]['message']['content'].strip()
                
                # Actualizar la respuesta de ChatGPT en la base de datos
                cursor.execute("""
                    UPDATE answers 
                    SET chatgpt_response = %s
                    WHERE answer_id = %s
                """, (chat_response, answer_id))
                
                cnx.commit()
                return jsonify({"status": "success, chatgpt_response updated"})
            else:
                return jsonify({"status": "failed, prompt not found for question_id"}), 404
        else:
            return jsonify({"status": "failed, answer not found for answer_id"}), 404
    except Exception as e:
        print("Error:", e)
        cnx.rollback()
        return jsonify({"status": "failed", "error": str(e)}), 500
    finally:
        cursor.close()
        cnx.close()
#actualizar nota de respuesta.

@application.route('/update-response/<answer_id>/<nota_vendedor>', methods=['GET'])


def update_response(answer_id, nota_vendedor):
    cnx = db_connection()
    cursor = cnx.cursor()
    try:
        # Comprobar si EvaluadaVendedor es 0 para este answer_id
        cursor.execute("SELECT EvaluadaVendedor FROM answers WHERE answer_id = %s", (answer_id,))
        result = cursor.fetchone()
        if result is None:
            return '', 404  # No se encontró el answer_id en la base de datos
        elif result[0] != 0:
            return '', 403  # Operación prohibida si EvaluadaVendedor no es 0
        
        # Actualizar las columnas EvaluadaVendedor y NotaVendedor
        update_query = """
        UPDATE answers 
        SET EvaluadaVendedor = 1, NotaEvaluacion = %s 
        WHERE answer_id = %s AND EvaluadaVendedor = 0
        """
        
        # Ejecutar la consulta de actualización
        cursor.execute(update_query, (nota_vendedor, answer_id))
        
        # Confirmar la transacción
        cnx.commit()
        
        return '''
        <html>
        <body>
        <h3>Evaluación enviada puedes cerrar esta pestaña, gracias</h3>
        <script>
        window.close();
        </script>
        </body>
        </html>
        '''
        
    except mysql.connector.Error as err:
        print("Error:", err)
        cnx.rollback()
        return '', 500  # Error interno del servidor
        
    finally:
        # Cerrar el cursor y la conexión
        cursor.close()
        cnx.close()

@application.route('/get-response-by-token/<token>', methods=['GET'])
def get_response_by_token(token):
    cnx = db_connection()
    cursor = cnx.cursor(buffered=True)  # Usa un cursor con buffer
    decoded_token = unquote(token)
    try:
        # Modificar la consulta para ordenar por created_at en orden descendente
        cursor.execute("""
            SELECT chatgpt_response 
            FROM answers 
            WHERE token = %s 
            ORDER BY created_at DESC
            LIMIT 1
        """, (decoded_token,))
        response = cursor.fetchone()
        if response:
            return jsonify({"status": "success", "data": response[0]})
        else:
            return jsonify({"status": "no data found for given token"}), 404
    except Exception as e:
        print(f"Error: {e}")
        return jsonify({"status": "error", "message": str(e)}), 500
    finally:
        cursor.close()  # Asegúrate de cerrar el cursor
        cnx.close()  # y la conexión



if __name__ == '__main__':
    application.run(host='0.0.0.0', port=5000)