// 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 "crypto/default/hasher.h"

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

#include "absl/base/no_destructor.h"
#include "absl/base/nullability.h"
#include "absl/log/absl_log.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "crypto/algorithms.h"
#include "crypto/hash.h"
#include "openssl/base.h"
#include "openssl/digest.h"

namespace credentio {
namespace {

class DefaultHashChecker : public HashChecker {
 public:
  explicit DefaultHashChecker(std::unique_ptr<Hasher> hasher)
      : hasher_(std::move(hasher)) {}

  void Update(absl::string_view content) override { hasher_->Update(content); }

  bool Check(absl::string_view expected_hash) override {
    std::string computed_hash = hasher_->Digest();
    if (computed_hash != expected_hash) {
      ABSL_DVLOG(1) << "Hash mismatch: base64(computed) = "
                    << absl::Base64Escape(computed_hash)
                    << " base64(expected) = "
                    << absl::Base64Escape(expected_hash);
      return false;
    }
    return true;
  }

 private:
  std::unique_ptr<Hasher> hasher_;
};

class DefaultHashCheckerFactoryImpl : public HashCheckerFactory {
 public:
  DefaultHashCheckerFactoryImpl() = default;

  absl::StatusOr<std::unique_ptr<HashChecker>> Create(
      HashAlgorithm algorithm) const override {
    ABSL_ASSIGN_OR_RETURN(auto hasher, CreateHasher(algorithm));
    return std::make_unique<DefaultHashChecker>(std::move(hasher));
  }
};

class DefaultHasher : public Hasher {
 public:
  static absl::StatusOr<std::unique_ptr<DefaultHasher>> Create(
      const EVP_MD* md) {
    bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_new());
    if (ctx == nullptr || EVP_DigestInit_ex(ctx.get(), md, nullptr) != 1) {
      return absl::InternalError("Failed to initialize hasher");
    }
    return std::unique_ptr<DefaultHasher>(new DefaultHasher(std::move(ctx)));
  }

  void Update(absl::string_view content) override {
    // We don't check the return value because BoringSSL's implementation always
    // returns 1.
    EVP_DigestUpdate(ctx_.get(), content.data(), content.size());
  }

  std::string Digest() override {
    unsigned int len = 0;
    unsigned char digest[EVP_MAX_MD_SIZE];
    // We don't check the return value because BoringSSL's implementation always
    // returns 1.
    EVP_DigestFinal_ex(ctx_.get(), digest, &len);
    return std::string(reinterpret_cast<char*>(digest), len);
  }

 private:
  explicit DefaultHasher(bssl::UniquePtr<EVP_MD_CTX> ctx)
      : ctx_(std::move(ctx)) {}

  bssl::UniquePtr<EVP_MD_CTX> ctx_;
};

}  // namespace

absl::StatusOr<std::unique_ptr<Hasher> absl_nonnull> CreateHasher(
    HashAlgorithm algorithm) {
  switch (algorithm) {
    case HashAlgorithm::kSha256:
      return DefaultHasher::Create(EVP_sha256());
    case HashAlgorithm::kSha384:
      return DefaultHasher::Create(EVP_sha384());
    case HashAlgorithm::kSha512:
      return DefaultHasher::Create(EVP_sha512());
  }
  std::string error_msg = absl::StrCat(
      "fell through end of exhaustive switch statement with HashAlgorithm "
      "value: ",
      static_cast<int>(algorithm));
  ABSL_LOG(DFATAL) << error_msg;
  return absl::FailedPreconditionError(error_msg);
}

absl::StatusOr<std::unique_ptr<Hasher> absl_nonnull> CreateHasher(
    absl::string_view algorithm) {
  ABSL_ASSIGN_OR_RETURN(auto ha, ParseHashAlgorithm(algorithm));
  return CreateHasher(ha);
}

const HashCheckerFactory& DefaultHashCheckerFactory() {
  static const absl::NoDestructor<DefaultHashCheckerFactoryImpl> singleton;
  return *singleton;
}

const HasherFactory& DefaultHasherFactory() {
  static const absl::NoDestructor<Sha256HasherFactory> singleton;
  return *singleton;
}

absl::StatusOr<std::unique_ptr<Hasher>> Sha256HasherFactory::Create() const {
  return DefaultHasher::Create(EVP_sha256());
}

absl::StatusOr<std::unique_ptr<Hasher>> Sha384HasherFactory::Create() const {
  return DefaultHasher::Create(EVP_sha384());
}

absl::StatusOr<std::unique_ptr<Hasher>> Sha512HasherFactory::Create() const {
  return DefaultHasher::Create(EVP_sha512());
}

}  // namespace credentio
