class Licitacao::ItemDoOrcamentoDaDespesaDoApostilamento < ApplicationRecord
  has_paper_trail

  belongs_to :item_do_contrato, class_name: 'Licitacao::ItemDoContrato', required: true
  belongs_to :orcamento_da_despesa_do_apostilamento, class_name: 'Licitacao::OrcamentoDaDespesaDoApostilamento', required: true

  delegate :itens_do_orcamento_da_despesa_do_apostilamento, to: :orcamento_da_despesa_do_apostilamento, allow_nil: true

  validates_presence_of :quantidade, :saldo

  validates_uniqueness_of :item_do_contrato_id, scope: :orcamento_da_despesa_do_apostilamento_id, if: :persisted?

  validate :item_do_contrato_deve_ser_unico, if: :new_record?
  validate :quantidade_deve_ser_menor_igual_ao_item_do_contrato, if: Proc.new { item_do_contrato.present? && quantidade.present? }
  validate :total_deve_ser_menor_igual_ao_item_do_contrato, if: Proc.new { item_do_contrato.present? && saldo.present? }

  def possui_itens_duplicados?
    itens_do_orcamento_da_despesa_do_apostilamento.reject(&:marked_for_destruction?).map(&:item_do_contrato_id).compact
      .select { |item_do_contrato_id| item_do_contrato_id == self.item_do_contrato_id }.size > 1
  end

  private

  def item_do_contrato_deve_ser_unico
    errors.add(:item_do_contrato_id, 'deve ser único') if possui_itens_duplicados?
  end

  def quantidade_deve_ser_menor_igual_ao_item_do_contrato
    errors.add(:quantidade, 'não pode ser maior que a quantidade disponível') if quantidade > item_do_contrato.quantidade_atual
  end

  def total_deve_ser_menor_igual_ao_item_do_contrato
    valor_total_item_do_contrato = item_do_contrato.valor_total

    errors.add(:saldo, "não pode ser maior que #{valor_total_item_do_contrato}") if saldo > valor_total_item_do_contrato
  end
end
