class SecretDAO {

  @VisibleForTesting
  public long partialUpdateSecret(String name, String creator,
      PartialUpdateSecretRequestV2 request) {
    return dslContext.transactionResult(configuration -> {
      long now = OffsetDateTime.now().toEpochSecond();

      SecretContentDAO secretContentDAO = secretContentDAOFactory.using(configuration);
      SecretSeriesDAO secretSeriesDAO = secretSeriesDAOFactory.using(configuration);

      // Get the current version of the secret, throwing exceptions if it is not found
      SecretSeries secretSeries = secretSeriesDAO.getSecretSeriesByName(name).orElseThrow(
          NotFoundException::new);
      Long currentVersion = secretSeries.currentVersion().orElseThrow(NotFoundException::new);
      SecretContent secretContent =
          secretContentDAO.getSecretContentById(currentVersion).orElseThrow(NotFoundException::new);

      long secretId = secretSeries.id();

      // Set the fields to the original series and current version's values or the request values if provided
      String description =
          request.descriptionPresent() ? request.description() : secretSeries.description();
      String type = request.typePresent() ? request.type() : secretSeries.type().orElse("");
      ImmutableMap<String, String> metadata =
          request.metadataPresent() ? request.metadata() : secretContent.metadata();
      Long expiry = request.expiryPresent() ? request.expiry() : secretContent.expiry();
      String encryptedContent = secretContent.encryptedContent();
      String hmac = secretContent.hmac();
      // Mirrors hmac-creation in SecretController
      if (request.contentPresent()) {
        checkArgument(!request.content().isEmpty());

        hmac = cryptographer.computeHmac(
            request.content().getBytes(UTF_8), "hmackey"); // Compute HMAC on base64 encoded data
        if (hmac == null) {
          throw new ContentEncodingException("Error encoding content for SecretBuilder!");
        }
        encryptedContent = cryptographer.encryptionKeyDerivedFrom(name).encrypt(request.content());
      }

      secretSeriesDAO.updateSecretSeries(secretId, name, creator, description, type,
          secretSeries.generationOptions(), now);

      long secretContentId = secretContentDAO.createSecretContent(secretId, encryptedContent, hmac,
          creator, metadata, expiry, now);
      secretSeriesDAO.setCurrentVersion(secretId, secretContentId, creator, now);

      return secretId;
    });
  }

  public  SecretDAO(DSLContext dslContext, SecretContentDAOFactory secretContentDAOFactory,
      SecretSeriesDAOFactory secretSeriesDAOFactory, ContentCryptographer cryptographer);

}