# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/

class PGPKeypair < ApplicationModel
  validates :fingerprint, uniqueness: { case_sensitive: true }

  def self.create_private_keys(raw, secret)
    Sequoia.emails_of(keys: raw).each do |address|
      downcased_address = address.downcase
      public_key = find_each.detect do |certificate|
        certificate.email_addresses.include?(downcased_address)
      end

      unless public_key
        raise Exceptions::UnprocessableEntity,
              'The public key for this private key could not be found.'
      end

      public_key.update!(private_key: raw, private_key_secret: secret)
    end
  end

  def self.create_public_keys(raw)
    create!(public_key: raw)
  end

  def self.for_sender_email_address(address)
    downcased_address = address.downcase
    where.not(private_key: nil).find_each.detect do |certificate|
      certificate.email_addresses.include?(downcased_address)
    end
  end

  def self.for_recipient_email_addresses!(addresses)
    certificates        = []
    remaining_addresses = addresses.map(&:downcase)
    find_each do |certificate|
      # intersection of both lists
      certificate_for = certificate.email_addresses & remaining_addresses
      next if certificate_for.blank?

      certificates.push(certificate)

      # subtract found recipient(s)
      remaining_addresses -= certificate_for

      # end loop if no addresses are remaining
      break if remaining_addresses.blank?
    end

    return certificates if remaining_addresses.blank?

    raise ActiveRecord::RecordNotFound,
          "Can't find PGP encryption certificates for: #{remaining_addresses.join(', ')}"
  end

  def public_key=(string)
    self.fingerprint = Sequoia.fingerprints_of(keys: string).first
    self[:public_key] = string
  end

  def email_addresses
    @email_addresses ||= Sequoia.emails_of(keys: public_key)
  end
end
