#ifndef THIRD_PARTY_GBMCWEB_HTTP_MUTUAL_TLS_H_
#define THIRD_PARTY_GBMCWEB_HTTP_MUTUAL_TLS_H_

#ifdef GOOGLE3_GBMCWEB_BUILD
#include <openssl/asn1.h>
#include <openssl/nid.h>
#include <openssl/obj.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#endif

#include <openssl/crypto.h>
#include <openssl/ssl.h>

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>

#include "boost/asio/ip/address.hpp"  // NOLINT
#include "boost/asio/ssl/verify_context.hpp"  // NOLINT
#include "logging.hpp"
#include "sessions.hpp"

inline std::shared_ptr<persistent_data::UserSession> verifyMtlsUser(
    const boost::asio::ip::address& clientIp,
    boost::asio::ssl::verify_context& ctx) {
  // do nothing if TLS is disabled
  if (!persistent_data::SessionStore::getInstance()
           .getAuthMethodsConfig()
           .tls) {
    BMCWEB_LOG_DEBUG << "TLS auth_config is disabled";
    return nullptr;
  }

  X509_STORE_CTX* cts = ctx.native_handle();
  if (cts == nullptr) {
    BMCWEB_LOG_DEBUG << "Cannot get native TLS handle.";
    return nullptr;
  }

  // Get certificate
  X509* peer_cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
  if (peer_cert == nullptr) {
    BMCWEB_LOG_DEBUG << "Cannot get current TLS certificate.";
    return nullptr;
  }

  // Check if certificate is OK
  int ctx_error = X509_STORE_CTX_get_error(cts);
  if (ctx_error != X509_V_OK) {
    BMCWEB_LOG_INFO << "Last TLS error is: " << ctx_error;
    return nullptr;
  }
  // Check that we have reached final certificate in chain
  int32_t depth = X509_STORE_CTX_get_error_depth(cts);
  if (depth != 0) {
    BMCWEB_LOG_DEBUG << "Certificate verification in progress (depth " << depth
                     << "), waiting to reach final depth";
    return nullptr;
  }

  BMCWEB_LOG_DEBUG << "Certificate verification of final depth";

  // Verify KeyUsage
  bool is_key_usage_digital_signature = false;
  bool is_key_usage_key_agreement = false;

  ASN1_BIT_STRING* usage = static_cast<ASN1_BIT_STRING*>(
      X509_get_ext_d2i(peer_cert, NID_key_usage, nullptr, nullptr));

  if (usage == nullptr) {
    BMCWEB_LOG_DEBUG << "TLS usage is null";
    return nullptr;
  }

  for (int i = 0; i < usage->length; i++) {
    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    unsigned char usage_char = usage->data[i];
    if (KU_DIGITAL_SIGNATURE & usage_char) {
      is_key_usage_digital_signature = true;
    }
    if (KU_KEY_AGREEMENT & usage_char) {
      is_key_usage_key_agreement = true;
    }
  }
  ASN1_BIT_STRING_free(usage);

  if (!is_key_usage_digital_signature || !is_key_usage_key_agreement) {
    BMCWEB_LOG_DEBUG << "Certificate ExtendedKeyUsage does "
                        "not allow provided certificate to "
                        "be used for user authentication";
    return nullptr;
  }

  // Determine that ExtendedKeyUsage includes Client Auth

  stack_st_ASN1_OBJECT* ext_usage = static_cast<stack_st_ASN1_OBJECT*>(
      X509_get_ext_d2i(peer_cert, NID_ext_key_usage, nullptr, nullptr));

  if (ext_usage == nullptr) {
    BMCWEB_LOG_DEBUG << "TLS ext_usage is null";
    return nullptr;
  }

  bool is_ex_key_usage_client_auth = false;
  for (int i = 0; i < sk_ASN1_OBJECT_num(ext_usage); i++) {
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
    int nid = OBJ_obj2nid(sk_ASN1_OBJECT_value(ext_usage, i));
    if (NID_client_auth == nid) {
      is_ex_key_usage_client_auth = true;
      break;
    }
  }
  sk_ASN1_OBJECT_free(ext_usage);

  // Certificate has to have proper key usages set
  if (!is_ex_key_usage_client_auth) {
    BMCWEB_LOG_DEBUG << "Certificate ExtendedKeyUsage does "
                        "not allow provided certificate to "
                        "be used for user authentication";
    return nullptr;
  }
  std::string ssl_user;
  // Extract username contained in CommonName
  ssl_user.resize(256, '\0');

  int status = X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
                                         NID_commonName, ssl_user.data(),
                                         static_cast<int>(ssl_user.size()));

  if (status == -1) {
    BMCWEB_LOG_DEBUG << "TLS cannot get username to create session";
    return nullptr;
  }

  size_t last_char = ssl_user.find('\0');
  if (last_char == std::string::npos || last_char == 0) {
    BMCWEB_LOG_DEBUG << "Invalid TLS user name";
    return nullptr;
  }
  ssl_user.resize(last_char);
  std::string unsupported_client_id;
  return persistent_data::SessionStore::getInstance().generateUserSession(
      ssl_user, clientIp, unsupported_client_id,
      persistent_data::PersistenceType::TIMEOUT);
}

#endif  // THIRD_PARTY_GBMCWEB_HTTP_MUTUAL_TLS_H_
