class SecretDAO {

  @VisibleForTesting
  public long createSecret(String name, String encryptedSecret, String hmac,
      String creator, Map<String, String> metadata, long expiry, String description,
      @Nullable String type, @Nullable Map<String, String> generationOptions) {
    return dslContext.transactionResult(configuration -> {
      // disallow use of a leading period in secret names
      // check is here because this is where all APIs converge on secret creation
      if (name.startsWith(".")) {
        throw new BadRequestException(format("secret cannot be created with name `%s` - secret "
            + "names cannot begin with a period", name));
      }

      // enforce a shorter max length than the db to ensure secrets renamed on deletion still fit
      if (name.length() > SECRET_NAME_MAX_LENGTH) {
        throw new BadRequestException(format("secret cannot be created with name `%s` - secret "
            + "names must be %d characters or less", name, SECRET_NAME_MAX_LENGTH));
      }

      long now = OffsetDateTime.now().toEpochSecond();

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

      Optional<SecretSeries> secretSeries = secretSeriesDAO.getSecretSeriesByName(name);
      long secretId;
      if (secretSeries.isPresent()) {
        SecretSeries secretSeries1 = secretSeries.get();
        if (secretSeries1.currentVersion().isPresent()) {
          throw new DataAccessException(format("secret already present: %s", name));
        } else {
          // Unreachable unless the implementation of getSecretSeriesByName is changed
          throw new IllegalStateException(
              format("secret %s retrieved without current version set", name));
        }
      } else {
        secretId = secretSeriesDAO.createSecretSeries(name, creator, description, type,
            generationOptions, now);
      }

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

      return secretId;
    });
  }

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

}