// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
#pragma once

#include "logging.hpp"

#include <security/_pam_types.h>
#include <security/pam_appl.h>

#include <algorithm>
#include <cstddef>
#include <cstring>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <vector>

struct PasswordData
{
    struct Response
    {
        std::string_view prompt;
        std::string value;
    };

    std::vector<Response> responseData;

    int addPrompt(std::string_view prompt, std::string_view value)
    {
        if (value.size() + 1 > PAM_MAX_MSG_SIZE)
        {
            BMCWEB_LOG_ERROR("value length error", prompt);
            return PAM_CONV_ERR;
        }
        responseData.emplace_back(prompt, std::string(value));
        return PAM_SUCCESS;
    }

    int makeResponse(const pam_message& msg, pam_response& response)
    {
        switch (msg.msg_style)
        {
            case PAM_PROMPT_ECHO_ON:
                break;
            case PAM_PROMPT_ECHO_OFF:
            {
                std::string prompt(msg.msg);
                auto iter = std::ranges::find_if(
                    responseData, [&prompt](const Response& data) {
                        return prompt.starts_with(data.prompt);
                    });
                if (iter == responseData.end())
                {
                    return PAM_CONV_ERR;
                }
                // NOLINTNEXTLINE(misc-include-cleaner)
                response.resp = strdup(iter->value.c_str());
                return PAM_SUCCESS;
            }
            break;
            case PAM_ERROR_MSG:
            {
                BMCWEB_LOG_ERROR("Pam error {}", msg.msg);
            }
            break;
            case PAM_TEXT_INFO:
            {
                BMCWEB_LOG_ERROR("Pam info {}", msg.msg);
            }
            break;
            default:
            {
                return PAM_CONV_ERR;
            }
        }
        return PAM_SUCCESS;
    }
};

// function used to get user input
inline int pamFunctionConversation(int numMsg, const struct pam_message** msgs,
                                   struct pam_response** resp, void* appdataPtr)
{
    if ((appdataPtr == nullptr) || (msgs == nullptr) || (resp == nullptr))
    {
        return PAM_CONV_ERR;
    }

    if (numMsg <= 0 || numMsg >= PAM_MAX_NUM_MSG)
    {
        return PAM_CONV_ERR;
    }
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    PasswordData* appPass = reinterpret_cast<PasswordData*>(appdataPtr);
    auto msgCount = static_cast<size_t>(numMsg);
    // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
    auto responseArrPtr = std::make_unique<pam_response[]>(msgCount);
    auto responses = std::span(responseArrPtr.get(), msgCount);
    auto messagePtrs = std::span(msgs, msgCount);
    for (size_t i = 0; i < msgCount; ++i)
    {
        const pam_message& msg = *(messagePtrs[i]);

        pam_response& response = responses[i];
        response.resp_retcode = 0;
        response.resp = nullptr;

        int r = appPass->makeResponse(msg, response);
        if (r != PAM_SUCCESS)
        {
            return r;
        }
    }

    *resp = responseArrPtr.release();
    return PAM_SUCCESS;
}

/**
 * @brief Attempt username/password authentication via PAM.
 * @param username The provided username aka account name.
 * @param password The provided password.
 * @param token The provided MFA token.
 * @returns PAM error code or PAM_SUCCESS for success. */
inline int pamAuthenticateUser(std::string_view username,
                               std::string_view password,
                               std::optional<std::string> token)
{
    std::string userStr(username);
    PasswordData data;
    if (int ret = data.addPrompt("Password: ", password); ret != PAM_SUCCESS)
    {
        return ret;
    }
    if (token)
    {
        if (int ret = data.addPrompt("Verification code: ", *token);
            ret != PAM_SUCCESS)
        {
            return ret;
        }
    }

    const struct pam_conv localConversation = {pamFunctionConversation, &data};
    pam_handle_t* localAuthHandle = nullptr; // this gets set by pam_start

    int retval = pam_start("webserver", userStr.c_str(), &localConversation,
                           &localAuthHandle);
    if (retval != PAM_SUCCESS)
    {
        return retval;
    }

    retval = pam_authenticate(localAuthHandle,
                              PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
    if (retval != PAM_SUCCESS)
    {
        pam_end(localAuthHandle, PAM_SUCCESS); // ignore retval
        return retval;
    }

    /* check that the account is healthy */
    retval = pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK);
    if (retval != PAM_SUCCESS)
    {
        pam_end(localAuthHandle, PAM_SUCCESS); // ignore retval
        return retval;
    }

    return pam_end(localAuthHandle, PAM_SUCCESS);
}

inline int pamUpdatePassword(const std::string& username,
                             const std::string& password)
{
    PasswordData data;
    if (int ret = data.addPrompt("New password: ", password);
        ret != PAM_SUCCESS)
    {
        return ret;
    }
    if (int ret = data.addPrompt("Retype new password: ", password);
        ret != PAM_SUCCESS)
    {
        return ret;
    }
    const struct pam_conv localConversation = {pamFunctionConversation, &data};
    pam_handle_t* localAuthHandle = nullptr; // this gets set by pam_start

    int retval = pam_start("webserver", username.c_str(), &localConversation,
                           &localAuthHandle);

    if (retval != PAM_SUCCESS)
    {
        return retval;
    }

    retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
    if (retval != PAM_SUCCESS)
    {
        pam_end(localAuthHandle, PAM_SUCCESS);
        return retval;
    }

    return pam_end(localAuthHandle, PAM_SUCCESS);
}
