module Keys
  class Report < Keys::Base

    attributes :report_id, :pool_id, :status, :ldap_login

    # TODO: Refactor to use twirp generated client once custom headers are supported
    def self.all(pool_id, cursor, ldap_login)
      post(
        '/twirp/code.justin.tv.commerce.phanto.Phanto/GetKeyPoolReports',
        body: {
          :pool_id => pool_id,
          :cursor => cursor
        }.to_json,
        headers: Keys.ldap_header(ldap_login)
      )
    end

    def generate_report
      post(
        '/twirp/code.justin.tv.commerce.phanto.Phanto/GenerateKeyPoolReport',
        body: {
          :pool_id => self.pool_id,
        }.to_json,
        headers: Keys.ldap_header(ldap_login)
      )
    end

    def report_download_info
      post(
        '/twirp/code.justin.tv.commerce.phanto.Phanto/GetKeyPoolReportDownloadInfo',
        body: {
          :report_id => self.report_id,
        }.to_json,
        headers: Keys.ldap_header(ldap_login)
      )
    end

    def self.download_and_decrypt_report(download_url, decryption_key)
      decryption_key = Base64.decode64(decryption_key)

      http_conn = Faraday.new do |builder|
        builder.adapter Faraday.default_adapter
      end
      encrypted_file_response = http_conn.get download_url
      unless encrypted_file_response.success? && encrypted_file_response.status == 200
        return ''
      end

      encrypted_file = encrypted_file_response.body
      decrypt_s3_key_report(encrypted_file, decryption_key)
    end

    def self.decrypt_s3_key_report(encrypted_data, key)
      # IV (nonce) is the first 12 bytes
      nonce = encrypted_data[0..11]

      # Auth tag is the last 16 bytes
      auth_tag = encrypted_data[-16..-1]

      # Data is the remaining bytes in the middle
      encrypted_data = encrypted_data[12..-1]
      encrypted_data = encrypted_data[0..-17]

      decrypt(encrypted_data, key, nonce, auth_tag)
    end

    def self.decrypt(data, key, nonce, auth_tag)
      cipher = OpenSSL::Cipher.new('aes-256-gcm')
      cipher.decrypt
      cipher.key = key
      cipher.iv = nonce
      cipher.auth_tag = auth_tag
      cipher.update(data) + cipher.final
    end

  end
end