#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#include <sys/syscall.h>

#include "../random.h"

namespace netplus {

static bool try_getrandom(uint8_t* dst, size_t len) {
#if defined(__linux__) && defined(SYS_getrandom)
    size_t done = 0;
    while (done < len) {
        ssize_t r = syscall(SYS_getrandom, dst + done, len - done, 0);
        if (r > 0) { done += (size_t)r; continue; }
        if (r < 0 && errno == EINTR) continue;
        return false;
    }
    return true;
#elif defined(__APPLE__) || defined(__FreeBSD__)
    arc4random_buf(dst, len);
    return true;
#else
    (void)dst;
    (void)len;
    return false;
#endif
}

void fillRandomBytes(uint8_t* dst, size_t len) {
    if (!dst || len == 0) return;

    // 1) try getrandom first
    if (try_getrandom(dst, len)) return;

    // 2) fallback /dev/urandom
    int fd = ::open("/dev/urandom", O_RDONLY);
    if (fd < 0) throw std::runtime_error("open(/dev/urandom) failed");

    size_t done = 0;
    while (done < len) {
        ssize_t r = ::read(fd, dst + done, len - done);
        if (r > 0) { done += (size_t)r; continue; }
        if (r < 0 && errno == EINTR) continue;
        ::close(fd);
        throw std::runtime_error("read(/dev/urandom) failed");
    }
    ::close(fd);
}

} // namespace netplus


