from flask import Flask, jsonify, request
import random
import string
from flask_cors import CORS
import asyncio
import websockets
import json
import mysql.connector
import random
import string
from datetime import datetime
import threading

tiempo_qr = 3

mydb = mysql.connector.connect(
    host='localhost',
    user='root',
    password='',
    database='qrWS'
)

conexiones = {}

def generar_string_aleatorio(longitud):
    return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(longitud))

def cambioQR(id_conexion,v_qr): 
    
    mydb = mysql.connector.connect(
        host='localhost',
        user='root',
        password='',
        database='qrWS'
    )
    
    mycursor = mydb.cursor()
    
    sql = f"SELECT leido FROM `qr` WHERE id = {id_conexion}"
    mycursor.execute(sql)
    usr = mycursor.fetchone()
    
    if str(usr[0]) == '1':
        return True
    
    sql = f'DELETE FROM `qr` WHERE id = {id_conexion}'
    mycursor.execute(sql)
    mydb.commit()

    sql = 'INSERT INTO `qr`(`id`, `qr`, `timer`) VALUES (%s,%s,%s)'
    fecha_hora = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    mycursor.execute(sql, (id_conexion, v_qr, fecha_hora))
    mydb.commit()
    mydb.close()
    
    return False

async def handle_connection(websocket):
    data = await websocket.recv()
    id_conexion = json.loads(data)['id_s']
    
    mydb = mysql.connector.connect(
        host='localhost',
        user='root',
        password='',
        database='qrWS'
    )

    mycursor = mydb.cursor()
    sql = f"SELECT * FROM `usr` WHERE id = {id_conexion}"
    mycursor.execute(sql)
    usr = mycursor.fetchone()
    mydb.close()

    if len(usr) != 0:
        v_qr = generar_string_aleatorio(10)
        
        mydb = mysql.connector.connect(
            host='localhost',
            user='root',
            password='',
            database='qrWS'
        )

        mycursor = mydb.cursor()
        sql = f'DELETE FROM `qr` WHERE id = {id_conexion}'
        mycursor.execute(sql)
        mydb.commit()

        sql = 'INSERT INTO `qr`(`id`, `qr`, `timer`) VALUES (%s,%s,%s)'
        fecha_hora = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        mycursor.execute(sql, (id_conexion, v_qr, fecha_hora))
        mydb.commit()
        mydb.close()

        qr = {
            'qr': v_qr,
            'cierre': 0
                }
        await websocket.send(json.dumps(qr))

        conexiones[id_conexion] = websocket
        print(f"Conexión establecida con {id_conexion}")

        async def enviar_qr():
            while True:
                try:
                    await asyncio.sleep(tiempo_qr)
                    v_qr = generar_string_aleatorio(10)
                    if cambioQR(id_conexion,v_qr):
                        return
                    qr = {
                        'qr': v_qr,
                        'cierre': 0
                            }
                    await websocket.send(json.dumps(qr))
                except websockets.exceptions.ConnectionClosedOK:
                    print('Conexión cerrada')
                    break

        tarea = asyncio.create_task(enviar_qr())
        while True:
            try:
                mensaje = await websocket.recv()
            except websockets.exceptions.ConnectionClosedOK:
                print('Conexión cerrada')
                del conexiones[id_conexion]
                tarea.cancel()
                break

async def main():
    async with websockets.serve(handle_connection, "192.168.0.100", 821):
        print("Servidor iniciado en 192.168.0.100:821")
        await asyncio.Future()  # Mantener el servidor en ejecución
        



def generar_string_aleatorio(longitud):
    return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(longitud))

app= Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}})

@app.route('/')
def root():
    return 'root'

@app.route('/rand')
def get_U():
    
    
    qr = {'qr':generar_string_aleatorio(10)}

    return jsonify(qr), 200

@app.route('/lector', methods=['GET'])
def lector():
    #qr = request.form['qr']
    qr = request.args.get('qr')

    # Ahora puedes utilizar las variables nombre, edad y ciudad
    print(f"QR: {qr}")
    
    mydb = mysql.connector.connect(
        host='localhost',
        user='root',
        password='',
        database='qrWS'
    )

    mycursor = mydb.cursor()
    sql = f"SELECT id,leido FROM `qr` WHERE qr = '{qr}'"
    print(sql)
    mycursor.execute(sql)
    inf_qr = mycursor.fetchone()
    mydb.close()
    
    print(f'var: {conexiones}')
    print(inf_qr[0])
        
    
    v_qr = generar_string_aleatorio(10)
    
    mydb = mysql.connector.connect(
        host='localhost',
        user='root',
        password='',
        database='qrWS'
    )
    
    mycursor = mydb.cursor()
    sql = f'DELETE FROM `qr` WHERE id = {inf_qr[0]}'
    mycursor.execute(sql)
    mydb.commit()

    sql = 'INSERT INTO `qr`(`id`, `qr`, `timer`, `leido`) VALUES (%s,%s,%s,%s)'
    fecha_hora = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    mycursor.execute(sql, (inf_qr[0], v_qr, fecha_hora, '1'))
    mydb.commit()
    mydb.close()
    
    qr = {
        'qr': v_qr,
        'cierre': 0
            }
    async def envio_lector():
        # ...
        await conexiones[str(inf_qr[0])].send(json.dumps(qr))
        # ...
        
    async def cierre_lector():
        
        qr = {
            'qr': 'leido',
            'cierre': 1
                }
        # ...
        await conexiones[str(inf_qr[0])].send(json.dumps(qr))
        # ...
    
    if str(inf_qr[1]) != '1':
        print(conexiones[str(inf_qr[0])])
        
        asyncio.run(envio_lector())

        return json.dumps({
            'rescibido': 1,
            'login': 0
                })
    else:
        
        asyncio.run(cierre_lector())
        
        return json.dumps({
            'rescibido': 1,
            'login': 1
                })


def inicio():
    app.run(host='192.168.0.100',port=2821)



if __name__ == "__main__":
    flas = threading.Thread(target=inicio)
    flas.daemon = True
    flas.start()
    asyncio.run(main())