#ifndef QUICHE_OBLIVIOUS_HTTP_BUFFERS_OBLIVIOUS_HTTP_REQUEST_H_
#define QUICHE_OBLIVIOUS_HTTP_BUFFERS_OBLIVIOUS_HTTP_REQUEST_H_

#include <optional>
#include <string>
#include <utility>

#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "openssl/hpke.h"
#include "quiche/common/platform/api/quiche_export.h"
#include "quiche/common/quiche_data_reader.h"
#include "quiche/oblivious_http/common/oblivious_http_header_key_config.h"

namespace quiche {
// 1. Handles client side encryption of the payload that will subsequently be
// added to HTTP POST body and passed on to Relay.
// 2. Handles server side decryption of the payload received in HTTP POST body
// from Relay.
// https://www.rfc-editor.org/rfc/rfc9458.html#section-4.3
class QUICHE_EXPORT ObliviousHttpRequest {
 public:
  // Holds the HPKE related data received from request. This context is created
  // during request processing, and subsequently passed into response handling
  // in `ObliviousHttpResponse`.
  class QUICHE_EXPORT Context {
   public:
    ~Context() = default;

    // Movable
    Context(Context&& other) = default;
    Context& operator=(Context&& other) = default;

    std::string GetEncapsulatedKey() const { return encapsulated_key_; }

   private:
    explicit Context(bssl::UniquePtr<EVP_HPKE_CTX> hpke_context,
                     std::string encapsulated_key);

    // All accessors must be friends to read `Context`.
    friend class ObliviousHttpRequest;
    friend class ObliviousHttpResponse;
    // Tests which need access.
    friend class
        ObliviousHttpRequest_TestDecapsulateWithSpecAppendixAExample_Test;
    friend class ObliviousHttpRequest_TestEncapsulatedRequestStructure_Test;
    friend class
        ObliviousHttpRequest_TestEncapsulatedOhttpEncryptedPayload_Test;
    friend class ObliviousHttpRequest_TestDeterministicSeededOhttpRequest_Test;
    friend class ObliviousHttpResponse_EndToEndTestForResponse_Test;
    friend class ObliviousHttpResponse_TestEncapsulateWithQuicheRandom_Test;

    bssl::UniquePtr<EVP_HPKE_CTX> hpke_context_;
    std::string encapsulated_key_;
  };
  // Parse the OHTTP request from the given `encrypted_data`.
  // On success, returns obj that callers will use to `GetPlaintextData`.
  // Generic Usecase : server-side calls this method in the context of Request.
  static absl::StatusOr<ObliviousHttpRequest> CreateServerObliviousRequest(
      absl::string_view encrypted_data, const EVP_HPKE_KEY& gateway_key,
      const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
      absl::string_view request_label =
          ObliviousHttpHeaderKeyConfig::kOhttpRequestLabel);

  // Constructs an OHTTP request for the given `plaintext_payload`.
  // On success, returns obj that callers will use to `EncapsulateAndSerialize`
  // OHttp request.
  static absl::StatusOr<ObliviousHttpRequest> CreateClientObliviousRequest(
      std::string plaintext_payload, absl::string_view hpke_public_key,
      const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
      absl::string_view request_label =
          ObliviousHttpHeaderKeyConfig::kOhttpRequestLabel);

  // Same as above but accepts a random number seed for testing.
  static absl::StatusOr<ObliviousHttpRequest> CreateClientWithSeedForTesting(
      std::string plaintext_payload, absl::string_view hpke_public_key,
      const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
      absl::string_view seed,
      absl::string_view request_label =
          ObliviousHttpHeaderKeyConfig::kOhttpRequestLabel);

  // Movable.
  ObliviousHttpRequest(ObliviousHttpRequest&& other) = default;
  ObliviousHttpRequest& operator=(ObliviousHttpRequest&& other) = default;

  ~ObliviousHttpRequest() = default;

  // Returns serialized OHTTP request bytestring.
  // @note: This method MUST NOT be called after `ReleaseContext()` has been
  // called.
  std::string EncapsulateAndSerialize() const;

  // Generic Usecase : server-side calls this method after Decapsulation using
  // `CreateServerObliviousRequest`.
  absl::string_view GetPlaintextData() const;

  // Oblivious HTTP request context is created after successful creation of
  // `this` object, and subsequently passed into the `ObliviousHttpResponse` for
  // followup response handling.
  // @returns: This rvalue reference qualified member function transfers the
  // ownership of `Context` to the caller, and further invokes
  // ClangTidy:misc-use-after-move warning if callers try to extract `Context`
  // twice after the fact that the ownership has already been transferred.
  // @note: Callers shouldn't extract the `Context` until you're done with this
  // Request and its data.
  Context ReleaseContext() && {
    return std::move(oblivious_http_request_context_.value());
  }

  // Reads the OHTTP request header from the given `reader`.
  // On success, attempts to setup and return the Gateway Context.
  static absl::StatusOr<Context> DecodeEncapsulatedRequestHeader(
      QuicheDataReader& reader, const EVP_HPKE_KEY& gateway_key,
      const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
      absl::string_view request_label);

  // Creates the client's HPKE sender context.
  static absl::StatusOr<Context> CreateHpkeSenderContext(
      absl::string_view hpke_public_key,
      const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
      absl::string_view seed, absl::string_view request_label);

  // Encrypts a chunk of plaintext. If `is_final_chunk` is true, the chunk will
  // be encrypted with a final AAD.
  static absl::StatusOr<std::string> EncryptChunk(
      absl::string_view plaintext_payload, const Context& context,
      bool is_final_chunk);

  // Decrypts an encrypted chunk. If `is_final_chunk` is true, the chunk will
  // be decrypted with a final AAD.
  static absl::StatusOr<std::string> DecryptChunk(
      Context& context, absl::string_view encrypted_chunk, bool is_final_chunk);

 private:
  explicit ObliviousHttpRequest(
      bssl::UniquePtr<EVP_HPKE_CTX> hpke_context, std::string encapsulated_key,
      const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
      std::string req_ciphertext, std::string req_plaintext);

  static absl::StatusOr<ObliviousHttpRequest> EncapsulateWithSeed(
      std::string plaintext_payload, absl::string_view hpke_public_key,
      const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
      absl::string_view seed, absl::string_view request_label);

  // This field will be empty after calling `ReleaseContext()`.
  std::optional<Context> oblivious_http_request_context_;
  ObliviousHttpHeaderKeyConfig key_config_;
  std::string request_ciphertext_;
  std::string request_plaintext_;
};

}  // namespace quiche

#endif  // QUICHE_OBLIVIOUS_HTTP_BUFFERS_OBLIVIOUS_HTTP_REQUEST_H_
