class Communication::SmtpConfig < ApplicationRecord
  include Encryptable

  attr_accessor :decrypted_password

  enum service: { custom: 0, gmail_ssl: 1, gmail_tls: 2, office: 3 }
  enum security_certificate: { empty: 0, ssl: 1, tls: 2 }

  GMAIL_TLS = { port: '587', server_address: 'smtp.gmail.com', security_certificate: 'tls' }
  GMAIL_SSL = { port: '465', server_address: 'smtp.gmail.com', security_certificate: 'ssl' }
  OFFICE = { port: '587', server_address: 'smtp.office365.com', security_certificate: 'ssl' }
  MAP = { gmail_tls: GMAIL_TLS, gmail_ssl: GMAIL_SSL, office: OFFICE }

  belongs_to :school

  validates :username, :password, :server_address, :service, :port, :security_certificate,
    presence: true

  validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }, if: :custom?

  after_find :decrypt_password

  before_validation :set_service_settings, unless: :custom?

  before_save :validate_smtp
  before_save :encrypt_password, if: :password_changed?

  def password=(value)
    self.decrypted_password = value
    super(value)
  end

  private
    def set_service_settings
      MAP[service.to_sym].each { |field, value| self[field] = value }
    end

    def validate_smtp
      smtp = Net::SMTP.new(server_address, port)

      if tls?
        smtp.enable_starttls_auto
      elsif ssl?
        smtp.enable_ssl
      end

      begin
        smtp.start(sending_domain, username, decrypted_password, :login)
        smtp.finish
      rescue
        self.accepted = false
      else
        self.accepted = true
      end
    end

    def sending_domain
      custom? ? server_address.split('.', 2).last : username.split('@').last
    end

    def decrypt_password
      self.decrypted_password = decrypt(password)
    end

    def encrypt_password
      self[:password] = encrypt(password)
    end
end
