# frozen_string_literal: true
require 'openssl'
require 'base64'

class CryptSerializer
  attr_reader :cipher

  class << self
    # pulling from DB - return plain value
    def load value
      new.decrypt value
    end

    # saving to DB - return encrypted value
    def dump value
      new.encrypt value
    end
  end

  def initialize
    @cipher = OpenSSL::Cipher::AES.new(128, :CBC)
  end

  def encrypt(value)
    unless value.is_a?(String)
      raise "Attribute was supposed to be a `String`, but was instead a `#{value.class}`"
    end

    return nil if value.blank?

    cipher.encrypt
    parts = [cipher.random_key, cipher.random_iv, cipher.update(value) + cipher.final]

    Base64.urlsafe_encode64 Marshal.dump(parts)
  end

  def decrypt(value)
    return value if value.nil?

    parts = Marshal.load Base64.urlsafe_decode64(value)
    cipher.decrypt
    cipher.key = parts[0]
    cipher.iv = parts[1]

    cipher.update(parts[2]) + cipher.final
  end
end
