#pragma once

#include "dbus_utility.hpp"
#include "logging.hpp"
#include "utils/dbus_utils.hpp"

#include <boost/container/flat_map.hpp>
#include <boost/url/format.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/unpack_properties.hpp>

#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <variant>
#include <vector>

namespace crow
{
struct UserFields
{
    std::optional<std::string> userRole;
    std::optional<bool> remote;
    std::optional<bool> passwordExpired;
    std::optional<std::vector<std::string>> userGroups;
};

struct UserRoleMap
{
  public:
    static UserRoleMap& getInstance()
    {
        static UserRoleMap userRoleMap;
        return userRoleMap;
    }

    UserFields getUserRole(std::string_view name)
    {
        auto it = roleMap.find(name);
        if (it == roleMap.end())
        {
            BMCWEB_LOG_ERROR("User name {} is not found in the UserRoleMap.",
                             name);
            return {};
        }
        return it->second;
    }
    UserRoleMap(const UserRoleMap&) = delete;
    UserRoleMap& operator=(const UserRoleMap&) = delete;
    UserRoleMap(UserRoleMap&&) = delete;
    UserRoleMap& operator=(UserRoleMap&&) = delete;
    ~UserRoleMap() = default;

  private:
    static UserFields extractUserRole(
        const dbus::utility::DBusInteracesMap& interfacesProperties)
    {
        UserFields fields;
        for (const auto& interface : interfacesProperties)
        {
            for (const auto& property : interface.second)
            {
                if (property.first == "UserPrivilege")
                {
                    const std::string* role =
                        std::get_if<std::string>(&property.second);
                    if (role != nullptr)
                    {
                        fields.userRole = *role;
                    }
                }
                else if (property.first == "UserGroups")
                {
                    const std::vector<std::string>* groups =
                        std::get_if<std::vector<std::string>>(&property.second);
                    if (groups != nullptr)
                    {
                        fields.userGroups = *groups;
                    }
                }
                else if (property.first == "UserPasswordExpired")
                {
                    const bool* expired = std::get_if<bool>(&property.second);
                    if (expired != nullptr)
                    {
                        fields.passwordExpired = *expired;
                    }
                }
                else if (property.first == "RemoteUser")
                {
                    const bool* remote = std::get_if<bool>(&property.second);
                    if (remote != nullptr)
                    {
                        fields.remote = *remote;
                    }
                }
            }
        }
        return fields;
    }

    void userAdded(sdbusplus::message_t& m)
    {
        BMCWEB_LOG_DEBUG("User Added");
        sdbusplus::message::object_path objPath;
        dbus::utility::DBusInteracesMap interfacesProperties;

        try
        {
            m.read(objPath, interfacesProperties);
        }
        catch (const sdbusplus::exception::SdBusError& e)
        {
            BMCWEB_LOG_ERROR(
                "Failed to parse user add signal.ERROR={}REPLY_SIG={}",
                e.what(), m.get_signature());
            return;
        }
        BMCWEB_LOG_DEBUG("obj path = {}", objPath.str);

        std::string name = objPath.filename();
        if (name.empty())
        {
            return;
        }
        UserFields role = extractUserRole(interfacesProperties);

        // Insert the newly added user name and the role
        auto res = roleMap.emplace(name, role);
        if (!res.second)
        {
            BMCWEB_LOG_ERROR(
                "Insertion of the user=\"{}\" in the roleMap failed.", name);
            return;
        }
    }

    void userRemoved(sdbusplus::message_t& m)
    {
        BMCWEB_LOG_DEBUG("User Removed");
        sdbusplus::message::object_path objPath;

        try
        {
            m.read(objPath);
        }
        catch (const sdbusplus::exception::SdBusError& e)
        {
            BMCWEB_LOG_ERROR("Failed to parse user delete signal.");
            BMCWEB_LOG_ERROR("ERROR={}REPLY_SIG={}", e.what(),
                             m.get_signature());
            return;
        }

        BMCWEB_LOG_DEBUG("obj path = {}", objPath.str);

        std::string name = objPath.filename();
        if (name.empty())
        {
            return;
        }

        roleMap.erase(name);
    }

    void userPropertiesChanged(sdbusplus::message_t& m)
    {
        BMCWEB_LOG_DEBUG("Properties Changed");
        std::string interface;
        dbus::utility::DBusPropertiesMap changedProperties;
        try
        {
            m.read(interface, changedProperties);
        }
        catch (const sdbusplus::exception::SdBusError& e)
        {
            BMCWEB_LOG_ERROR("Failed to parse user properties changed signal.");
            BMCWEB_LOG_ERROR("ERROR={}REPLY_SIG={}", e.what(),
                             m.get_signature());
            return;
        }
        dbus::utility::DBusInteracesMap map;
        map.emplace_back("xyz.openbmc_project.User.Attributes",
                         changedProperties);
        const sdbusplus::message::object_path path(m.get_path());

        BMCWEB_LOG_DEBUG("Object Path = \"{}\"", path.str);

        std::string user = path.filename();
        if (user.empty())
        {
            return;
        }

        BMCWEB_LOG_DEBUG("User Name = \"{}\"", user);

        UserFields role = extractUserRole(map);

        auto userProps = roleMap.find(user);
        if (userProps == roleMap.end())
        {
            BMCWEB_LOG_CRITICAL("User {} not found", user);
            return;
        }
        if (role.userRole)
        {
            userProps->second.userRole = role.userRole;
        }
        if (role.remote)
        {
            userProps->second.remote = role.remote;
        }
        if (role.userGroups)
        {
            userProps->second.userGroups = role.userGroups;
        }
        if (role.passwordExpired)
        {
            userProps->second.passwordExpired = role.passwordExpired;
        }
    }

    void onGetManagedObjects(
        const boost::system::error_code& ec,
        const dbus::utility::ManagedObjectType& managedObjects)
    {
        if (ec)
        {
            BMCWEB_LOG_DEBUG("User manager call failed, ignoring");
            return;
        }

        for (const auto& managedObj : managedObjects)
        {
            std::string name =
                sdbusplus::message::object_path(managedObj.first).filename();
            if (name.empty())
            {
                continue;
            }
            UserFields role = extractUserRole(managedObj.second);
            roleMap.emplace(name, role);
        }
    }

    static constexpr const char* userObjPath = "/xyz/openbmc_project/user";

    UserRoleMap() :
        userAddedSignal(
            *crow::connections::systemBus,
            sdbusplus::bus::match::rules::interfacesAdded(userObjPath),
            std::bind_front(&UserRoleMap::userAdded, this)),
        userRemovedSignal(
            *crow::connections::systemBus,
            sdbusplus::bus::match::rules::interfacesRemoved(userObjPath),
            std::bind_front(&UserRoleMap::userRemoved, this)),
        userPropertiesChangedSignal(
            *crow::connections::systemBus,
            sdbusplus::bus::match::rules::propertiesChangedNamespace(
                userObjPath, "xyz.openbmc_project.User.Attributes"),
            std::bind_front(&UserRoleMap::userPropertiesChanged, this))
    {
        dbus::utility::getManagedObjects(
            "xyz.openbmc_project.User.Manager", {userObjPath},
            std::bind_front(&UserRoleMap::onGetManagedObjects, this));
    }

    // Map of username -> role
    boost::container::flat_map<std::string, UserFields, std::less<>> roleMap;

    // These MUST be last, otherwise destruction can cause race conditions.
    sdbusplus::bus::match_t userAddedSignal;
    sdbusplus::bus::match_t userRemovedSignal;
    sdbusplus::bus::match_t userPropertiesChangedSignal;
};

} // namespace crow
