#!/usr/bin/env python3
import json
import os
import sys
import threading
import time
import subprocess
from datetime import datetime
from mesh_mensaje_clase import Ruta_Mensajes
from mesh_registra_clase import RegistradorMensajes

# === CONFIGURACIÓN MQTT ===
with open('mensa-config.json', 'r', encoding='utf-8') as f:
    config_data = json.load(f)
CONFIG_MQTT = config_data['CONFIG']

# Instancia del registrador de base de datos
registrador = RegistradorMensajes()

# === CALLBACKS ===
def callback_posicion(datos):
    nombre_corto = datos.get('nombre_corto', datos['id_nodo'][-4:].upper())
    print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 📍 NUEVA POSICIÓN")
    print(f"    🆔 ID Nodo: {datos['id_nodo']} ({nombre_corto})")
    print(f"    📡 Canal: {datos['canal_nombre']}")
    print(f"    🌍 Coordenadas: Lat {datos['latitud']:.6f}, Lon {datos['longitud']:.6f}")
    print(f"    ⛰️  Altitud: {datos.get('altitud', 0)} metros")
    if 'fecha_gps' in datos and datos['fecha_gps']:
        print(f"    🕒 Hora GPS: {datos['fecha_gps']}")
    print(f"    📶 Satélites: {datos.get('satelites', 0)} | Velocidad: {datos.get('velocidad', 0)} m/s")
    print("-" * 60)
    registrador.registrar_posicion(datos)

def callback_telemetria(datos):
    nombre_corto = datos.get('nombre_corto', datos['id_nodo'][-4:].upper())
    bateria = datos.get('bateria', 'N/A')
    voltaje = datos.get('voltaje', 'N/A')
    uso_canal = datos.get('uso_canal', 'N/A')
    transmision = datos.get('transmision', 'N/A')
    temp = datos.get('temperatura', None)
    hum = datos.get('humedad', None)
    pres = datos.get('presion', None)

    print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 📊 NUEVA TELEMETRÍA")
    print(f"    🆔 Nodo: {datos['id_nodo']} ({nombre_corto}) | Canal: {datos['canal_nombre']}")
    print(f"    🔋 Batería: {bateria}% | ⚡ Voltaje: {voltaje}V")
    print(f"    📡 Utilización canal: {uso_canal}% | TX: {transmision}%")
    if temp is not None or hum is not None or pres is not None:
        print(f"    🌡️  Temperatura: {temp}°C | Humedad: {hum}% | Presión: {pres} hPa")
    print("-" * 60)
    registrador.registrar_telemetria(datos)

def callback_usuario(datos):
    nombre_corto = datos.get('nombre_corto', datos['id_nodo'][-4:].upper())
    print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 👤 NUEVO USUARIO/NODO")
    print(f"    🆔 ID: {datos['id_nodo']}")
    print(f"    📛 Nombre: {datos.get('nombre_largo', 'Sin nombre')} ({nombre_corto})")
    print(f"    🖥️  HW: {datos.get('modelo', 'Desconocido')} | 📄 Rol: {datos.get('rol', 'Desconocido')}")
    print("-" * 60)
    registrador.registrar_usuario(datos)

def callback_texto(datos):
    nombre_corto = datos.get('nombre_corto', datos['id_nodo'][-4:].upper())
    destino = "Broadcast" if datos['id_recep'] == "!ffffffff" else datos['id_recep']
    print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 💬 NUEVO MENSAJE DE TEXTO")
    print(f"    🆔 De: {datos['id_nodo']} ({nombre_corto})")
    print(f"    📥 Para: {destino}")
    print(f"    📡 Canal: {datos['canal_nombre']}")
    print(f"    📝 Texto: \"{datos['texto']}\"")
    print("-" * 60)
    registrador.registrar_texto(datos)

# === FUNCIÓN: EJECUTAR subir_datos.py CADA 30 MINUTOS ===
def tarea_periodica_subir_datos():
    ruta_subir_datos = os.path.join(os.path.dirname(__file__), "mesh_subir_datos.py")
    while True:
        try:
            print("\n🕒 Ejecutando subir_datos.py como proceso externo...")
            result = subprocess.run(
                [sys.executable, ruta_subir_datos],
                capture_output=True,
                text=True,
                cwd=os.path.dirname(__file__)
            )
            if result.returncode == 0:
                print("✅ subir_datos.py finalizó correctamente.")
            else:
                print(f"❌ mesh_subir_datos.py falló. Código: {result.returncode}")
                if result.stdout.strip():
                    print("   STDOUT:", result.stdout.strip())
                if result.stderr.strip():
                    print("   STDERR:", result.stderr.strip())
        except Exception as e:
            print(f"⚠️ Error al ejecutar mesh_subir_datos.py: {e}")
        print("⏳ Esperando 30 minutos para la próxima ejecución...")
        time.sleep(30 * 60)  # 1800 segundos

# === FUNCIÓN PRINCIPAL ===
def main():
    print("🚀 Iniciando receptor de mensajes Meshtastic...")
    print(f"📡 Broker: {CONFIG_MQTT['broker']}:{CONFIG_MQTT['puerto']}")
    print("💾 Guardando en base de datos + subiendo nodos.json cada 30 min...")
    print("-" * 60)

    # Iniciar hilo para ejecutar subir_datos.py periódicamente
    hilo_subida = threading.Thread(target=tarea_periodica_subir_datos, daemon=True)
    hilo_subida.start()

    # Configurar y conectar el router de mensajes
    router = Ruta_Mensajes(
        topico_base=CONFIG_MQTT['topico_base'],
        callback_crudo=None,
        callback_posicion=callback_posicion,
        callback_telemetria=callback_telemetria,
        callback_usuario=callback_usuario,
        callback_texto=callback_texto
    )

    try:
        router.conectar(CONFIG_MQTT)
    except KeyboardInterrupt:
        print("\n🛑 Detenido por el usuario.")
    except Exception as e:
        print(f"❌ Error crítico: {e}")
    finally:
        registrador.cerrar()

if __name__ == "__main__":
    main()