#include <stdint.h>

#include <string>
#include <utility>

#include "absl/strings/escaping.h"
#include "absl/strings/string_view.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";
  std::string hpke_key_bytes;
  EXPECT_TRUE(absl::HexStringToBytes(hpke_key_hex, &hpke_key_bytes));
  return hpke_key_bytes;
}

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

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; });

TEST(ObliviousHttpIntegrationTest, TestWithCustomRequestResponseLabels) {
  const std::string kRequestLabel = "test_request_label";
  const std::string kResponseLabel = "test_response_label";

  ObliviousHttpResponseTestStrings test = {"", 4, "test_request_plaintext",
                                           "test_response_plaintext"};

  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,
      kRequestLabel);
  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, kRequestLabel);
  EXPECT_TRUE(server_req_decap.ok());
  EXPECT_EQ(server_req_decap->GetPlaintextData(), test.request_plaintext);

  auto failed_server_req_decap =
      ObliviousHttpRequest::CreateServerObliviousRequest(
          client_req_encap->EncapsulateAndSerialize(),
          *(ConstructHpkeKey(GetHpkePrivateKey(), ohttp_key_config)),
          ohttp_key_config);
  EXPECT_FALSE(failed_server_req_decap.ok());

  // 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, kResponseLabel);
  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,
      kResponseLabel);
  EXPECT_TRUE(client_resp_decap.ok());
  EXPECT_EQ(client_resp_decap->GetPlaintextData(), test.response_plaintext);

  auto failed_client_resp_decap =
      ObliviousHttpResponse::CreateClientObliviousResponse(
          server_resp_encap->EncapsulateAndSerialize(), client_request_context);
  EXPECT_FALSE(failed_client_resp_decap.ok());
}

}  // namespace quiche
