#pragma once

#include "logging.hpp"
#include "persistent_data.hpp"

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

#include <boost/asio/ip/address.hpp>
#include <boost/asio/ssl/verify_context.hpp>

#include <memory>
#include <span>

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* peerCert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
    if (peerCert == nullptr)
    {
        BMCWEB_LOG_DEBUG << "Cannot get current TLS certificate.";
        return nullptr;
    }

    // Check if certificate is OK
    int ctxError = X509_STORE_CTX_get_error(cts);
    if (ctxError != X509_V_OK)
    {
        BMCWEB_LOG_INFO << "Last TLS error is: " << ctxError;
        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 isKeyUsageDigitalSignature = false;
    bool isKeyUsageKeyAgreement = false;

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

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

    for (auto usageChar :
         std::span(usage->data, static_cast<size_t>(usage->length)))
    {
        if (KU_DIGITAL_SIGNATURE & usageChar)
        {
            isKeyUsageDigitalSignature = true;
        }
        if (KU_KEY_AGREEMENT & usageChar)
        {
            isKeyUsageKeyAgreement = true;
        }
    }
    ASN1_BIT_STRING_free(usage);

    if (!isKeyUsageDigitalSignature || !isKeyUsageKeyAgreement)
    {
        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* extUsage = static_cast<stack_st_ASN1_OBJECT*>(
        X509_get_ext_d2i(peerCert, NID_ext_key_usage, nullptr, nullptr));

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

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

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

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

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

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