import os
import aiohttp
import json
import aiosqlite
import pprint
import asyncio
import traceback
import sqlite3
import datetime  # :v

from funciones.mainselenium import verificar_mensajes, monitorear_ventana, enviar_mensaje
from funciones.utiles import respuesta, timeit

from bd.bd import crear_string_insert

url_enviar_mensaje = os.getenv("IP_ATAPIS") + "/nuevo_mensaje"
ruta_bd = os.getenv("RUTA_BD")
telefono = os.getenv("TELEFONO")
url_solicitar_mensajes = os.getenv("IP_ATAPIS") + "/msj/obtener_msj_para_enviar"


def monitorear_mensajes(driver):
    # print("monitorear mensajes")
    """Esta corutina se encarga de revisar los chats de la izquierda, verificando si entran mensajes nuevos
        y guardandolos en la tabla que corresponda para luego ser enviados a AtApis"""

    rta = verificar_mensajes(driver)

    if rta['Estado'] is False:
        return rta

    mensajes = rta['Dato']

    if mensajes:
        conexion = sqlite3.connect(ruta_bd)
        cursor = conexion.cursor()
        for i in mensajes:
            str_insert_mensajes = crear_string_insert(i, tabla='mensajes')
            print("query mm es:", str_insert_mensajes)
            cursor.execute(str_insert_mensajes)

            conexion.commit()
            # conexion.close()
            # await asyncio.sleep(1)

        return respuesta(estado=True,
                         respuesta="Se encontraron chats con mensajes en la izquierda")

    else:
        return respuesta(estado=True,
                         respuesta="No habia mensajes nuevos en los chats de la izquierda")


def monitorear_chat(driver):
    # print("monitorear chat")
    """Esta corutina se encarga de monitorear la ventana de un chat que se encuentra abierto, obteniendo asi los
        ultimos mensajes que llegan para luego guardarlos en la tabla correspondiente y pos teriormente
        ser enviados a AtApis"""

    rta = {'Dato': None}

    try:
        rta = monitorear_ventana(driver)
    except Exception:
        print(traceback.format_exc())

    if not rta['Dato']:
        return respuesta(estado=True, respuesta="No hay ningun chat abierto")

    # id_ultimo_mensaje = rta['Dato']['id_mensaje']
    conexion, cursor = obtener_conexion()  # 0,1ms

    for elemento in rta['Dato']:
        str_insert = insercion(elemento)  # 0,5ms
        ejecutar_query(conexion, cursor, str_insert)  # 0,2ms


# @timeit
def ejecutar_query(conexion, cursor, str_insert):
    try:
        cursor.execute(str_insert)
        conexion.commit()
    except:
        pass


# @timeit
def insercion(rta):
    # cursor.execute(f"SELECT * FROM mensajes WHERE id_mensaje='{id_ultimo_mensaje}'")
    #
    # ultimo_mensaje = cursor.fetchone()
    #
    # if ultimo_mensaje:
    #     return respuesta(estado=True, respuesta="No habia mensajes nuevos en el chat abierto")
    rta['estado'] = 'pendiente'
    # print("trata de insertar directamente. a lo sumo lo rebota
    str_insert = crear_string_insert(*rta.values(), tabla='mensajes')
    # str_insert = crear_string_insert(*rta['Dato'].values(), tabla='mensajes')
    # print("query mc:", str_insert)
    return str_insert


# @timeit
def obtener_conexion():
    conexion = sqlite3.connect(ruta_bd)
    return conexion, conexion.cursor()


# @timeit
def enviar_pendientes_a_usuarios(driver):
    # print("enviar pendientes a usuarios")
    """Esta corutina se encarga de obtener los mensajes pendientes de enviar a un usuario provenientes de AtApis y que
        se han guardado en la tabla 'fila', luego utiliza el webdriver para enviarlos a los usuarios que correspondan"""

    lista_errores = []

    conexion = sqlite3.connect(ruta_bd)

    cursor = conexion.cursor()

    cursor.execute("SELECT rowid,mensaje,telefono,nombre_agendado FROM fila WHERE estado='pendiente'")

    for row in cursor:

        conexion.execute(f"UPDATE fila SET estado='enviando' WHERE rowid={row[0]}")

        conexion.commit()
        print("va a enviarm:", row[1])

        rta = enviar_mensaje(driver, row[1], row[2], row[3])
        # print("envio mensaje",row['mensaje'])
        if rta['Estado'] is False:
            lista_errores.append(rta)
            continue

        conexion.execute(f"UPDATE fila SET estado='enviado' WHERE rowid={row[0]}")

        conexion.commit()

        # conexion.close()

    # si hay errores
    if lista_errores:
        return respuesta(estado=False,
                         respuesta=f"Hubo {len(lista_errores)} errores al enviar mensajes a usuarios",
                         dato=lista_errores)
    # si no hay errores
    return respuesta(estado=True,
                     respuesta="Se enviaron todos los mensajes a los usuarios correctamente")


# @timeit
async def obtener_pendientes_y_enviar():
    # print("enviar a atapis")

    """Esta corutina se encarga de obtener los mensajes que deben enviarse a AtApis, provenientes de la tabla
        'mensajes', luego se evalua la respuesta de AtApis y se actualiza el estado del mensaje a 'enviado'
        solamente si la respuesta de AtApis llego con estado en True"""
    lista_errores = []

    pendientes = []

    telefono_cliente = os.getenv("TELEFONO")

    async with aiosqlite.connect(ruta_bd) as bd:
        bd.row_factory = aiosqlite.Row

        async with bd.execute("SELECT * FROM mensajes WHERE estado='pendiente'") as cursor:
            async for row in cursor:

                print(row['fecha_hora'])  # :v

                hora  = row["fecha_hora"].split(" ")[1]
                fecha_texto = row["fecha_hora"].split(" ")[0]
                print(hora, fecha_texto)

                fecha_date = datetime.datetime.strptime(fecha_texto, '%Y/%m/%d')

                fecha = datetime.datetime.strftime(fecha_date, '%d/%m/%Y')
                print('fecha es de tipo string???',type(fecha))

                fecha_hora = hora + " " + fecha
                print("fecha_hora!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", fecha_hora)  # :V

                dic = dict(telefono_origen=row['telefono'].replace(' ', '').replace('-', ''),
                           telefono_destino=telefono_cliente,
                           mensaje=row['mensaje'],
                           nombre=row['nombre_agendado'],
                           hora_mensaje=fecha_hora,  # row['fecha_hora'] :v
                           clase=row['clase'])

                pendiente = (dic, row['id_mensaje'])

                await bd.execute(f"UPDATE mensajes SET estado='enviando' WHERE id_mensaje='{row['id_mensaje']}'")

                await bd.commit()

                pendientes.append(pendiente)

            if len(pendientes) == 0:
                # print("no hay mensajes pendientes")
                return respuesta(estado=True,
                                 respuesta="No se encontraron mensajes pendientes")
            # print("entro aca una vez")
            async with aiohttp.ClientSession() as sesion:

                # print("si hay mensajes pendientes son:",pendientes)
                for pendiente in pendientes:

                    async with sesion.post(url=url_enviar_mensaje, json=pendiente[0]) as rta_request:

                        rta_atapis = await rta_request.text()

                        rta_atapis = json.loads(rta_atapis)

                        if rta_atapis['Estado']:

                            str_update = f"UPDATE mensajes SET estado='enviado' WHERE id_mensaje='{pendiente[1]}'"

                            await bd.execute(str_update)

                            await bd.commit()

                            # await asyncio.sleep(1)
                        else:
                            lista_errores.append(rta_atapis)

    if len(lista_errores) > 0:
        return respuesta(estado=False,
                         respuesta="Hubo errores al mandar a AtApis",
                         dato=lista_errores)

    else:
        return respuesta(estado=True,
                         respuesta="Se enviaron todos los mensajes a AtApis correctamente")


# @timeit
async def pedir_mensajes():
    import web_pdb
    # web_pdb.set_trace()
    # await asyncio.sleep(1)
    # print("pedir a atapi")

    "pide mensajes a atapis para enviarle a los usuarios y los guarda como pendientes en la bd"
    async with aiohttp.ClientSession() as sesion:

        datos_request = dict(telefono=telefono)

        # print("pide mensaje at apis")
        async with sesion.post(url=url_solicitar_mensajes, json=datos_request) as rta_request:

            rta_atapis = json.loads(await rta_request.text())

            if rta_atapis['Estado'] is False:
                return rta_atapis

            pendientes = rta_atapis['Dato']

            if not pendientes:
                return respuesta(estado=True, respuesta="No habia mensajes pendientes para enviar a usuarios")

    async with aiosqlite.connect(ruta_bd) as bd:

        for pendiente in pendientes:
            print("va a querer insertar obtener mensaje enviar:", pendiente['mensaje'])
            str_insert = crear_string_insert(pendiente['telefono_destino'],
                                             pendiente['mensaje'],
                                             'pendiente',
                                             pendiente['telefono_destino'],
                                             pendiente['fecha_hora'],
                                             tabla='fila')

            await bd.execute(str_insert)

            await bd.commit()

    return respuesta(estado=True, respuesta="Se obtuvieron todos los mensajes pendientes correctamente")
