class Patrimonio::Transferencia < ApplicationRecord
  has_paper_trail
  
  include TradutorConcern
  include IncrementadorDeCodigoConcern
  include AASM
  include GeradorDeEventosContabeis

  attr_accessor :estado_do_bem
  attr_accessor :nome_responsavel

  belongs_to :unidade_gestora_origem, class_name: 'Loa::UnidadeGestora', foreign_key: :unidade_gestora_origem_id
  belongs_to :centro_de_custo_origem, class_name: 'Controladoria::CentroDeCusto', foreign_key: :centro_de_custo_origem_id
  belongs_to :responsavel_origem, class_name: 'Controladoria::ResponsavelDoCentroDeCusto', foreign_key: :responsavel_origem_id
  belongs_to :orcamento, class_name: 'Orcamento'

  has_many :dados_dos_destinos_das_transferencias, class_name: 'Patrimonio::DadosDoDestinoDaTransferencia'
  has_many :itens_da_transferencia, class_name: 'Patrimonio::ItemDaTransferencia'

  accepts_nested_attributes_for :dados_dos_destinos_das_transferencias, allow_destroy: true
  accepts_nested_attributes_for :itens_da_transferencia, allow_destroy: true

  validates_presence_of :unidade_gestora_origem_id, :centro_de_custo_origem_id, :data_da_transferencia, :tipo

  validates :data_da_transferencia, data_nao_pode_estar_no_futuro: true
	validates :data_da_transferencia, sabado_ou_domingo_ou_feriado: true
  validate :data_nao_pode_ser_diferente_do_ano_corrente
  validate :valida_se_ja_houve_envio_do_sim

  validates :dados_dos_destinos_das_transferencias, uniq_nested_attributes: { atributo: :id, mensagem: "unidade gestora deve ser única dentro de uma transferência" }
  validates_associated :itens_da_transferencia

  before_save :gera_numero_da_transferencia, if: Proc.new { new_record? || data_da_transferencia_changed? }

  after_destroy :remove_dependentes

  enum tipo: { por_tombamento: 1, por_lote: 2, por_lote_e_tombamento: 3}
  enum status: { aberto: 1, confirmado: 2, enviado_ao_patrimonio: 3, recusado: 4 }

  scope :tombamento_na_transferencia, -> (tombo) {
    joins(itens_da_transferencia: :bem_patrimonial).where("LTRIM(patrimonio_bens_patrimoniais.numero_do_tombamento, '0') = ?", tombo.to_i.to_s)
  }

  def self.ransackable_scopes(auth_object = nil)
    [:tombamento_na_transferencia]
  end

  aasm column: :status, enum: true, whiny_transitions: false do
    state :aberto, :initial => true
    state :confirmado
    state :enviado_ao_patrimonio
    state :recusado
    
    event :enviar_ao_patrimonio do
      transitions from: :aberto, to: :enviado_ao_patrimonio do
        guard do
          self.aberto? && self.contem_itens?
        end
      end
    end

    event :confirmar_transferencia do
      transitions from: [:aberto, :enviado_ao_patrimonio], to: :confirmado do
        guard do
          (self.aberto? || self.enviado_ao_patrimonio?) && self.contem_itens?
        end
        after do
          self.itens_da_transferencia.each do |item_da_transferencia|
            item_da_transferencia.atualiza_localizacao
          end
        end
      end
    end

    event :recusar_transferencia do
      transitions from: :enviado_ao_patrimonio, to: :recusado do
        guard do
          self.enviado_ao_patrimonio? && self.contem_itens?
        end
      end
    end

    event :retornar_para_aberto do
      transitions from: [:confirmado, :recusado], to: :aberto do
        guard do 
          (self.confirmado? || self.recusado?)
        end
        after do
					self.voltar_etapa_de_itens_e_remover_dependencias if self.confirmado?
				end
      end
    end

  end

  def gera_numero_da_transferencia
		gerar_codigo(data_da_transferencia, :numero_da_transferencia, :data_da_transferencia, :orcamento_id, self.orcamento_id)
	end

  def somente_um_destino?
		self.dados_dos_destinos_das_transferencias.size == 1
	end

  def contem_itens?
    self.itens_da_transferencia.size > 0
  end

  def voltar_etapa_de_itens_e_remover_dependencias
    self.itens_da_transferencia.each do |item_da_transferencia|
      bem = Patrimonio::BemPatrimonial.find_by(id: item_da_transferencia.bem_patrimonial.id)
      localizacao = Patrimonio::LocalizacaoDoBem.where(bem_patrimonial: bem.id, centro_de_custo: item_da_transferencia.centro_de_custo.id).last
      responsavel = Patrimonio::ResponsavelDoBemPatrimonial.where(bem_patrimonial: bem.id).last
      localizacao.destroy unless localizacao.nil?
      responsavel.destroy unless responsavel.nil?

      ulti_local = Patrimonio::LocalizacaoDoBem.where(bem_patrimonial: bem.id).last
      bem.update_columns(unidade_gestora_id: self.unidade_gestora_origem.id, localizacao_atual_id: ulti_local.id)
    end

	end

  def remove_dependentes
    ActiveRecord::Base.connection.execute("DELETE FROM patrimonio_dados_dos_destinos_das_transferencias WHERE transferencia_id = #{self.id}")
    ActiveRecord::Base.connection.execute("DELETE FROM patrimonio_itens_da_transferencia WHERE transferencia_id = #{self.id}")

  end

  def data_nao_pode_ser_diferente_do_ano_corrente
    if data_da_transferencia.present? && data_da_transferencia.year.to_i != orcamento.exercicio.to_i
      errors.add(:data_da_transferencia, "Não pode ser diferente do ano/orçamento corrente.")
    end
  end

  def valida_se_ja_houve_envio_do_sim
    if existe_lote_do_sim?
			errors.add(:data_da_transferencia, 'O SIM do mês já foi enviado')
      elsif mes_bloqueado?
			errors.add(:data_da_transferencia, 'O mês do objeto está bloqueado, solicite o desbloqueio ao administrador')
		end
	end

	def existe_lote_do_sim?
		if data_da_transferencia.present?
			lote_sim = Tcm::Lote.find_by(
				orcamento_id: orcamento_id,
				tipo: [Tcm::Lote.tipos[:todos], Tcm::Lote.tipos[:contabilidade]],
				mes_de_referencia: data_da_transferencia.month,
				situacao: [Tcm::Lote.situacoes[:gerado], Tcm::Lote.situacoes[:finalizado]]
			)

			return lote_sim.present?
		end

		return false
	end

end