from pynput import keyboard
import serial
import requests
import logging
import time
import json
import sys
import os
import json

# ============================================================
# CONFIGURACION
# ============================================================

CONFIG_FILE = r"config.json"

with open(CONFIG_FILE, "r", encoding="utf-8") as f:
    config = json.load(f)

API_URL = config["api"]["url"] + "/api/access/validate"
REQUEST_TIMEOUT = config["api"]["timeout"]

ARDUINO_PORT = config["arduino"]["port"]
ARDUINO_BAUDRATE = config["arduino"]["baudrate"]

LOG_DIR = config["logging"]["path"]

ENTRANCE_COMMAND = config["commands"]["entrance"]
EXIT_COMMAND = config["commands"]["exit"]
DENIED_COMMAND = config["commands"]["denied"]
EMERGENCY_COMMAND = config["commands"]["emergency"]

# ============================================================
# LOGGING
# ============================================================
os.makedirs(LOG_DIR, exist_ok=True)
logging.basicConfig(
    filename=os.path.join(LOG_DIR, config["logging"]["name"]),
    level=config["logging"]["level"],
    format="%(asctime)s | %(levelname)s | %(message)s",
)

# ============================================================
# SERIAL
# ============================================================
arduino = None


def connect_arduino():
    global arduino

    while True:
        try:

            # arduino = serial.Serial(
            #     port=ARDUINO_PORT, baudrate=ARDUINO_BAUDRATE, timeout=1
            # )

            logging.info(f"Arduino conectado en {ARDUINO_PORT}")

            return

        except Exception as e:

            logging.error(f"Error conectando Arduino: {str(e)}")

            time.sleep(5)


def send_command(command: str):

    global arduino

    try:

        # if arduino is None or not arduino.is_open:
        #     connect_arduino()
        # arduino.write(command.encode())

        logging.info(f"COMANDO ENVIADO => {command}")
    except Exception as e:
        logging.error(f"Error enviando comando: {str(e)}")
        # try:
        #     arduino.close()
        # except:
        #     pass
        # connect_arduino()


# ============================================================
# API
# ============================================================


def validate_qr(code: str):

    try:

        response = requests.post(
            API_URL,
            headers={
                "Accept": "application/json",
            },
            json={"code": code},
            timeout=REQUEST_TIMEOUT,
        )
        # debug response
        logging.info(f"API RESPONSE => {response.status_code} {response.text}")
        return response.json()

    except Exception as e:

        logging.error(f"Error API: {str(e)}")
        logging.error(f"At line: {sys.exc_info()[-1].tb_lineno}")

        return {"authorized": False, "command": DENIED_COMMAND, "message": "API_ERROR"}


# ============================================================
# PROCESAMIENTO
# ============================================================


def process_qr(code):

    code = code.strip()

    if not code:
        return

    logging.info(f"QR LEIDO => {code}")

    result = validate_qr(code)

    authorized = result.get("authorized", False)

    command = result.get("command", DENIED_COMMAND)

    message = result.get("message", "")

    logging.info(f"API => AUTH={authorized} CMD={command} MSG={message}")

    send_command(command)


# ============================================================
# LECTOR HID
# ============================================================

buffer = ""


def on_press(key):

    try:
        print(repr(key))
    except:
        pass

# ============================================================
# MAIN
# ============================================================


def main():

    logging.info("SERVICIO INICIADO")

    connect_arduino()

    listener = keyboard.Listener(on_press=on_press)

    listener.start()

    listener.join()


if __name__ == "__main__":
    main()
