#pragma once
#include <Arduino.h>
#include <RF24.h>

/// Роль модуля на радиоканале — одна труба используется либо на приём, либо на передачу.
enum class NrfRole : uint8_t {
    Transmitter,
    Receiver,
};

/**
 * @brief Демонстрационный пакет телеметрии.
 * 13 байт — далеко в пределах лимита payload в 32 байта (аппаратное
 * ограничение nRF24L01+, см. THEORY.md).
 */
struct TelemetryPacket {
    uint32_t sequence;   ///< номер пакета — по нему приёмник видит потери (разрывы в последовательности)
    uint32_t sentAtMs;   ///< millis() отправителя на момент отправки — для оценки задержки на приёмнике
    float payloadValue;  ///< демонстрационное значение полезной нагрузки (пример для будущих компонентов)
};

/**
 * @brief Прикладной радиомост поверх библиотеки RF24 для пары модулей nRF24L01+.
 *
 * RF24 уже сама по себе является низкоуровневым драйвером чипа (работа с
 * регистрами по SPI, Auto-ACK, повторные попытки) — этот класс не дублирует
 * её работу, а даёт прикладной протокол поверх неё: типизированные пакеты
 * телеметрии и статистику качества связи через успешность Auto-ACK.
 *
 * У nRF24L01+ нет измерения настоящего RSSI, поэтому "качество связи" здесь —
 * это доля успешных подтверждений (Auto-ACK), а не сила сигнала в дБм.
 */
class NrfLink {
public:
    /// Максимальный размер payload, аппаратное ограничение чипа nRF24L01+.
    static constexpr uint8_t kMaxPayloadBytes = 32;

    NrfLink(uint8_t cePin, uint8_t csnPin);

    /**
     * @brief Инициализирует SPI-соединение с чипом и настраивает радиоэфир.
     * @param role Transmitter открывает трубу на запись, Receiver — на чтение.
     * @param address 5-байтовый адрес трубы, общий для передатчика и приёмника.
     * @param channel Номер канала 0-125 (частота = 2400 + channel МГц).
     * @param dataRate Скорость эфира — ниже скорость, выше чувствительность/дальность.
     * @param paLevel Мощность усилителя передачи.
     * @return false, если чип не отвечает по SPI.
     */
    bool begin(NrfRole role, uint64_t address, uint8_t channel = 110,
               rf24_datarate_e dataRate = RF24_250KBPS,
               rf24_pa_dbm_e paLevel = RF24_PA_MIN);

    /**
     * @brief Отправляет пакет телеметрии (только для роли Transmitter).
     * @return false, если Auto-ACK не получен (пакет считается потерянным).
     */
    bool sendTelemetry(const TelemetryPacket& packet);

    /**
     * @brief Читает очередной пакет телеметрии, если он пришёл (только для роли Receiver).
     * @return false, если новых пакетов нет.
     */
    bool receiveTelemetry(TelemetryPacket& outPacket);

    /// Доля успешных ACK от общего числа отправленных пакетов, 0.0-1.0 (только Transmitter).
    float getAckSuccessRate() const;
    uint32_t getPacketsSent() const { return _packetsSent; }
    uint32_t getPacketsAcked() const { return _packetsAcked; }

    /// Прямая проверка присутствия чипа по SPI (не требует протокольного обмена телеметрией).
    bool isChipConnected() { return _radio.isChipConnected(); }

    /// Была ли недавняя активность на линии: успешная отправка (TX) или приём (RX).
    bool isAlive(unsigned long timeoutMs = 2000) const {
        return (millis() - _lastActivityMs) < timeoutMs;
    }

private:
    RF24 _radio;
    NrfRole _role = NrfRole::Transmitter;
    uint32_t _packetsSent = 0;
    uint32_t _packetsAcked = 0;
    unsigned long _lastActivityMs = 0;
};
