// 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 "claim/local_signer.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "absl/log/absl_log.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "async/async_context.h"
#include "claim/signer.h"
#include "cose/sig_structure.h"
#include "cose/timestamp_creator.h"
#include "crypto/crypto_write_handler.h"
#include "crypto/hash.h"
#include "utils/cbor_padding.h"

namespace credentio {

namespace {

absl::StatusOr<std::string> FinalizeSignature(
    const absl::StatusOr<std::string>& timestamp,
    TimeStampingMode time_stamping_mode, uint64_t max_timestamp_byte_size,
    CoseSign1TaggedStructure* cose_sign1, uint64_t max_signature_byte_size,
    std::optional<size_t> pad_to_size) {
  if (!timestamp.ok() && time_stamping_mode == TimeStampingMode::kRequired) {
    return absl::Status(timestamp.status().code(),
                        absl::StrCat("timestamping is required but failed: ",
                                     timestamp.status().message()));
  }
  if (timestamp.ok()) {
    if (timestamp.value().size() > max_timestamp_byte_size) {
      if (time_stamping_mode == TimeStampingMode::kRequired) {
        return absl::InternalError(
            absl::StrCat("Timestamp size ", timestamp.value().size(),
                         " is larger than the maximum allowed size ",
                         max_timestamp_byte_size));
      } else {
        ABSL_LOG_EVERY_N_SEC(WARNING, 60)
            << "Ignoring timestamp because the timestamp size "
            << timestamp.value().size()
            << " is larger than the maximum allowed size "
            << max_timestamp_byte_size;
      }
    } else if (!timestamp.value().empty()) {
      cose_sign1->unprotected_header.sig_tst2 =
          TstContainer{.tst_tokens = {{.val = timestamp.value()}}};
    }
  }
  if (pad_to_size.has_value()) {
    // This logic is necessary for remote signing fallback to local where
    // the template and final signatures must be padded to the same size.
    // e.g. template uses remote signing but final uses local signing.
    ABSL_RETURN_IF_ERROR(
        PadCoseSign1TaggedStructure(*cose_sign1, *pad_to_size));
  } else {
    ABSL_RETURN_IF_ERROR(PadCoseSign1TaggedStructure(
        *cose_sign1, max_signature_byte_size, max_timestamp_byte_size));
  }
  return EncodeCoseSign1TaggedStructure(*cose_sign1);
}

}  // namespace

void LocalClaimSigner::Sign(
    absl::string_view claim, Options options,
    absl::AnyInvocable<void(absl::StatusOr<SignResult>) &&> cb) const {
  AsyncResolver<SignResult> resolver(options.async_context, std::move(cb));

  auto& signer = crypto_writer_.GetSigner();
  auto protected_header_res = EncodeProtectedHeader(
      ProtectedHeader{.alg = signer.algorithm(),
                      .certificate_chain = signer.certificate_chain()});
  if (!protected_header_res.ok()) {
    resolver.Return(protected_header_res.status());
    return;
  }
  std::string protected_header = *std::move(protected_header_res);

  Sig1Structure sig_structure{
      .context = "Signature1",
      .body_protected = std::move(protected_header),
      .payload = std::string(claim),
  };
  auto sign_res = signer.Sign(EncodeSig1Structure(sig_structure));
  if (!sign_res.ok()) {
    resolver.Return(sign_res.status());
    return;
  }
  if (sign_res->signature.size() > signer.max_signature_byte_size()) {
    resolver.Return(absl::InternalError(
        absl::StrCat("Signature size ", sign_res->signature.size(),
                     " is larger than the maximum allowed size ",
                     signer.max_signature_byte_size())));
    return;
  }

  auto cose_sign1 = std::make_shared<CoseSign1TaggedStructure>();
  cose_sign1->protected_header = sig_structure.body_protected;
  cose_sign1->signature = std::move(sign_res->signature);
  // Add OCSP responses.
  const std::vector<std::string>& ocsp_responses = signer.ocsp_responses();
  if (!ocsp_responses.empty()) {
    cose_sign1->unprotected_header.ocsp_responses = ocsp_responses;
  }
  // Create timestamp and finalize signature.
  uint64_t max_signature_byte_size = signer.max_signature_byte_size();
  uint64_t max_timestamp_byte_size =
      crypto_writer_.max_timestamp_byte_size(hasher_factory_.algorithm());
  auto time_stamping_mode = options.time_stamping_mode;

  if (time_stamping_mode == TimeStampingMode::kOmittedWithPadding) {
    auto signature = FinalizeSignature(
        /*timestamp=*/"", time_stamping_mode, max_timestamp_byte_size,
        cose_sign1.get(), max_signature_byte_size, pad_to_size_);
    if (!signature.ok()) {
      resolver.Return(signature.status());
      return;
    }
    SignResult sign_result{.signature = std::move(*signature)};
    resolver.Return(std::move(sign_result));
    return;
  }

  TimestampCreator::Options timestamp_creator_options{
      .async_context = options.async_context,
  };

  auto create_timestamp_cb =
      [resolver = std::move(resolver), max_timestamp_byte_size, cose_sign1,
       max_signature_byte_size, pad_to_size = pad_to_size_, time_stamping_mode](
          absl::StatusOr<std::string> timestamp_result) mutable {
        auto signature = FinalizeSignature(
            timestamp_result, time_stamping_mode, max_timestamp_byte_size,
            cose_sign1.get(), max_signature_byte_size, pad_to_size);
        if (!signature.ok()) {
          resolver.Return(signature.status());
          return;
        }
        SignResult sign_result{.signature = std::move(*signature)};
        resolver.Return(std::move(sign_result));
      };

  timestamp_creator_.CreateTimestamp(*cose_sign1,
                                     std::move(timestamp_creator_options),
                                     std::move(create_timestamp_cb));
}

}  // namespace credentio
