#include "privilege_helper.h"

#include <pwd.h>
#include <grp.h>
#include <unistd.h>

#include <vector>

static bool isUserInGroup(const QString& username, const QString& groupName) {
    if (username.isEmpty() || groupName.isEmpty()) return false;

    const QByteArray userBytes = username.toLocal8Bit();
    struct passwd* pw = getpwnam(userBytes.constData());
    if (!pw) return false;

    // Primary group id match
    struct group* primary = getgrgid(pw->pw_gid);
    if (primary && primary->gr_name && groupName == QString::fromLocal8Bit(primary->gr_name)) {
        return true;
    }

    // Supplementary groups
    int ngroups = 0;
    // getgrouplist requires an initial call to learn size
    getgrouplist(userBytes.constData(), pw->pw_gid, nullptr, &ngroups);
    if (ngroups <= 0) return false;

    std::vector<gid_t> groups(static_cast<size_t>(ngroups));
    if (getgrouplist(userBytes.constData(), pw->pw_gid, groups.data(), &ngroups) < 0) {
        return false;
    }

    for (int i = 0; i < ngroups; ++i) {
        struct group* gr = getgrgid(groups[static_cast<size_t>(i)]);
        if (gr && gr->gr_name && groupName == QString::fromLocal8Bit(gr->gr_name)) {
            return true;
        }
    }

    return false;
}

bool PrivilegeHelper::isAdminUser(const QString& username) {
    if (username.isEmpty()) return false;

    const QByteArray userBytes = username.toLocal8Bit();
    struct passwd* pw = getpwnam(userBytes.constData());
    if (pw && pw->pw_uid == 0) return true;

    return isUserInGroup(username, QStringLiteral("sudo"));
}
