import sqlite3
import pandas as pd

pd.set_option('display.max_columns', None)
pd.set_option('display.width', None)


def crear_bd_en_memoria():
    conexion = sqlite3.connect(':memory:')

    return conexion


def crear_bd():
    conexion = sqlite3.connect('atwsp.db')

    return conexion


def crear_tabla(conexion, tabla, **campos):
    '''
    Funcion que se encarga de crear una tabla en la base de datos correspondiente al cursor dado.

    :param cursor: (SQLite3) Un objeto de SQLite3 para manejar la base de datos
    :param tabla: (str) El nombre de la tabla
    :param campos: (dict) Un diccionario con el formato {'campo':'tipo_de_campo'}
    :return: None
    '''

    cursor = conexion.cursor()

    _campos = ""

    # Creamos el string para la creacion de la tabla en la base de datos
    for campo, tipo in campos.items():
        _campos += f"{campo} {tipo}, "

    _campos = f"({_campos[:-2]})"  # Sacamos la ultima coma

    _tabla = f"CREATE TABLE {tabla}"

    tabla_str = f"{_tabla} {_campos}"
    print("1112:", tabla_str)
    # tabla_str=tabla_str+' CONSTRAINT id_mensaje_pk PRIMARY KEY (id_mensaje)'

    try:
        cursor.execute(tabla_str)  # Ejecutamos la creacion de la tabla
    except Exception as error:
        if f'table {tabla} already exists' in str(error):
            return

    conexion.commit()


def insertar(conexion, tabla, *values):
    '''
    Funcion que se encarga de insertar en una tabla dada los campos otorgados.

    :param conexion: (SQLite3) Un objeto de SQLite3 para manejar la base de datos
    :param tabla: (str) El nombre de la tabla
    :param values: (list) Una lista con los valores a insertar en la tabla.
    :return: None
    '''

    cursor = conexion.cursor()

    values = f"({str(values).rstrip(',)').lstrip('(')})"

    insertar_str = f"INSERT INTO {tabla} VALUES {values}"

    cursor.execute(insertar_str)

    conexion.commit()

    return cursor.lastrowid


def obtener_todos(conexion, tabla):
    '''
    Esta funcion se encarga de obtener todos los registros de una tabla dada.

    :param conexion: (SQLite3) Un objeto de SQLite3 para manejar la base de datos
    :param tabla: (str) El nombre de la tabla
    :return: (list) Una lista con los resultados de la query
    '''

    cursor = conexion.cursor()

    cursor.row_factory = sqlite3.Row

    cursor.execute(f"SELECT rowid,* FROM {tabla}")

    return cursor.fetchall()


def obtener_pendientes(conexion):
    '''
    Esta funcion se encarga de obtener los mensajes que se encuentran con estado 'pendiente' para enviar al servidor.

    :param conexion: (SQLite3) Un objeto de SQLite3 para manejar la base de datos
    :return:
    '''

    cursor = conexion.cursor()

    cursor.row_factory = sqlite3.Row

    return cursor.execute("SELECT * FROM mensajes WHERE estado='pendiente'").fetchall()


def actualizar_estado_mensaje(conexion, id_mensaje, estado):
    '''
    Esta funcion se encarga de actualizar el estado de un mensaje dado.
    :param conexion: (SQLite3) Un objeto de SQLite3 para manejar la base de datos
    :param id_mensaje: (str) La id unica de un mensaje de WhatsApp
    :param estado: (str) El estado de un mensaje
    :return:
    '''

    cursor = conexion.cursor()

    actualizar_str = "UPDATE mensajes SET estado=? WHERE id_mensaje=?"

    cursor.execute(actualizar_str, (estado, id_mensaje))

    conexion.commit()


def obtener_mensajes_a_enviar(conexion):
    '''
    Esta funcion se encarga de obtener todos los mensajes para enviar a traves de selenium.

    :param conexion: (SQLite3) Un objeto de SQLite3 para manejar la base de datos
    :return:
    '''

    cursor = conexion.cursor()

    cursor.row_factory = sqlite3.Row

    return cursor.execute("SELECT rowid,* FROM fila WHERE estado=?", ['pendiente']).fetchall()


def obtener_id_ultimo_mensaje(conexion, telefono):
    '''
    Esta funcion se encarga de obtener el id del ultimo mensaje enviado por un usuario.

    :param conexion: (SQLite3) Un objeto de SQLite3 para manejar la base de datos
    :param telefono: (str) El telefono del usuario.
    :return:
    '''

    cursor = conexion.cursor()

    cursor.row_factory = sqlite3.Row

    busqueda = "SELECT * FROM mensajes WHERE telefono=?"

    return cursor.execute(busqueda, [telefono]).fetchall()


def obtener_usuario(conexion, telefono):
    cursor = conexion.cursor()

    cursor.row_factory = sqlite3.Row

    busqueda = "SELECT * FROM usuarios WHERE telefono=?"

    return cursor.execute(busqueda, [telefono]).fetchone()


def actualizar_mensaje_fila(conexion, id_mensaje, estado):
    cursor = conexion.cursor()

    actualizar_str = "UPDATE fila SET estado=? WHERE rowid=?"

    cursor.execute(actualizar_str, (estado, id_mensaje))

    conexion.commit()


def printear_tabla(conexion, tabla):
    print(pd.read_sql_query(f"SELECT * FROM {tabla}", conexion))


def actualizar_contacto(conexion, telefono, nombre_agendado):
    cursor = conexion.cursor()

    actualizar_str = "UPDATE usuarios SET nombre_agendado=? WHERE telefono=?"

    cursor.execute(actualizar_str, (nombre_agendado, telefono))

    conexion.commit()