/**
 * @file main.cpp
 * @brief Demostración de integración autónoma en lazo cerrado utilizando el SDK C++ de NumChat.
 */

#include "numchat_sdk.h"
#include <iostream>
#include <cassert>
#include <iomanip>

// ── MOCKS DE ACTUADORES FÍSICOS (INTEGRACIÓN M2M REAL) ──────────────────

// Representa el actuador de energía de una pantalla LED o máquina minera
void set_cabinet_power_state(uint16_t node_id, bool active) {
    std::cout << "[ACTUADOR FÍSICO] " 
              << (active ? "ENCENDIENDO" : "APAGANDO INMEDIATAMENTE") 
              << " alimentación eléctrica del Gabinete/Nodo ID: " << node_id 
              << " por protección térmica/cortocircuito.\n";
}

// Representa el actuador de evacuación de emergencia civil en DOOH
void trigger_dooh_evacuation_alert(bool active) {
    std::cout << "[ACTUADOR FÍSICO] "
              << (active ? "ACTIVANDO MODO EVACUACIÓN GLOBAL." : "DESACTIVANDO ALERTA.")
              << " Interrumpiendo señal de vídeo principal. Mostrando mapa de evacuación en pantalla.\n";
}

// Representa el regulador de brillo LED para mitigación automática
void set_cabinet_brightness(uint16_t node_id, uint8_t level_percent) {
    std::cout << "[ACTUADOR FÍSICO] Ajustando brillo del Gabinete ID: " << node_id 
              << " al " << static_cast<int>(level_percent) << "% para reducir temperatura.\n";
}


// ── MAIN: EJECUCIÓN AUTÓNOMA DE LAZO CERRADO ───────────────────────────

int main() {
    std::cout << "============================================================\n";
    std::cout << "   DEMOSTRACIÓN DE CONTROL AUTÓNOMO M2M - PROTOCOLO NUMCHAT \n";
    std::cout << "============================================================\n\n";

    // 1. Inicializar el motor receptor de NumChat con la semilla criptográfica acordada
    uint32_t shared_cryptographic_seed = 0x5EEDCAFE;
    NumChat::ReceiverEngine receiver(shared_cryptographic_seed);

    // 2. REGISTRAR REGLAS DE RESPUESTA AUTÓNOMA SIN INTERVENCIÓN HUMANA
    std::cout << "[CONFIG] Registrando callbacks de eventos en lazo cerrado...\n";

    // Regla para Sobrecalentamiento de Gabinete (Código 2010): Mitigar reduciendo brillo
    receiver.on_code(2010, [](const NumChat::DecodedFrame& frame) {
        std::cout << "\n>> [REGLA DE SOFTWARE] Alarma 2010: Sobrecalentamiento en Gabinete " << frame.node_id << ".\n";
        // El valor de telemetría (0-63) mapea de 20 °C a 83 °C. Recuperamos los grados reales.
        int celsius = 20 + frame.telemetry_value;
        std::cout << "   Lectura de Temperatura: " << celsius << " C (Valor de Telemetría: " 
                  << static_cast<int>(frame.telemetry_value) << ")\n";

        if (celsius >= 75) {
            std::cout << "   [Lógica] Temperatura critica (>=75C). Ejecutando accion física...\n";
            set_cabinet_brightness(frame.node_id, 30); // Bajar brillo al 30% automáticamente
        } else {
            std::cout << "   [Lógica] Temperatura elevada pero bajo control. Mitigando levemente...\n";
            set_cabinet_brightness(frame.node_id, 70); // Bajar brillo al 70% de forma preventiva
        }
    });

    // Regla para Cortocircuito / Fallo Eléctrico (Código 1020): Cortar alimentación para prevenir incendios
    receiver.on_code(1020, [](const NumChat::DecodedFrame& frame) {
        std::cout << "\n>> [REGLA DE SOFTWARE] Alarma Crítica 1020: Cortocircuito detectado en Gabinete " << frame.node_id << ".\n";
        std::cout << "   [Lógica] Desconectando energía eléctrica de forma inmediata sin intervención humana...\n";
        set_cabinet_power_state(frame.node_id, false);
    });

    // Regla global para cualquier comando con prioridad Failsafe / Emergencia (Prioridad 11)
    receiver.on_priority(NumChat::PriorityLevel::Failsafe, [](const NumChat::DecodedFrame& frame) {
        std::cout << "\n>> [REGLA GLOBAL] DETECTADO COMANDO FAILSAFE DE ALTA PRIORIDAD (11).\n";
        if (frame.cartridge_code == 5020) { // Código 5020: Forzar modo Evacuación
            std::cout << "   Código Semántico: 5020 (Evacuación de Emergencia DOOH).\n";
            trigger_dooh_evacuation_alert(true);
        }
    });

    // Callback por defecto para fines informativos / logs
    receiver.on_default([](const NumChat::DecodedFrame& frame) {
        std::cout << "\n[LOG DE RUTINA] Recibido reporte del Gabinete ID " << frame.node_id 
                  << " | Código Semántico: " << frame.cartridge_code 
                  << " | Telemetría: " << static_cast<int>(frame.telemetry_value) << "\n";
    });


    // ── SIMULACIÓN DE RECEPCIÓN DE RÁFAGAS CIFRADAS EN DIRECTO ──────────

    // Simulador de emisor (utiliza la misma semilla rotativa compartida para cifrar)
    uint32_t sender_seed = shared_cryptographic_seed;
    auto encrypt_frame = [&sender_seed](uint32_t plain_frame) -> uint32_t {
        uint32_t encrypted = plain_frame ^ sender_seed;
        // Rotar semilla de transmisión
        sender_seed = (sender_seed * 1103515245 + 12345) & 0x7FFFFFFF;
        return encrypted;
    };

    std::cout << "\n[SIMULACIÓN] Iniciando recepción de ráfagas en vivo...\n";

    // --- ESCENARIO 1: Reporte cíclico de rutina de temperatura estable ---
    // Trama construida manualmente:
    // Prioridad: 00 (Routine)
    // Código Cartucho: 2010 (Sobrecalentamiento/Monitoreo Térmico)
    // ID Gabinete: Columna 4, Fila 2 -> 00100 (4) + 00010 (2) = Node ID: 130
    // Telemetría: 35 (Equivale a 20 + 35 = 55 °C)
    // Binario esperado: Prioridad(2b) | Código(14b) | Nodo(10b) | Telemetría(6b)
    // 00 | 00 0111 1101 1010 | 00 1000 0010 | 10 0011
    uint32_t plain_frame1 = (0x00ULL << 30) | (2010ULL << 16) | (130ULL << 6) | 35ULL;
    uint32_t encrypted_frame1 = encrypt_frame(plain_frame1);

    std::cout << "\n--- Ráfaga 1 Recibida (Física: 4 bytes cifrados: 0x" << std::hex << encrypted_frame1 << std::dec << ") ---";
    receiver.process_incoming_burst(encrypted_frame1);

    // --- ESCENARIO 2: Emergencia por sobrecalentamiento crítico (75 °C) ---
    // Mismo gabinete (ID 130), temperatura sube a 75 °C (Valor telemetría: 55)
    // Prioridad: 01 (Warning)
    uint32_t plain_frame2 = (0x01ULL << 30) | (2010ULL << 16) | (130ULL << 6) | 55ULL;
    uint32_t encrypted_frame2 = encrypt_frame(plain_frame2);

    std::cout << "\n--- Ráfaga 2 Recibida (Física: 4 bytes cifrados: 0x" << std::hex << encrypted_frame2 << std::dec << ") ---";
    receiver.process_incoming_burst(encrypted_frame2);

    // --- ESCENARIO 3: Cortocircuito crítico en gabinete ---
    // Gabinete ID: 45
    // Prioridad: 10 (Critical)
    // Código Cartucho: 1020 (Cortocircuito)
    // Telemetría: 0 (No aplicable)
    uint32_t plain_frame3 = (0x02ULL << 30) | (1020ULL << 16) | (45ULL << 6) | 0ULL;
    uint32_t encrypted_frame3 = encrypt_frame(plain_frame3);

    std::cout << "\n--- Ráfaga 3 Recibida (Física: 4 bytes cifrados: 0x" << std::hex << encrypted_frame3 << std::dec << ") ---";
    receiver.process_incoming_burst(encrypted_frame3);

    // --- ESCENARIO 4: Comando global de evacuación (Failsafe DOOH / Emergencia Civil) ---
    // Afecta a todos los gabinetes (ID de Broadcast: 1023)
    // Prioridad: 11 (Failsafe)
    // Código Cartucho: 5020 (Forzar modo Evacuación)
    // Telemetría: 0
    uint32_t plain_frame4 = (0x03ULL << 30) | (5020ULL << 16) | (1023ULL << 6) | 0ULL;
    uint32_t encrypted_frame4 = encrypt_frame(plain_frame4);

    std::cout << "\n--- Ráfaga 4 Recibida (Física: 4 bytes cifrados: 0x" << std::hex << encrypted_frame4 << std::dec << ") ---";
    receiver.process_incoming_burst(encrypted_frame4);

    std::cout << "\n============================================================\n";
    std::cout << "   DEMOSTRACIÓN FINALIZADA CON ÉXITO - 100% AUTOMATIZADO \n";
    std::cout << "============================================================\n";

    return 0;
}