#include "config.hpp"
#include "lorahandler.hpp"
#include "logger.h"
#include "pins.hpp"

extern logging::Logger logger;
extern Config config;

LoraHandler::LoraHandler() {
    // Initialize with new SX1268 radio
}

void LoraHandler::setup()
{
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "Initializing SX1268 with RadioLib!");
    
    // Create new SPI instance for LoRa
    spi = new SPIClass(VSPI);
    spi->begin(RADIO_SCK, RADIO_MISO, RADIO_MOSI, RADIO_CS);
    
    // Create SX1268 instance
    radio = new SX1268(new SPIDriver(spi, RADIO_CS));
    
    // Configure RXEN/TXEN pins
    pinMode(RADIO_RXEN, OUTPUT);
    pinMode(RADIO_TXEN, OUTPUT);
    digitalWrite(RADIO_RXEN, LOW);
    digitalWrite(RADIO_TXEN, LOW);
    
    // Initialize LoRa module
    int state = radio->begin();
    if (state != RADIOLIB_ERR_NONE)
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "LoRa init failed: %i", state);
        while (true) {
            delay(1000);
        }
    }
    
    // Configure LoRa parameters
    long freq = config.loraConfig.frequency;
    state = radio->setFrequency(freq);
    if (state != RADIOLIB_ERR_NONE)
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "setFrequency failed: %i", state);
    }
    
    state = radio->setSpreadingFactor(config.loraConfig.spreadingFactor);
    if (state != RADIOLIB_ERR_NONE)
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "setSpreadingFactor failed: %i", state);
    }
    
    state = radio->setBandwidth(config.loraConfig.signalBandwidth);
    if (state != RADIOLIB_ERR_NONE)
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "setBandwidth failed: %i", state);
    }
    
    state = radio->setCodingRate(config.loraConfig.codingRate4);
    if (state != RADIOLIB_ERR_NONE)
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "setCodingRate failed: %i", state);
    }
    
    state = radio->setOutputPower(config.loraConfig.power);
    if (state != RADIOLIB_ERR_NONE)
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa", "setOutputPower failed: %i", state);
    }
    
    // Enable CRC
    radio->setCRC(true);
    
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", "SX1268 initialized successfully!");
    String currentLoRainfo = "LoRa Freq: " + String(freq) + " / SF:" + String(config.loraConfig.spreadingFactor) + " / CR: " + String(config.loraConfig.codingRate4);
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", currentLoRainfo.c_str());
}

void LoraHandler::sendPacket(const String& data)
{
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa Tx", "Sending: %s", data.c_str());
    
    // Enable TX mode
    digitalWrite(RADIO_TXEN, HIGH);
    digitalWrite(RADIO_RXEN, LOW);
    delay(10);
    
    int state = radio->transmit(data);
    
    // Disable TX mode
    digitalWrite(RADIO_TXEN, LOW);
    
    if (state != RADIOLIB_ERR_NONE)
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa Tx", "Transmit failed: %i", state);
    }
    else
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa Tx", "Packet sent!");
    }
}

ReceivedLoRaPacket LoraHandler::receivePacket()
{
    ReceivedLoRaPacket receivedLoraPacket;
    
    // Enable RX mode
    digitalWrite(RADIO_RXEN, HIGH);
    digitalWrite(RADIO_TXEN, LOW);
    
    int state = radio->receive(0);  // 0 = non-blocking
    
    if (state == RADIOLIB_ERR_RX_ONGOING)
    {
        // No packet received yet
        return receivedLoraPacket;
    }
    else if (state == RADIOLIB_ERR_NONE)
    {
        // Packet received!
        receivedLoraPacket.text = radio->readData();
        receivedLoraPacket.rssi = radio->getRSSI();
        receivedLoraPacket.snr = radio->getSNR();
        receivedLoraPacket.freqError = radio->getFrequencyError();
        
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa Rx", "---> %s (RSSI: %d, SNR: %.1f)", 
                   receivedLoraPacket.text.c_str(), receivedLoraPacket.rssi, receivedLoraPacket.snr);
    }
    else
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "LoRa Rx", "Receive error: %i", state);
    }
    
    return receivedLoraPacket;
}