#include "utils.h"
#include <QDateTime>
#include <QElapsedTimer>
#include <time.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <netinet/in.h>

Utils::Utils(QObject *parent)
    : QObject{parent}
{

}

QString Utils::timestamp()
{
    return QString("%1").arg(QDateTime::currentMSecsSinceEpoch());
}

qint64 Utils::currentNanoTimestamp()
{
#if 0
    static QElapsedTimer timer;
    static qint64 baseNano = 0;
    static bool initialized = false;

    if (!initialized) {
        // 当前毫秒时间戳 → 转成纳秒
        baseNano = QDateTime::currentMSecsSinceEpoch() * 1000000LL;

        // 启动高精度计时器
        timer.start();
        initialized = true;
    }

    // 当前 epoch 纳秒时间戳 = 基准时间 + 已经过的纳秒
    return baseNano + timer.nsecsElapsed();
#endif

    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    qint64 timestamp = ts.tv_sec * 1000000000LL + ts.tv_nsec;
    return timestamp;
}

bool Utils::ipv4(const char *ifname, char **ip_str, char **mask_str)
{
    struct ifaddrs *ifaddr, *ifa;
    char ip[INET_ADDRSTRLEN] = {0};
    char mask[INET_ADDRSTRLEN] = {0};

    if (getifaddrs(&ifaddr) == -1) {
        perror("getifaddrs");
        return NULL;
    }

    // char *addr = NULL;
    // char *mask = NULL;
    // QString ipv4;

    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        if (!ifa->ifa_addr)
            continue;

        if (strcmp(ifa->ifa_name, ifname) != 0)
            continue;

        if (ifa->ifa_addr->sa_family == AF_INET) {
            struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr;
            struct sockaddr_in *netmask = (struct sockaddr_in *)ifa->ifa_netmask;
            if (inet_ntop(AF_INET, &addr->sin_addr, ip, sizeof(ip)) &&
                inet_ntop(AF_INET, &netmask->sin_addr, mask, sizeof(mask))) {
                *ip_str = strdup(ip);
                *mask_str = strdup(mask);
                // ipv4 = QString("%1/%2").arg(ip, mask);
                return true; // IPv4 一般只有一个
            }
        }
    }

    freeifaddrs(ifaddr);
    // free(result);
    return false;
}

QString Utils::broadcast(const char *ip_str, const char *mask_str)
{
    struct in_addr ip, mask, broadcast;

    inet_pton(AF_INET, ip_str, &ip);
    inet_pton(AF_INET, mask_str, &mask);

    broadcast.s_addr = ip.s_addr | ~mask.s_addr;
    char broadcast_str[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &broadcast, broadcast_str, INET_ADDRSTRLEN);

    return QString("%1").arg(broadcast_str);
}
