#ifndef THIRD_PARTY_GBMCWEB_HTTP_HTTP_CONNECTION_H_
#define THIRD_PARTY_GBMCWEB_HTTP_HTTP_CONNECTION_H_

#include <array>
#include <charconv>
#include <chrono>  // NOLINT
#include <cstddef>
#include <cstdint>
#include <filesystem>  // NOLINT
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT
#include <tuple>
#include <utility>

#include "boost/algorithm/string/predicate.hpp"  // NOLINT
#include "boost/asio/io_context.hpp"  // NOLINT
#include "boost/asio/io_context_strand.hpp"  // NOLINT
#include "boost/asio/ip/tcp.hpp"  // NOLINT
#include "boost/asio/socket_base.hpp"  // NOLINT
#include "boost/asio/ssl/stream.hpp"  // NOLINT
#include "boost/asio/steady_timer.hpp"  // NOLINT
#include "boost/beast/core/flat_static_buffer.hpp"  // NOLINT
#include "boost/beast/http/error.hpp"  // NOLINT
#include "boost/beast/http/parser.hpp"  // NOLINT
#include "boost/beast/http/read.hpp"  // NOLINT
#include "boost/beast/http/serializer.hpp"  // NOLINT
#include "boost/beast/http/write.hpp"  // NOLINT
#include "boost/beast/ssl/ssl_stream.hpp"  // NOLINT
#include "boost/beast/websocket.hpp"  // NOLINT
#include "bmcweb_config.h"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "mutual_tls.hpp"
#include "async_resp.hpp"
#include "authentication.hpp"
#include "forward_unauthorized.hpp"
#include "http_utility.hpp"
#include "json_html_serializer.hpp"
#include "security_headers.hpp"
#include "sessions.hpp"
#include "ssl_key_handler.hpp"
#include <nlohmann/json.hpp>

namespace crow {

inline void prettyPrintJson(crow::Response& res) {
  json_html_util::dumpHtml(res.body(), res.jsonValue);

  res.addHeader(boost::beast::http::field::content_type,
                "text/html;charset=UTF-8");
}

// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
static int connectionCount = 0;

// request body limit size set by the bmcwebHttpReqBodyLimitMb option
constexpr uint64_t httpReqBodyLimit =
    1024UL * 1024UL * bmcwebHttpReqBodyLimitMb;

constexpr uint64_t loggedOutPostBodyLimit = 4096;

constexpr uint32_t httpHeaderLimit = 8192;

template <typename Adaptor, typename Handler>
class Connection
    : public std::enable_shared_from_this<Connection<Adaptor, Handler>> {
  using self_type = Connection<Adaptor, Handler>;

 public:
  Connection(Handler* handlerIn, boost::asio::steady_timer&& timerIn,
             std::function<std::string()>& getCachedDateStrF, Adaptor adaptorIn)
      : adaptor(std::move(adaptorIn)),
        handler(handlerIn),
        timer(std::move(timerIn)),
        getCachedDateStr(getCachedDateStrF) {
    parser.emplace(std::piecewise_construct, std::make_tuple());
    parser->body_limit(httpReqBodyLimit);
    parser->header_limit(httpHeaderLimit);

#ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION
    prepareMutualTls();
#endif  // BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION

    connectionCount++;

    BMCWEB_LOG_DEBUG << this << " Connection open, total " << connectionCount;
  }

  ~Connection() {
    res.setCompleteRequestHandler(nullptr);
    cancelDeadlineTimer();

    connectionCount--;
    BMCWEB_LOG_DEBUG << this << " Connection closed, total " << connectionCount;
  }

  Connection(const Connection&) = delete;
  Connection(Connection&&) = delete;
  Connection& operator=(const Connection&) = delete;
  Connection& operator=(Connection&&) = delete;

  bool tlsVerifyCallback(bool preverified,
                         boost::asio::ssl::verify_context& ctx) {
    // We always return true to allow full auth flow for resources that
    // don't require auth
    if (preverified) {
      mtlsSession = verifyMtlsUser(req->ipAddress, ctx);
      if (mtlsSession) {
        BMCWEB_LOG_DEBUG << this << " Generating TLS session: "
                         << mtlsSession->uniqueId;
      }
    }
    return true;
  }

  void prepareMutualTls() {
    std::error_code error;
    std::filesystem::path ca_path(ensuressl::trustStorePath);
    auto ca_available = !std::filesystem::is_empty(ca_path, error);
    ca_available = ca_available && !error;
    if (ca_available && persistent_data::SessionStore::getInstance()
                            .getAuthMethodsConfig()
                            .tls) {
      adaptor.set_verify_mode(boost::asio::ssl::verify_peer);
      std::string id = "bmcweb";

      const char* c_str = id.c_str();
      // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
      const auto* id_c = reinterpret_cast<const unsigned char*>(c_str);
      int ret =
          SSL_set_session_id_context(adaptor.native_handle(), id_c,
                                     static_cast<unsigned int>(id.length()));
      if (ret == 0) {
        BMCWEB_LOG_ERROR << this << " failed to set SSL id";
      }
    }

    adaptor.set_verify_callback(
        std::bind_front(&self_type::tlsVerifyCallback, this));
  }

  Adaptor& socket() { return adaptor; }

  void start() {
    if (connectionCount >= 100) {
      BMCWEB_LOG_CRITICAL << this << "Max connection count exceeded.";
      return;
    }

    startDeadline();

    // TODO(ed) Abstract this to a more clever class with the idea of an
    // asynchronous "start"
    if constexpr (std::is_same_v<Adaptor, boost::beast::ssl_stream<
                                              boost::asio::ip::tcp::socket>>) {
      adaptor.async_handshake(boost::asio::ssl::stream_base::server,
                              [this, self(shared_from_this())](
                                  const boost::system::error_code& ec) {
                                if (ec) {
                                  return;
                                }
                                doReadHeaders();
                              });
    } else {
      doReadHeaders();
    }
  }

  void handle() {
    std::error_code req_ec;
    crow::Request& this_req = req.emplace(parser->release(), req_ec);
    if (req_ec) {
      BMCWEB_LOG_DEBUG << "Request failed to construct" << req_ec;
      res.result(boost::beast::http::status::bad_request);
      completeRequest(res);
      return;
    }

    int64_t max_age_sec = 0;
    std::string_view max_age_sec_str =
        this_req.getHeaderValue(bmcweb::BMCWEB_HINT_MAX_AGE_SEC);
    if (!max_age_sec_str.empty()) {
      std::from_chars(max_age_sec_str.data(),
                      max_age_sec_str.data() + max_age_sec_str.size(),
                      max_age_sec);
    }

    BMCWEB_LOG_ALWAYS << "=> Connection: handle: target: " << this_req.target()
                      << " max_age_sec_str: " << max_age_sec_str
                      << " max_age_sec: " << max_age_sec;

    this_req.session = userSession;

    // Fetch the client IP address
    readClientIp();

    // Check for HTTP version 1.1.
    if (this_req.version() == 11) {
      if (this_req.getHeaderValue(boost::beast::http::field::host).empty()) {
        res.result(boost::beast::http::status::bad_request);
        completeRequest(res);
        return;
      }
    }

    BMCWEB_LOG_INFO << "Request: "
                    << " " << this << " HTTP/" << this_req.version() / 10 << "."
                    << this_req.version() % 10 << ' ' << this_req.methodString()
                    << " " << this_req.target() << " "
                    << this_req.ipAddress.to_string();

    std::string uri_string = static_cast<std::string>(this_req.target());
    res.requestStartTime(uri_string);
    res.startTimetrace("BMCWEB");
    res.isAliveHelper = [this]() -> bool { return isAlive(); };

    this_req.ioService = static_cast<decltype(this_req.ioService)>(
        &adaptor.get_executor().context());

    if (res.completed) {
      completeRequest(res);
      return;
    }
    keepAlive = this_req.keepAlive();
#ifndef BMCWEB_INSECURE_DISABLE_AUTHX
    if (!crow::authentication::isOnAllowlist(req->url().buffer(),
                                             req->method()) &&
        this_req.session == nullptr) {
      BMCWEB_LOG_WARNING << "Authentication failed";
      forward_unauthorized::sendUnauthorized(
          req->url().encoded_path(), req->getHeaderValue("X-Requested-With"),
          req->getHeaderValue("Accept"), res);
      completeRequest(res);
      return;
    }
#endif  // BMCWEB_INSECURE_DISABLE_AUTHX

    auto async_resp = std::make_shared<bmcweb::AsyncResp>(nullptr);
    async_resp->hintMaxAgeSec =
        max_age_sec;  // TODO: Remove after g3 managedStore dependency merges
    async_resp->hintCacheMaxAgeSec = max_age_sec;

    BMCWEB_LOG_DEBUG << "Setting completion handler: " << " hintMaxAgeSec: "
                     << async_resp->hintCacheMaxAgeSec.value();
    async_resp->res.setCompleteRequestHandler(
        [self(shared_from_this())](crow::Response& thisRes) {
          self->completeRequest(thisRes);
        });

    if (this_req.isUpgrade() &&
        boost::iequals(
            this_req.getHeaderValue(boost::beast::http::field::upgrade),
            "websocket")) {
      async_resp->res.setCompleteRequestHandler(
          [self(shared_from_this())](crow::Response& thisRes) {
            if (thisRes.result() != boost::beast::http::status::ok) {
              // When any error occurs before handle upgradation,
              // the result in response will be set to respective
              // error. By default the Result will be OK (200),
              // which implies successful handle upgrade. Response
              // needs to be sent over this connection only on
              // failure.
              self->completeRequest(thisRes);
              return;
            }
          });
      handler->handleUpgrade(this_req, async_resp, std::move(adaptor));
      return;
    }
    std::string_view expected =
        req->getHeaderValue(boost::beast::http::field::if_none_match);
    if (!expected.empty()) {
      res.setExpectedHash(expected);
    }
    async_resp->res.startTimetrace("LOCAL");
    // Only post to strand for GET requests.
    if (this_req.method() == boost::beast::http::verb::get) {
      auto strand = std::make_shared<boost::asio::io_context::strand>(
          *this_req.ioService);
      async_resp->strand_ = strand;
      strand->post([this, this_req{std::move(this_req)},
                    async_resp{std::move(async_resp)}]() mutable {
        handler->handle(this_req, async_resp);
        async_resp->res.endTimetrace("LOCAL");
      });
      return;
    }
    handler->handle(this_req, async_resp);
    async_resp->res.endTimetrace("LOCAL");
  }

  bool isAlive() {
    if constexpr (std::is_same_v<Adaptor, boost::beast::ssl_stream<
                                              boost::asio::ip::tcp::socket>>) {
      return adaptor.next_layer().is_open();
    } else {
      return adaptor.is_open();
    }
  }

  // Set the socket to use a keepAlive. ONLY CALL THIS DURING SOCKET ACCEPT
  void setKeepAlive() {
    // Sets SO_KEEPALIVE. For more info see
    // https://beta.boost.org/doc/libs/1_82_0/doc/html/boost_asio/reference/socket_base/keep_alive.html
    boost::asio::socket_base::keep_alive option(true);
    if constexpr (std::is_same_v<Adaptor, boost::beast::ssl_stream<
                                              boost::asio::ip::tcp::socket>>) {
      adaptor.next_layer().set_option(option);
    } else {
      adaptor.set_option(option);
    }
  }

  void close() {
    if constexpr (std::is_same_v<Adaptor, boost::beast::ssl_stream<
                                              boost::asio::ip::tcp::socket>>) {
      adaptor.next_layer().close();
      if (mtlsSession != nullptr) {
        BMCWEB_LOG_DEBUG << this
                         << " Removing TLS session: " << mtlsSession->uniqueId;
        persistent_data::SessionStore::getInstance().removeSession(mtlsSession);
      }
    } else {
      adaptor.close();
    }
  }

  void completeRequest(crow::Response& thisRes) {
    if (!req) {
      return;
    }
    res = std::move(thisRes);
    res.keepAlive(keepAlive);

    BMCWEB_LOG_INFO << "Response: " << this << ' ' << req->url().encoded_path()
                    << ' ' << res.resultInt() << " keepalive=" << keepAlive;

    addSecurityHeaders(*req, res);

    crow::authentication::cleanupTempSession(*req);

    if (!isAlive()) {
      // BMCWEB_LOG_DEBUG << this << " delete (socket is closed) " <<
      // isReading
      // << ' ' << isWriting;
      // delete this;

      // delete lambda with self shared_ptr
      // to enable connection destruction
      res.setCompleteRequestHandler(nullptr);
      return;
    }

    res.setHashAndHandleNotModified();

    if (res.body().empty() && !res.jsonValue.empty()) {
      using http_helpers::ContentType;
      std::array<ContentType, 3> allowed{ContentType::CBOR, ContentType::JSON,
                                         ContentType::HTML};
      ContentType prefered =
          getPreferedContentType(req->getHeaderValue("Accept"), allowed);

      if (prefered == ContentType::HTML) {
        prettyPrintJson(res);
      } else if (prefered == ContentType::CBOR) {
        res.addHeader(boost::beast::http::field::content_type,
                      "application/cbor");
        nlohmann::json::to_cbor(res.jsonValue, res.body());
      } else {
        // Technically prefered could also be NoMatch here, but we'd
        // like to default to something rather than return 400 for
        // backward compatibility.
        res.addHeader(boost::beast::http::field::content_type,
                      "application/json");
        res.body() = res.jsonValue.dump(
            2, ' ', true, nlohmann::json::error_handler_t::replace);
      }
    }

    if (res.resultInt() >= 400 && res.body().empty()) {
      res.body() = std::string(res.reason());
    }

    if (res.result() == boost::beast::http::status::no_content) {
      // Boost beast throws if content is provided on a no-content
      // response.  Ideally, this would never happen, but in the case that
      // it does, we don't want to throw.
      BMCWEB_LOG_CRITICAL
          << this << " Response content provided but code was no-content";
      res.body().clear();
    }

    res.addHeader(boost::beast::http::field::date, getCachedDateStr());

    res.endTimetrace("BMCWEB");
    res.requestEndTime();
    res.updateTraceInManagedStore();

    doWrite(res);

    // delete lambda with self shared_ptr
    // to enable connection destruction
    res.setCompleteRequestHandler(nullptr);
  }

  void readClientIp() {
    boost::asio::ip::address ip;
    boost::system::error_code ec = getClientIp(ip);
    if (ec) {
      return;
    }
    req->ipAddress = ip;
  }

  boost::system::error_code getClientIp(boost::asio::ip::address& ip) {
    boost::system::error_code ec;
    BMCWEB_LOG_DEBUG << "Fetch the client IP address";
    boost::asio::ip::tcp::endpoint endpoint =
        boost::beast::get_lowest_layer(adaptor).remote_endpoint(ec);

    if (ec) {
      // If remote endpoint fails keep going. "ClientOriginIPAddress"
      // will be empty.
      BMCWEB_LOG_ERROR << "Failed to get the client's IP Address. ec : " << ec;
      return ec;
    }
    ip = endpoint.address();
    return ec;
  }

 private:
  void doReadHeaders() {
    BMCWEB_LOG_DEBUG << this << " doReadHeaders";

    // Clean up any previous Connection.
    boost::beast::http::async_read_header(
        adaptor, buffer, *parser,
        [this, self(shared_from_this())](const boost::system::error_code& ec,
                                         std::size_t bytesTransferred) {
          BMCWEB_LOG_DEBUG << this << " async_read_header " << bytesTransferred
                           << " Bytes";
          bool errorWhileReading = false;
          if (ec) {
            errorWhileReading = true;
            if (ec == boost::beast::http::error::end_of_stream) {
              BMCWEB_LOG_WARNING << this
                                 << " Error while reading: " << ec.message();
            } else {
              BMCWEB_LOG_ERROR << this
                               << " Error while reading: " << ec.message();
            }
          } else {
            // if the adaptor isn't open anymore, and wasn't handed to a
            // websocket, treat as an error
            if (!isAlive() &&
                !boost::beast::websocket::is_upgrade(parser->get())) {
              errorWhileReading = true;
            }
          }

          cancelDeadlineTimer();

          if (errorWhileReading) {
            close();
            BMCWEB_LOG_DEBUG << this << " from read(1)";
            return;
          }

          readClientIp();

          boost::asio::ip::address ip;
          if (getClientIp(ip)) {
            BMCWEB_LOG_DEBUG << "Unable to get client IP";
          }
#ifndef BMCWEB_INSECURE_DISABLE_AUTHX
          boost::beast::http::verb method = parser->get().method();
          userSession = crow::authentication::authenticate(
              ip, res, method, parser->get().base(), mtlsSession);

          bool loggedIn = userSession != nullptr;
          if (!loggedIn) {
            const boost::optional<uint64_t> contentLength =
                parser->content_length();
            if (contentLength && *contentLength > loggedOutPostBodyLimit) {
              BMCWEB_LOG_DEBUG << "Content length greater than limit "
                               << *contentLength;
              close();
              return;
            }

            BMCWEB_LOG_DEBUG << "Starting quick deadline";
          }
#endif  // BMCWEB_INSECURE_DISABLE_AUTHX

          if (parser->is_done()) {
            handle();
            return;
          }

          doRead();
        });
  }

  void doRead() {
    BMCWEB_LOG_DEBUG << this << " doRead";
    startDeadline();
    boost::beast::http::async_read_some(
        adaptor, buffer, *parser,
        [this, self(shared_from_this())](const boost::system::error_code& ec,
                                         std::size_t bytesTransferred) {
          BMCWEB_LOG_DEBUG << this << " async_read_some " << bytesTransferred
                           << " Bytes";

          if (ec) {
            BMCWEB_LOG_ERROR << this
                             << " Error while reading: " << ec.message();
            close();
            BMCWEB_LOG_DEBUG << this << " from read(1)";
            return;
          }

          // If the user is logged in, allow them to send files incrementally
          // one piece at a time. If authentication is disabled then there is
          // no user session hence always allow to send one piece at a time.
          if (userSession != nullptr) {
            cancelDeadlineTimer();
          }
          if (!parser->is_done()) {
            doRead();
            return;
          }

          cancelDeadlineTimer();
          handle();
        });
  }

  void doWrite(crow::Response& thisRes) {
    BMCWEB_LOG_DEBUG << this << " doWrite";
    thisRes.preparePayload();
    serializer.emplace(*thisRes.stringResponse);
    startDeadline();
    boost::beast::http::async_write(
        adaptor, *serializer,
        [this, self(shared_from_this())](const boost::system::error_code& ec,
                                         std::size_t bytesTransferred) {
          BMCWEB_LOG_DEBUG << this << " async_write " << bytesTransferred
                           << " bytes";

          cancelDeadlineTimer();

          if (ec) {
            BMCWEB_LOG_DEBUG << this << " from write(2)";
            return;
          }
          if (!keepAlive) {
            close();
            BMCWEB_LOG_DEBUG << this << " from write(1)";
            return;
          }

          serializer.reset();
          BMCWEB_LOG_DEBUG << this << " Clearing response";
          res.clear();
          parser.emplace(std::piecewise_construct, std::make_tuple());
          parser->body_limit(httpReqBodyLimit);  // reset body limit for
                                                 // newly created parser
          buffer.consume(buffer.size());

          userSession = nullptr;

          // Destroy the Request via the std::optional
          req.reset();
          doReadHeaders();
        });
  }

  void cancelDeadlineTimer() { timer.cancel(); }

  void startDeadline() {
    // Timer is already started so no further action is required.
    if (timerStarted) {
      return;
    }

    std::chrono::seconds timeout(15);

    std::weak_ptr<Connection<Adaptor, Handler>> weak_self = weak_from_this();
    timer.expires_after(timeout);
    timer.async_wait([weak_self](const boost::system::error_code ec) {
      // Note, we are ignoring other types of errors here;  If the timer
      // failed for any reason, we should still close the connection
      std::shared_ptr<Connection<Adaptor, Handler>> self = weak_self.lock();
      if (!self) {
        BMCWEB_LOG_CRITICAL << self << " Failed to capture connection";
        return;
      }

      self->timerStarted = false;

      if (ec == boost::asio::error::operation_aborted) {
        // Canceled wait means the path succeeded.
        return;
      }
      if (ec) {
        BMCWEB_LOG_CRITICAL << self << " timer failed " << ec;
      }

      BMCWEB_LOG_WARNING << self << "Connection timed out, closing";

      self->close();
    });

    timerStarted = true;
    BMCWEB_LOG_DEBUG << this << " timer started";
  }

  Adaptor adaptor;   // NOLINT
  Handler* handler;  // NOLINT
  // Making this a std::optional allows it to be efficiently destroyed and
  // re-created on Connection reset
  std::optional<
      boost::beast::http::request_parser<boost::beast::http::string_body>>
      parser;  // NOLINT

  boost::beast::flat_static_buffer<8192> buffer;  // NOLINT

  std::optional<
      boost::beast::http::response_serializer<boost::beast::http::string_body>>
      serializer;  // NOLINT

  std::optional<crow::Request> req;  // NOLINT
  crow::Response res;                // NOLINT

  std::shared_ptr<persistent_data::UserSession> userSession;  // NOLINT
  std::shared_ptr<persistent_data::UserSession> mtlsSession;  // NOLINT

  boost::asio::steady_timer timer;  // NOLINT

  bool keepAlive = true;  // NOLINT

  bool timerStarted = false;  // NOLINT

  std::function<std::string()>& getCachedDateStr;  // NOLINT

  using std::enable_shared_from_this<
      Connection<Adaptor, Handler>>::shared_from_this;

  using std::enable_shared_from_this<
      Connection<Adaptor, Handler>>::weak_from_this;
};
}  // namespace crow

#endif  // THIRD_PARTY_GBMCWEB_HTTP_HTTP_CONNECTION_H_
