// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "testing/create_test_crypto_write_handler.h"

#include <memory>
#include <string>
#include <utility>

#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/notification.h"
#include "absl/time/simulated_clock.h"
#include "absl/time/time.h"
#include "cose/simple_cms_parser.h"
#include "crypto/algorithms.h"
#include "crypto/crypto_write_handler.h"
#include "crypto/default/trust_store.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "openssl/pki/verify.h"
#include "testing/local_key_crypto_write_handler.h"
#include "testing/test_validation_tracker.h"
#include "tsp/parsed_timestamp_token.h"
#include "tsp/timestamp_verifier.h"
#include "tsp/verified_timestamp.h"

namespace credentio {
namespace {

using ::absl_testing::IsOk;
using ::absl_testing::StatusIs;
using ::testing::ElementsAreArray;
using ::testing::HasSubstr;
using ::testing::IsEmpty;
using ::testing::Not;

absl::StatusOr<std::string> GetTimestamp(CryptoWriteHandler& handler,
                                         HashAlgorithm hash_algorithm,
                                         absl::string_view hashed_message) {
  absl::Notification done;
  absl::StatusOr<std::string> result;
  handler.CreateTimestamp(hash_algorithm, std::string(hashed_message),
                          /*options=*/{},
                          [&result, &done](absl::StatusOr<std::string> res) {
                            result = std::move(res);
                            done.Notify();
                          });
  done.WaitForNotification();
  return result;
}

TEST(CreateTestCryptoWriteHandlerTest, CreateTimestamp) {
  absl::SimulatedClock clock;
  absl::Time now = absl::FromUnixSeconds(1739221301);  // within validity period
  clock.SetTime(now);
  std::string message_imprint = "message_imprint";
  absl::StatusOr<std::unique_ptr<CryptoWriteHandler>> writer =
      CreateTestCryptoWriteHandler({.clock = &clock});
  ABSL_ASSERT_OK(writer);
  absl::StatusOr<std::string> created_timestamp =
      GetTimestamp(**writer, HashAlgorithm::kSha384, message_imprint);
  ABSL_ASSERT_OK(created_timestamp);

  absl::StatusOr<std::unique_ptr<bssl::VerifyTrustStore>> trust_store =
      LoadTrustStore(DefaultTestPki().root_ca.cert_pem);
  ABSL_ASSERT_OK(trust_store);
  TimestampVerifier verifier(trust_store->get());
  SimpleCmsParser parser;

  TestValidationTracker t;
  absl::StatusOr<std::unique_ptr<ParsedTimestampToken>> parsed_token =
      parser.ParseTimestampToken(*created_timestamp);
  ABSL_ASSERT_OK(parsed_token);
  absl::StatusOr<VerifiedTimestamp> verified_timestamp =
      verifier.VerifyTimestampToken(**parsed_token);
  ABSL_ASSERT_OK(verified_timestamp);
  ASSERT_THAT(t.GetFailureStatuses(), IsEmpty());
  EXPECT_EQ(verified_timestamp->message_imprint_hash(), message_imprint);
  EXPECT_EQ(verified_timestamp->asserted_time(), now);
}

TEST(CreateTestCryptoWriteHandlerTest, HasCertChainAndOcspResponse) {
  absl::StatusOr<std::unique_ptr<CryptoWriteHandler>> writer =
      CreateTestCryptoWriteHandler({});
  ABSL_ASSERT_OK(writer);
  EXPECT_THAT((*writer)->GetSigner().certificate_chain(), Not(IsEmpty()));
  EXPECT_THAT((*writer)->GetSigner().ocsp_responses(), Not(IsEmpty()));
}

TEST(CreateTestCryptoWriteHandlerTest,
     UsesConfiguredCertChainAndOcspResponses) {
  LocalKeyClaimSignerCredentials credentials = TestClaimSignerCredentials();
  credentials.ocsp_responses.clear();
  absl::StatusOr<std::unique_ptr<CryptoWriteHandler>> writer =
      CreateTestCryptoWriteHandler({.claim_signer = std::move(credentials)});
  ABSL_ASSERT_OK(writer);

  EXPECT_THAT((*writer)->GetSigner().certificate_chain(),
              ElementsAreArray(TestClaimSignerCredentials().certificate_chain));
  EXPECT_THAT((*writer)->GetSigner().ocsp_responses(), IsEmpty());
}

TEST(CreateTestCryptoWriteHandlerTest, UsesConfiguredSigningKey) {
  // Any other valid EC P-256 key will do; reuse the TSA's.
  LocalKeyClaimSignerCredentials credentials = TestClaimSignerCredentials();
  credentials.key_pem = TestTsaCredentials().key_pem;
  absl::StatusOr<std::unique_ptr<CryptoWriteHandler>> writer =
      CreateTestCryptoWriteHandler({.claim_signer = std::move(credentials)});
  ABSL_ASSERT_OK(writer);
  absl::StatusOr<std::unique_ptr<CryptoWriteHandler>> default_writer =
      CreateTestCryptoWriteHandler({});
  ABSL_ASSERT_OK(default_writer);

  absl::StatusOr<SignResponse> response =
      (*writer)->GetSigner().Sign("to_be_signed");
  ABSL_ASSERT_OK(response);
  absl::StatusOr<SignResponse> default_response =
      (*default_writer)->GetSigner().Sign("to_be_signed");
  ABSL_ASSERT_OK(default_response);
  EXPECT_NE(response->signature, default_response->signature);
}

TEST(CreateTestCryptoWriteHandlerTest, UsesConfiguredTsa) {
  absl::SimulatedClock clock;
  clock.SetTime(absl::FromUnixSeconds(1739221301));  // within validity period
  absl::StatusOr<std::unique_ptr<CryptoWriteHandler>> writer =
      CreateTestCryptoWriteHandler(
          {.clock = &clock, .tsa = TestTsaCredentials()});
  ABSL_ASSERT_OK(writer);

  EXPECT_THAT(GetTimestamp(**writer, HashAlgorithm::kSha384, "message_imprint"),
              IsOk());
}

TEST(CreateTestCryptoWriteHandlerTest,
     RejectsIncompleteClaimSignerCredentials) {
  EXPECT_THAT(CreateTestCryptoWriteHandler({.claim_signer = {{}}}),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("Claim signer key")));

  LocalKeyClaimSignerCredentials no_chain = TestClaimSignerCredentials();
  no_chain.certificate_chain.clear();
  EXPECT_THAT(
      CreateTestCryptoWriteHandler({.claim_signer = std::move(no_chain)}),
      StatusIs(absl::StatusCode::kInvalidArgument,
               HasSubstr("Claim signer certificate chain")));
}

TEST(CreateTestCryptoWriteHandlerTest, RejectsIncompleteTsaCredentials) {
  EXPECT_THAT(
      CreateTestCryptoWriteHandler({.tsa = {{}}}),
      StatusIs(absl::StatusCode::kInvalidArgument, HasSubstr("TSA key")));

  LocalKeyTsaCredentials no_cert = TestTsaCredentials();
  no_cert.cert_pem.clear();
  EXPECT_THAT(CreateTestCryptoWriteHandler({.tsa = std::move(no_cert)}),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("TSA certificate")));
}

}  // namespace
}  // namespace credentio
