class Patrimonio::ImportacaoDeDadosPatrimonial < ApplicationRecord
  has_paper_trail
	include AASM

	enum status: { aguardando_carregamento: 1, carregado: 2, recarregado: 3, cancelado: 4, concluido: 5 }

  attr_default :data_de_importacao, Date.today
	
	has_many :bens_da_importacao_de_dados_patrimoniais, class_name: 'Patrimonio::BensDaImportacaoDeDadosPatrimonial', dependent: :destroy
  has_many :bens_patrimoniais, through: :bens_da_importacao_de_dados_patrimoniais

  accepts_nested_attributes_for :bens_da_importacao_de_dados_patrimoniais, allow_destroy: true

	has_attached_file :documento
	validates_attachment_content_type :documento, content_type: ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']

	validates_attachment_size :documento, in: 0..7.megabytes

  validates_presence_of :nome, :data_de_importacao, :documento

	def tipo_de_label
    if self.aguardando_carregamento?
      'info'
    else
      'success'
    end
  end

	aasm column: :status, enum: true, whiny_transitions: false do
		state :aguardando_carregamento, :initial => true
		state :carregado
    state :cancelado
    state :concluido

    event :carregar_dados_da_planilha do
			transitions from: :aguardando_carregamento, to: :carregado do
        guard do
          self.data_de_importacao.present? && self.documento.present? && self.aguardando_carregamento?
        end
        after do
          self.verifica_e_insere_bens_da_importacao_de_dados_patrimoniais
        end
      end
    end

    event :gerar_bens_novos do
			transitions from: :carregado, to: :concluido do
        guard do
          self.data_de_importacao.present? && self.documento.present? && self.carregado?
        end
        after do
          self.criar_bens_novos
        end
      end
    end
	end

  def eh_editavel?
		aguardando_carregamento? || carregado?
	end

  def bens_inaptos_para_importacao
    self.bens_da_importacao_de_dados_patrimoniais.where(bem_patrimonial_id: nil).where(item_id: nil)
  end

  def bens_aptos_para_importacao
    self.bens_da_importacao_de_dados_patrimoniais.where.not(item_id: nil, bem_patrimonial_id: nil)
  end

  def criar_bens_novos
    bens_para_atualizar = self.bens_da_importacao_de_dados_patrimoniais
    if self.may_gerar_bens_novos?
      bens_da_importacao = self.bens_da_importacao_de_dados_patrimoniais.where(bem_patrimonial_id: nil).group_by{|bem| bem.item}
      bens_da_importacao.each do |item, bens_da_importacao|
        dados_extras = self.gera_dados_extras_do_bem(bens_da_importacao.first)
        
        bens_da_importacao.each do |bem_da_importacao|
          bem_da_importacao.gerar_bem_patrimonial(dados_extras)
          bem_patrimonial = bem_da_importacao.bem_patrimonial
          next unless bem_patrimonial.present?

          estado = case bem_da_importacao.conservacao.try(:strip).try(:upcase)
          when 'BOM' then :bom
          when 'NOVO' then :novo
          when 'REGULAR' then :regular
          when 'PÉSSIMO', 'PESSIMO' then :pessimo
          when 'OCIOSO' then :ocioso
          when 'RECUPERÁVEL', 'RECUPERAVEL' then :recuperavel
          when 'ANTIECONÔMICO', 'ANTIECONOMICO' then :antieconomico
          when 'INSERVÍVEL', 'INSERVIVEL', 'INSERVIVEL IRRECUPERAVEL' then :inservivel_irrecuperavel
          else
            :novo
          end
          next unless estado

          Patrimonio::ConservacaoDoBem.create!(
            bem_patrimonial: bem_patrimonial,
            estado_do_bem: estado,
            data_da_conservacao: bem_patrimonial.data_do_tombamento
          )
        end
      end
    end

    bens_para_atualizar.each do |bem_importado|
      tombo_atual_curto = bem_importado.tombo_atual.to_s
      tombo_atual_longo = tombo_atual_curto.rjust(8, '0')

      tombo_anterior_curto = bem_importado.tombo_anterior.to_s
      tombo_anterior_longo = tombo_anterior_curto.rjust(8, '0')

      bem_importado.gera_localizacao_inicial(bem_importado.bem_patrimonial)

      bem_existente = Patrimonio::BemPatrimonial.find_by(
        'numero_do_tombamento IN (?) OR numero_tombamento_antigo IN (?)',
        [tombo_atual_curto, tombo_atual_longo, tombo_anterior_curto, tombo_anterior_longo],
        [tombo_atual_curto, tombo_atual_longo, tombo_anterior_curto, tombo_anterior_longo]
      )

        estado = case bem_importado.conservacao.try(:strip).try(:upcase)
        when 'BOM' then :bom
        when 'NOVO' then :novo
        when 'REGULAR' then :regular
        when 'PÉSSIMO', 'PESSIMO' then :pessimo
        when 'OCIOSO' then :ocioso
        when 'RECUPERÁVEL', 'RECUPERAVEL' then :recuperavel
        when 'ANTIECONÔMICO', 'ANTIECONOMICO' then :antieconomico
        when 'INSERVÍVEL', 'INSERVIVEL', 'INSERVIVEL IRRECUPERAVEL' then :inservivel_irrecuperavel
        else
          :novo
        end
        next unless estado

        Patrimonio::ConservacaoDoBem.create!(
          bem_patrimonial: bem_existente,
          estado_do_bem: estado,
          data_da_conservacao: bem_existente.data_do_tombamento
        )
      
      if bem_existente.present?
        bem_existente.update(
          numero_do_tombamento: bem_importado.tombo_atual || bem_existente.numero_do_tombamento,
          numero_tombamento_antigo: bem_importado.tombo_anterior || bem_existente.numero_tombamento_antigo
        )
        bem_importado.update(bem_patrimonial_id: bem_existente.id)
      end
    end
  end

  def gera_dados_extras_do_bem(referencia_bem)
    dados_extras = Patrimonio::DadosExtrasDoBem.new(
      natureza_do_bem: 1, tipo_de_ingresso: 7, valor_de_aquisicao: referencia_bem.valor,
      gerou_bens: true, modelo: referencia_bem.modelo, vida_util: 10, porcentagem_valor_residual: 0.10,
      valor_residual: (referencia_bem.valor_residual.nil? ? (referencia_bem.valor_aquisicao * 0.10) : referencia_bem.valor_residual),
      valor_de_aquisicao: referencia_bem.valor_aquisicao
    )
    dados_extras.save(validate: false)

    return dados_extras
  end

	def verifica_e_insere_bens_da_importacao_de_dados_patrimoniais
    documento_xlsx = Paperclip.io_adapters.for(self.documento)
    arquivo = RubyXL::Parser.parse(documento_xlsx)
  
    arquivo.worksheets.each do |tabela|
      (1..tabela.sheet_data.size).each do |line|
        data_linha = tabela.sheet_data[line]
        next unless data_linha.present?
  
        campos = %w[
          orgao_unidade secretaria setor id_centro_custo data_cadastro tombo_atual tombo_anterior descricao_bens especificacao
          marca modelo serie chassi cor conservacao grupo subgrupo situacao aquisicao nota_fiscal data_aquisicao data_tombamento
          valor_aquisicao valor_residual valor_liquido vida_util meses valor_depreciacao_mensal meses_depreciados depreciado_ate_agora valor_atualizado natureza_tce fornecedor
          fonte_de_recurso data_empenho empenho classificacao baixa data_vistoria nome_vistoriador data_vistoria_dois
          nome_vistoria_dois data_vistoria_tres nome_vistoria_tres observacao 
        ]        
  
        valores = (0...campos.size).map { |i| data_linha[i]&.value }
        descricao_elemento = Hash[campos.zip(valores)]
  
        bem_importado = Patrimonio::BensDaImportacaoDeDadosPatrimonial.new(descricao_elemento)
        bem_importado.importacao_de_dados_patrimonial_id = self.id
  
        # Busca do bem patrimonial pelo número de tombamento
        tombo_formatado = ->(tombo) { tombo.to_s.gsub(/^0+/, '') }
  
        bem_patrimonial = nil
        [bem_importado.tombo_atual, bem_importado.tombo_anterior].each do |tombo|
          next unless tombo.present?
  
          bem_patrimonial ||= Patrimonio::BemPatrimonial.find_by(
            "LTRIM(patrimonio_bens_patrimoniais.numero_do_tombamento, '0') = ? AND tipo_de_poder = ?",
            tombo_formatado.call(tombo), 1
          )
        end
  
        bem_importado.bem_patrimonial_id = bem_patrimonial.id if bem_patrimonial.present?
  
        # Busca do item por nome com unaccent/similarity
        if bem_importado.descricao_bens.present?
          descricao_bens = bem_importado.descricao_bens.strip
  
          item = ::Base::Item.find_by(
            "unaccent(UPPER(descricao)) = unaccent(?) OR similarity(unaccent(UPPER(descricao)), unaccent(?)) > 0.50",
            descricao_bens.upcase, descricao_bens
          )

  
          bem_importado.item_id = item.id if item.present?
        end
  
        bem_importado.save
      end
    end
  end
  
end
