#include <stdint.h>

#include <string>

#include "absl/strings/escaping.h"
#include "openssl/hpke.h"
#include "quiche/common/platform/api/quiche_test.h"
#include "quiche/oblivious_http/buffers/oblivious_http_response.h"

namespace quiche {
namespace {

struct ObliviousHttpResponseTestStrings {
  std::string test_case_name;
  uint8_t key_id;
  std::string request_plaintext;
  std::string response_plaintext;
};

std::string GetHpkePrivateKey() {
  absl::string_view hpke_key_hex =
      "b77431ecfa8f4cfc30d6e467aafa06944dffe28cb9dd1409e33a3045f5adc8a1";
  return absl::HexStringToBytes(hpke_key_hex);
}

std::string GetHpkePublicKey() {
  absl::string_view public_key =
      "6d21cfe09fbea5122f9ebc2eb2a69fcc4f06408cd54aac934f012e76fcdcef62";
  return absl::HexStringToBytes(public_key);
}

const ObliviousHttpHeaderKeyConfig GetOhttpKeyConfig(uint8_t key_id,
                                                     uint16_t kem_id,
                                                     uint16_t kdf_id,
                                                     uint16_t aead_id) {
  auto ohttp_key_config =
      ObliviousHttpHeaderKeyConfig::Create(key_id, kem_id, kdf_id, aead_id);
  EXPECT_TRUE(ohttp_key_config.ok());
  return std::move(ohttp_key_config.value());
}

bssl::UniquePtr<EVP_HPKE_KEY> ConstructHpkeKey(
    absl::string_view hpke_key,
    const ObliviousHttpHeaderKeyConfig &ohttp_key_config) {
  bssl::UniquePtr<EVP_HPKE_KEY> bssl_hpke_key(EVP_HPKE_KEY_new());
  EXPECT_NE(bssl_hpke_key, nullptr);
  EXPECT_TRUE(EVP_HPKE_KEY_init(
      bssl_hpke_key.get(), ohttp_key_config.GetHpkeKem(),
      reinterpret_cast<const uint8_t *>(hpke_key.data()), hpke_key.size()));
  return bssl_hpke_key;
}
}  // namespace

using ObliviousHttpParameterizedTest =
    test::QuicheTestWithParam<ObliviousHttpResponseTestStrings>;

TEST_P(ObliviousHttpParameterizedTest, TestEndToEndWithOfflineStrings) {
  // For each test case, verify end to end request-handling and
  // response-handling.
  const ObliviousHttpResponseTestStrings &test = GetParam();

  auto ohttp_key_config =
      GetOhttpKeyConfig(test.key_id, EVP_HPKE_DHKEM_X25519_HKDF_SHA256,
                        EVP_HPKE_HKDF_SHA256, EVP_HPKE_AES_256_GCM);
  // Round-trip request flow.
  auto client_req_encap = ObliviousHttpRequest::CreateClientObliviousRequest(
      test.request_plaintext, GetHpkePublicKey(), ohttp_key_config);
  EXPECT_TRUE(client_req_encap.ok());
  ASSERT_FALSE(client_req_encap->EncapsulateAndSerialize().empty());
  auto server_req_decap = ObliviousHttpRequest::CreateServerObliviousRequest(
      client_req_encap->EncapsulateAndSerialize(),
      *(ConstructHpkeKey(GetHpkePrivateKey(), ohttp_key_config)),
      ohttp_key_config);
  EXPECT_TRUE(server_req_decap.ok());
  EXPECT_EQ(server_req_decap->GetPlaintextData(), test.request_plaintext);

  // Round-trip response flow.
  auto server_request_context =
      std::move(server_req_decap.value()).ReleaseContext();
  auto server_resp_encap = ObliviousHttpResponse::CreateServerObliviousResponse(
      test.response_plaintext, server_request_context);
  EXPECT_TRUE(server_resp_encap.ok());
  ASSERT_FALSE(server_resp_encap->EncapsulateAndSerialize().empty());
  auto client_request_context =
      std::move(client_req_encap.value()).ReleaseContext();
  auto client_resp_decap = ObliviousHttpResponse::CreateClientObliviousResponse(
      server_resp_encap->EncapsulateAndSerialize(), client_request_context);
  EXPECT_TRUE(client_resp_decap.ok());
  EXPECT_EQ(client_resp_decap->GetPlaintextData(), test.response_plaintext);
}

INSTANTIATE_TEST_SUITE_P(
    ObliviousHttpParameterizedTests, ObliviousHttpParameterizedTest,
    testing::ValuesIn<ObliviousHttpResponseTestStrings>(
        {{"test_case_1", 4, "test request 1", "test response 1"},
         {"test_case_2", 6, "test request 2", "test response 2"},
         {"test_case_3", 7, "test request 3", "test response 3"},
         {"test_case_4", 2, "test request 4", "test response 4"},
         {"test_case_5", 1, "test request 5", "test response 5"},
         {"test_case_6", 7, "test request 6", "test response 6"},
         {"test_case_7", 3, "test request 7", "test response 7"},
         {"test_case_8", 9, "test request 8", "test response 8"},
         {"test_case_9", 3, "test request 9", "test response 9"},
         {"test_case_10", 4, "test request 10", "test response 10"}}),
    [](const testing::TestParamInfo<ObliviousHttpParameterizedTest::ParamType>
           &info) { return info.param.test_case_name; });

}  // namespace quiche
