#ifndef THIRD_PARTY_GBMCWEB_INCLUDE_PAM_AUTHENTICATE_H_
#define THIRD_PARTY_GBMCWEB_INCLUDE_PAM_AUTHENTICATE_H_

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

#include <cstdlib>
#include <cstring>
#include <string>
#include <string_view>

#include "boost/utility/string_view.hpp"  // NOLINT

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

  if (numMsg <= 0 || numMsg >= PAM_MAX_NUM_MSG) {
    return PAM_CONV_ERR;
  }

  for (int i = 0; i < numMsg; ++i) {
    /* Ignore all PAM messages except prompting for hidden input */
    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) {
      continue;
    }

    /* Assume PAM is only prompting for the password as hidden input */
    /* Allocate memory only when PAM_PROMPT_ECHO_OFF is encountered */

    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    char* app_pass = reinterpret_cast<char*>(appdataPtr);
    size_t app_pass_size = std::strlen(app_pass);

    if ((app_pass_size + 1) > PAM_MAX_RESP_SIZE) {
      return PAM_CONV_ERR;
    }
    // IDeally we'd like to avoid using malloc here, but because we're
    // passing off ownership of this to a C application, there aren't a lot
    // of sane ways to avoid it.

    // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)'
    void* pass_ptr = malloc(app_pass_size + 1);
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    char* pass = reinterpret_cast<char*>(pass_ptr);
    if (pass == nullptr) {
      return PAM_BUF_ERR;
    }

    std::strncpy(pass, app_pass, app_pass_size + 1);

    size_t num_msg_size = static_cast<size_t>(numMsg);
    // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
    void* ptr = calloc(num_msg_size, sizeof(struct pam_response));
    if (ptr == nullptr) {
      // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
      free(pass);
      return PAM_BUF_ERR;
    }

    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    *resp = reinterpret_cast<pam_response*>(ptr);

    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    resp[i]->resp = pass;

    return PAM_SUCCESS;
  }

  return PAM_CONV_ERR;
}

/**
 * @brief Attempt username/password authentication via PAM.
 * @param username The provided username aka account name.
 * @param password The provided password.
 * @returns PAM error code or PAM_SUCCESS for success. */
inline int pamAuthenticateUser(std::string_view username,
                               std::string_view password) {
  std::string user_str(username);
  std::string pass_str(password);

  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
  char* pass_str_no_const = const_cast<char*>(pass_str.c_str());
  const struct pam_conv local_conversation = {pamFunctionConversation,
                                              pass_str_no_const};
  pam_handle_t* local_auth_handle = nullptr;  // this gets set by pam_start

  int retval = pam_start("webserver", user_str.c_str(), &local_conversation,
                         &local_auth_handle);
  if (retval != PAM_SUCCESS) {
    return retval;
  }

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

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

  return pam_end(local_auth_handle, PAM_SUCCESS);
}

inline int pamUpdatePassword(const std::string& username,
                             const std::string& password) {
  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
  char* pass_str_no_const = const_cast<char*>(password.c_str());
  const struct pam_conv local_conversation = {pamFunctionConversation,
                                              pass_str_no_const};
  pam_handle_t* local_auth_handle = nullptr;  // this gets set by pam_start

  int retval = pam_start("webserver", username.c_str(), &local_conversation,
                         &local_auth_handle);

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

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

  return pam_end(local_auth_handle, PAM_SUCCESS);
}

#endif  // THIRD_PARTY_GBMCWEB_INCLUDE_PAM_AUTHENTICATE_H_
