class ZuoraConnect::AppInstanceBase

def kms_decrypt(value, field_name: nil, encryption_type: ZuoraConnect.configuration.encryption_type)

def kms_decrypt(value, field_name: nil, encryption_type: ZuoraConnect.configuration.encryption_type)
  kms_tries ||= 0
  original_encryption_type ||= encryption_type.dup

  case encryption_type
  when :direct
    result = kms_client.decrypt(ciphertext_blob: [value].pack("H*") ).plaintext 
    #Update original encryption
    if original_encryption_type != encryption_type && field_name.present?
      ZuoraConnect.logger.debug("Updating encryption to '#{original_encryption_type}', from '#{encryption_type}' for field '#{field_name}'", self.default_ougai_items)
      self.update_column(field_name, self.kms_encrypt(result, encryption_type: original_encryption_type))
    end
    return result
  when :envelope
    cipher = fetch_cipher('decrypt') 
    result = cipher.update(Base64.strict_decode64(value)) + cipher.final
    #Update original encryption
    if original_encryption_type != encryption_type && field_name.present?
      ZuoraConnect.logger.debug("Updating encryption to '#{original_encryption_type}', from '#{encryption_type}' for field '#{field_name}'", self.default_ougai_items)
      self.update_column(field_name, self.kms_encrypt(result, encryption_type: original_encryption_type))
    end
    return result
  else
    ZuoraConnect::Exceptions::Error.new("Invalid encryption method '#{encryption_type}'.")
  end
rescue ArgumentError, OpenSSL::Cipher::CipherError => ex
  if (
    ex.is_a?(ArgumentError) && ['invalid base64', 'data must not be empty'].include?(ex.message) ||
      ex.is_a?(OpenSSL::Cipher::CipherError) && ['wrong final block length', 'bad decrypt'].include?(ex.message)
  ) && encryption_type == :envelope && (kms_tries += 1) < 3
    ZuoraConnect.logger.warn("Fallback to encryption 'direct', from '#{encryption_type}'", ex, self.default_ougai_items)
    encryption_type = :direct 
    retry
  end
  raise#Add protection when decrypting
rescue Aws::KMS::Errors::InvalidCiphertextException => ex
  if encryption_type == :direct && (kms_tries += 1) < 3
    ZuoraConnect.logger.warn("Fallback to encryption 'envelope', from '#{encryption_type}'", ex, self.default_ougai_items)
    encryption_type = :envelope 
    retry
  end
  raise
rescue *AWS_AUTH_ERRORS => ex
  if (kms_tries += 1) < 3
    Rails.logger.warn(AWS_AUTH_ERRORS_MSG, ex)
    retry
  else
    Rails.logger.error(AWS_AUTH_ERRORS_MSG, ex)
    raise
  end
end