import os
import sys

# Carpeta donde vive este archivo. Hace que el cliente funcione igual
# en cualquier máquina sin depender del directorio de trabajo ni del ._pth.
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
if BASE_DIR not in sys.path:
    sys.path.insert(0, BASE_DIR)

import paho.mqtt.client as mqtt
import json
import base64
from datetime import datetime
from imprimir import imprimir_tspl, imprimir_pdf

class MQTTSubscriber:
    def __init__(self):
        self.client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
        
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message
        self.client.on_disconnect = self.on_disconnect
        self.client.on_subscribe = self.on_subscribe
        
        self.config = self.cargar_configuracion()
        self.broker_host = self.config.get('server')
        self.broker_port = self.config.get('port', 1883)
        self.mapa_rutas_impresoras = self.crear_mapa_rutas()
    
    def cargar_configuracion(self):
        try:
            with open(os.path.join(BASE_DIR, 'config.json'), 'r', encoding='utf-8') as file:
                return json.load(file)
        except Exception as e:
            print(f"Error al cargar configuración: {e}")
            return {}
    
    def crear_mapa_rutas(self):
        mapa = {}
        for impresora in self.config.get('impresoras', []):
            ruta = impresora.get('ruta')
            mapa[ruta] = {
                'nombre': impresora.get('nombre'),
                'formato': impresora.get('formato'),
                'descripcion': impresora.get('descripcion')
            }
        return mapa
    
    def on_connect(self, client, userdata, flags, reason_code, properties):
        if reason_code == 0:
            print(f"Conectado MQTT en {self.config.get('descripcion_lugar')}")
            self.subscribe_to_topics()
        else:
            print(f"Error de conexión. Código: {reason_code}")
    
    def on_subscribe(self, client, userdata, mid, reason_codes, properties):
        print(f"Suscrito exitosamente. Códigos: {reason_codes}")
    
    def on_disconnect(self, client, userdata, flags, reason_code, properties):
        print("Desconectado del broker MQTT")
    
    def funcion_impresion_tspl(self, topic, message):
        impresora_info = self.mapa_rutas_impresoras.get(topic)
        if impresora_info:
            nombre_impresora = impresora_info['nombre']
            exito = imprimir_tspl(message, nombre_impresora)
            if exito:
                print(f"TSPL impreso en {nombre_impresora}")
            else:
                print(f"Error imprimiendo TSPL en {nombre_impresora}")

    def funcion_impresion_pdf(self, topic, message):
        impresora_info = self.mapa_rutas_impresoras.get(topic)
        if impresora_info:
            nombre_impresora = impresora_info['nombre']
            try:
                contenido_pdf_binario = base64.b64decode(message)
                exito = imprimir_pdf(contenido_pdf_binario, nombre_impresora)
                if exito:
                    print(f"PDF impreso en {nombre_impresora}")
                else:
                    print(f"Error imprimiendo PDF en {nombre_impresora}")
            except Exception as e:
                print(f"Error al decodificar PDF: {e}")
    
    def subscribe_to_topics(self):
        topics = []
        for ruta in self.mapa_rutas_impresoras.keys():
            topics.append((ruta, 0))
        
        for topic, qos in topics:
            self.client.subscribe(topic, qos)
            print(f"Suscrito a: {topic}")

    def on_message(self, client, userdata, msg):
        topic = msg.topic
        message = msg.payload.decode('utf-8')
        
        impresora_info = self.mapa_rutas_impresoras.get(topic)
        if impresora_info:
            formato = impresora_info['formato']
            if formato == "TSPL":
                self.funcion_impresion_tspl(topic, message)
            elif formato == "PDF":
                self.funcion_impresion_pdf(topic, message)
            else:
                print(f"Formato no reconocido: {formato}")
        else:
            print(f"Topic no configurado: {topic}")
                        

    def connect_and_listen(self):
        try:
            self.client.connect(self.broker_host, self.broker_port, 60)
            print("Iniciar escucha...")
            self.client.loop_forever()
        except KeyboardInterrupt:
            print("\nDetenido por el usuario")
        except Exception as e:
            print(f"Error: {e}")
        finally:
            self.client.disconnect()

subscriber = MQTTSubscriber()
subscriber.connect_and_listen()