class GestaoDeEstoque::DevolucaoDeMaterial < ApplicationRecord
  has_paper_trail

	include AASM
  include TradutorConcern
  include IncrementadorDeCodigoConcern

  enum tipo_de_devolucao: { devolucao_total: 1, devolucao_parcial: 2 }
  enum status: { aberto: 1, enviado_ao_almoxarifado: 2, recusado: 3, recebido: 4, confirmado: 5, cancelado: 6 }

  attr_default :status, :aberto

  belongs_to :origem, polymorphic: true, required: true, foreign_key: :origem_id
  belongs_to :orcamento, class_name: "Orcamento"

  has_many :itens_das_devolucoes_de_materiais, class_name: "GestaoDeEstoque::ItemDaDevolucaoDeMaterial", dependent: :destroy
  has_many :itens, through: :itens_das_devolucoes_de_materiais

  accepts_nested_attributes_for :itens_das_devolucoes_de_materiais, allow_destroy: true

  validates_presence_of :data_da_devolucao, :tipo_de_devolucao

	scope :validos, -> { where.not(status: [:recusado, :cancelado]) }

	before_validation :atribui_numero_disponivel
  # after_save :atualiza_requisicao

  aasm column: :status, enum: true, whiny_transitions: false do
		state :aberto, :initial => true
    state :enviado_ao_almoxarifado
		state :recusado
		state :recebido
    state :confirmado
    state :cancelado

    event :enviar_para_almoxarifado do
      transitions from: :aberto, to: :enviado_ao_almoxarifado
    end

    event :cancelar do
      transitions from: :aberto, to: :cancelado
    end

		event :recusar do
			transitions from: :enviado_ao_almoxarifado, to: :recusado do
        guard do
          self.motivo_da_recusa.present?
        end
      end
		end

    event :confirmar_recebimento do
      transitions from: :enviado_ao_almoxarifado, to: :recebido
    end

    event :receber_devolucao do
      transitions from: [:aberto, :enviado_ao_almoxarifado], to: :recebido do
        guard do
          (self.aberto? || self.enviado_ao_almoxarifado?)
        end
      end
    end

    event :confirmar_devolucao do
      transitions from: :recebido, to: :confirmado do
        guard do
          self.recebido?
        end
        after do
          self.itens_das_devolucoes_de_materiais.each do |item_da_devolucao|
            item_da_devolucao.adiciona_ou_atualiza_saldo_no_estoque
          end
        end
      end
    end
	end

  def atualiza_requisicao
    if self.requisicao_de_material.devolucoes_de_materiais.validos.size > 0
      if self.requisicao_de_material.saldo_disponivel_para_devolucao == 0
        self.requisicao_de_material.status = :devolvido_ao_almoxarifado
      else
        self.requisicao_de_material.status = :devolvido_parcialmente_ao_almoxarifado
      end
    else
      if self.requisicao_de_material.itens_das_requisicoes_de_materiais.sum(:quantidade_requisitada) == self.requisicao_de_material.itens_das_requisicoes_de_materiais.sum(:quantidade_atendida)
        self.requisicao_de_material.status = :atendido
      else
        self.requisicao_de_material.status = :atendido_parcialmente
      end
    end
    self.requisicao_de_material.save
  end

  def atribui_numero_disponivel
    if self.data_da_devolucao.present?
      gerar_codigo(self.data_da_devolucao, :numero_da_devolucao, :data_da_devolucao, :orcamento_id, self.orcamento_id)
    end
  end

  def retorna_se_ja_existe_devolucao(origem, origem_type)
    if origem_type == 'GestaoDeEstoque::Transferencia'
      GestaoDeEstoque::DevolucaoDeMaterial.find_by(origem_id: origem_id, origem_type: origem_type).try(:tipo_de_devolucao) 
    end
  end

  def quantidade_total_do_item(item)
    if self.origem_type == 'GestaoDeEstoque::Transferencia'
      quantidade_item = self.origem.itens_da_transferencia.where(item_id: item).sum(:quantidade).to_f rescue 0
    elsif self.origem_type == 'Administrativo::RequisicaoDeMaterial'
      quantidade_item = self.origem.itens_das_requisicoes_de_materiais.where(item_id: item).sum(:quantidade_requisitada).to_f rescue 0
    end
    return quantidade_item
  end
end
