class Pca::Acao < ApplicationRecord
	include AASM
	include TradutorConcern
	has_paper_trail

	validates_presence_of :unidade_orcamentaria_id, :categoria_de_despesa, :tipo_de_contratacao, :prioridade, :data_de_cadastro, :data_de_previsao_da_contratacao, :objeto, :responsavel_id
	
	belongs_to :orcamento, class_name: 'Orcamento'
	belongs_to :unidade_orcamentaria, class_name: 'Loa::UnidadeOrcamentaria', foreign_key: 'unidade_orcamentaria_id'
	belongs_to :responsavel, class_name: 'Base::AgentePublicoMunicipal'

	has_many :orcamentos_da_despesa_por_acao, class_name: 'Pca::OrcamentoDaDespesaPorAcao', dependent: :destroy
	has_many :orcamentos_da_despesa, through: :orcamentos_da_despesa_por_acao, class_name: "Loa::OrcamentoDaDespesa"
	has_many :tipos_de_despesa_por_acao, class_name: 'Pca::TipoDeDespesaPorAcao', dependent: :destroy
	has_many :documentos_da_acao, dependent: :destroy
	has_many :criticas_de_envio_pncp, as: :modulo, class_name: "Pncp::CriticasDeEnvio"
	has_many :itens_da_acao, class_name: 'Pca::ItemDaAcao', inverse_of: :acao, dependent: :destroy
	has_many :categorias_da_acao, class_name: 'Pca::CategoriaDaAcao', inverse_of: :acao, dependent: :destroy
	has_many :categorias, through: :categorias_da_acao
	has_many :subcategorias, through: :categorias_da_acao
	has_many :acoes_do_etp, class_name: 'Licitacao::AcaoDoEtp'
  has_many :etps, through: :acoes_do_etp, source: :etp

	attr_default :enviado_pncp, false
	attr_default :envia_pncp, true

	accepts_nested_attributes_for :tipos_de_despesa_por_acao, reject_if: :all_blank, allow_destroy: true
	accepts_nested_attributes_for :itens_da_acao, reject_if: :all_blank, allow_destroy: true
	accepts_nested_attributes_for :categorias_da_acao, reject_if: :all_blank, allow_destroy: true

	validates :itens_da_acao, uniq_nested_attributes: { atributo: :item_id, mensagem: "item deve ser único dentro de uma ação" }
	validates :tipos_de_despesa_por_acao, uniq_nested_attributes: { atributo: :tipo_de_despesa, mensagem: "Tipo de Despesa deve ser único dentro de uma Ação" }
	validates :categorias_da_acao, uniq_nested_attributes: { atributo: :subcategoria_id, mensagem: "subcategoria deve ser única dentro de uma ação" }
	validate :valida_exercicio

	validates_associated :categorias_da_acao
	validates_associated :itens_da_acao

	scope :ano_atual, -> (comeco_de_ano, fim_de_ano) { where("data_de_previsao_da_contratacao >= ? AND data_de_previsao_da_contratacao <= ?", comeco_de_ano, fim_de_ano)}
	scope :ano_seguinte, -> (comeco_de_ano, fim_de_ano) { where("data_de_previsao_da_contratacao >= ? AND data_de_previsao_da_contratacao <= ?", comeco_de_ano, fim_de_ano)}


	enum prioridade: {
		baixa: 1,
		media: 2, 
		alta: 3
	}

	enum tipo_de_contratacao: {
		nova_contratacao: 1,
		renovacao_prorrogacao: 2,
		sem_contrato: 3,
		renovacao_nova_contratacao: 4,
		nova_contratacao_arp: 5
	}

	enum categoria_de_despesa: {
		custeio: 1,
		investimento: 2,
		custeio_e_investimento: 3
	}

	enum forma_de_contratacao_modalidade: {
		processo_licitatorio: 1,
		dispensa_de_licitacao: 2,
		inexigibilidade_de_licitacao: 3,
		carona: 4,
		parceria_osc: 5,
		credenciamento: 6
	}

	enum forma_de_contratacao_modalidade_de_licitacao: {
		pregao: 1,
		concorrencia_publica: 2,
		concurso: 3,
		dialogo_competitivo: 4,
		chamamento_publico: 5,
		dispensa_de_chamamento: 6,
		inexigibilidade_de_chamamento: 7,
		chamada_publica: 8,
		tomada_de_preco: 9,
		nao_de_aplica: 10
	}

	enum status: {
		aberto: 1,
		fechado: 2,
		em_estudo: 3,
		em_execucao:4
	}

	after_create :define_numero
	
	aasm column: :status, enum: true, whiny_transitions: false do
		state :aberto, :initial => true
		state :fechado
		state :em_estudo
		state :em_execucao

		event :fechar do
			transitions from: :aberto, to: :fechado
		end

		event :voltar_para_aberto do
			transitions from: :fechado, to: :aberto
		end
	end
	
	def define_numero
		ultimo_numero = ActiveRecord::Base.connection.exec_query("
			SELECT MAX(CAST(ac.numero AS INTEGER)) AS max_value
			FROM pca_acoes ac
			INNER JOIN loa_unidades_orcamentarias uo ON uo.id = ac.unidade_orcamentaria_id
			INNER JOIN loa_orgaos org ON org.id = uo.orgao_id
			WHERE uo.codigo = '#{self.unidade_orcamentaria.codigo}'
			AND org.codigo = '#{self.unidade_orcamentaria.orgao.codigo}'
			AND EXTRACT(YEAR FROM ac.data_de_previsao_da_contratacao) = #{self.data_de_previsao_da_contratacao.year.to_i}
		")[0]["max_value"]

		numero_disponivel = !ultimo_numero.present? ? "#{self.unidade_orcamentaria.orgao.codigo}#{self.unidade_orcamentaria.orgao.codigo}#{sprintf('%04d', ultimo_numero.to_i + 1)}" : ultimo_numero + 1
		self.numero = numero_disponivel
		self.save!
	end

	def valor_da_acao
		if self.orcamentos_da_despesa_por_acao.any?
			self.orcamentos_da_despesa_por_acao.sum(&:valor)
		else
			0
		end
	end

	def itens_to_pncp
		self.orcamentos_da_despesa_por_acao.map{|f| f.to_pca}
	end

	def cnpj_pncp
		unidade_orcamentaria.unidade_gestora.orgao_pncp.cnpj
	end

	def categorias_dos_itens
		self.categorias_da_acao.map(&:categoria_do_item).flatten
	end

	def valida_exercicio
		errors.add(:data_de_previsao_da_contratacao, 'A data de previsão da contratação, não está dentro do exercício selecionado.') if self.unidade_orcamentaria.orgao.orcamento.exercicio.to_i+1  != self.data_de_previsao_da_contratacao.year.to_i
	end
end
