#pragma once

#include "protocol.h"
#include "ring_buffer.h"
#include <atomic>
#include <memory>
#include <string>
#include <thread>
#include <vector>

/**
 * One UDP ingest channel — dedicated thread receiving samples and writing
 * them into a lock-free ring buffer without heap allocation after init.
 */
class UDPReceiver {
public:
    struct Stats {
        uint64_t datagrams_rx  = 0;
        uint64_t bytes_rx      = 0;
        uint64_t seq_gaps      = 0;
        uint64_t overflows     = 0;
        bool     connected     = false;
    };

    using RingBuf = SPSCRingBuffer<float>;

    UDPReceiver(uint16_t port, const std::string& bind_addr,
                std::shared_ptr<RingBuf> fullrate,
                std::shared_ptr<RingBuf> overview);

    ~UDPReceiver();

    void start();
    void stop();
    Stats stats() const;

private:
    void run();

    uint16_t                 port_;
    std::string              bind_addr_;
    std::shared_ptr<RingBuf> fullrate_;
    std::shared_ptr<RingBuf> overview_;
    std::thread              thread_;
    std::atomic<bool>        running_{false};

    // Stats (written by ingest thread, read by main)
    std::atomic<uint64_t> rx_datagrams_{0};
    std::atomic<uint64_t> rx_bytes_{0};
    std::atomic<uint64_t> seq_gaps_{0};
    std::atomic<bool>     connected_{false};
};
