module Licitacao
class ProcessosController < ApplicationController
	include LicitacaoHelper
	include ControllerConcern
	include Licitacao::ProcessosHelper
	include ProcessoControllersConcern

	skip_before_action :verifica_se_tem_orcamento_na_sessao!, only: [:contratos], raise: false
	skip_before_action :verifica_se_sessao_eh_de_licitacao!, only: [:contratos, :unidades_orcamentarias, :ganhadores_dos_lotes], raise: false

	before_action :authenticate_usuario!
	before_action :autoriza_usuario!, except: [:atualizar_licitantes, :contratos, :editar_dados_do_sim, :atualizar_dados_do_sim, :enviar_para_sim, :confirmar_cancelamento, :adiciona_licitantes, :busca_licitantes, :voltar_para_aberto, :voltar_para_fase_de_lances, :voltar_para_enviado_para_comissao, :deleta_processo, :editar_data_de_adjudicacao, :atualiza_data_de_adjudicacao, :editar_data_da_homologacao, :atualiza_data_da_homologacao, :confirmar_revogacao, :revogar, :caronas]
	before_action :set_processo, except: [:index, :contratos, :caronas]
  before_action :acao_corresponde_ao_status_do_pedido?, except: [:edit, :index, :new, :create, :contratos, :caronas]
	before_action :testa_autorizacao_em_update, only: [:homologar, :editar_licitantes, :atualizar_licitantes]
	before_action :valida_adicionar_remover_licitante, only: [:editar_licitantes]
  before_action :disponibiliza_configuracao, only: [:show]

	before_action only: [:atualizar_licitantes] do |controller|
		redirect_to @processo, alert: 'lista não pode ficar em branco. Alterações não foram salvas.' unless params[:licitacao_processo]
	end

	# GET /licitacao/processos
	def index
		@orcamentos = Orcamento.all.order(exercicio: :desc)
		@action_processos = nil
		@url_processos = nil

		orcamento =
			unless query_params["orcamento_id_eq"].blank?
				Orcamento.find(query_params["orcamento_id_eq"])
			else
				contexto_atual
			end

		@unidades_orcamentarias = orcamento.unidades_orcamentarias.order(:codigo, :nome)

		@modalidade_de_processo =
			if params[:dispensa]
				@action_processos = "dispensa"
				@url_processos = dispensa_licitacao_processos_path
				Licitacao::Projeto.modalidades_do_processo[:dispensa_de_licitacao]
			elsif params[:inexigibilidade]
				@action_processos = "inexigibilidade"
				@url_processos = inexigibilidade_licitacao_processos_path
				Licitacao::Projeto.modalidades_do_processo[:inexigibilidade_de_licitacao]
			elsif params[:parcerias]
				@action_processos = "parcerias"
				@url_processos = parcerias_licitacao_processos_path
				Licitacao::Projeto.modalidades_do_processo[:parceria_osc]
			elsif params[:processo_licitatorio]
				@action_processos = "processo_licitatorio"
				@url_processos = licitacao_processos_path
				Licitacao::Projeto.modalidades_do_processo[:processo_licitatorio]
			elsif params[:outros]
				@action_processos = "outros"
				@url_processos = outros_licitacao_processos_path
				Licitacao::Projeto.modalidades_do_processo[:outro]
			else
				@action_processos = "processo_licitatorio"
				@url_processos = licitacao_processos_path
				Licitacao::Projeto.modalidades_do_processo[:processo_licitatorio]
			end


		@processos_filtrados =
		if contabilidade_atual.present? && params[:criado_na_contabilidade].present?
			@url_processos = contabilidade_processos_path
			orcamento.processos.joins(:pedido).where('licitacao_pedidos.criado_na_contabilidade = true').order("data_do_projeto desc")
		elsif current_usuario.desenvolvedor?
			orcamento.processos.despachados.where(modalidade_do_processo: @modalidade_de_processo).where.not(modalidade_de_licitacao: Licitacao::Projeto.modalidades_de_licitacao[:carona]).order("data_do_projeto desc")
		else
			current_usuario.processos.do_exercicio(orcamento.exercicio).despachados.where(modalidade_do_processo: @modalidade_de_processo).where.not(modalidade_de_licitacao: Licitacao::Projeto.modalidades_de_licitacao[:carona]).order("data_do_projeto desc")
		end

		@q = @processos_filtrados.search(params[:q])
		@processos = @q.result(distinct: true).paginate(page: params[:page], per_page: 10)
	end

	# GET /licitacao/processos/carona
	def caronas
		return if bloqueia_usuario_com_base_em 'read'
		@orcamentos = Orcamento.all.order(exercicio: :desc)
		@action_processos = nil
		@url_processos = nil

		orcamento = unless query_params["orcamento_id_eq"].blank?
			Orcamento.find(query_params["orcamento_id_eq"])
		else
			contexto_atual
		end
		@unidades_orcamentarias = orcamento.unidades_orcamentarias.order(:codigo, :nome)

		@action_processos = "carona"
		@url_processos = licitacao_processos_path

		@url_processos = carona_licitacao_processos_path
		@carona = Licitacao::Projeto.modalidades_de_licitacao[:carona]

		@processos_filtrados =
			if current_usuario.administrador?
				orcamento.processos.despachados.where(modalidade_de_licitacao: @carona).order("data_do_projeto desc")
			else
				current_usuario.processos.do_exercicio(orcamento.exercicio).despachados.where(modalidade_de_licitacao: @carona).order("data_do_projeto desc")
			end

		@q = @processos_filtrados.search(params[:q])
		@processos = @q.result(distinct: false).paginate(page: params[:page], per_page: 10)
	end

	def contratos
		if params[:unidade_orcamentaria_id].present? && params[:unidade_orcamentaria_id] != "undefined"
			projeto = Licitacao::Processo.find(params[:id])
			unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(params[:unidade_orcamentaria_id])
			if params[:fechado].present? && params[:fechado] == "true" && !params[:reconhecimento_de_divida].present?
				contratos = projeto.contratos.fechado.joins(unidade_orcamentaria_do_exercicio: :orgao).where(loa_orgaos:{codigo: unidade_orcamentaria.orgao.codigo}).where(loa_unidades_orcamentarias: {codigo: unidade_orcamentaria.codigo})
			else
				contratos = projeto.contratos.joins(unidade_orcamentaria_do_exercicio: :orgao).where(loa_orgaos:{codigo: unidade_orcamentaria.orgao.codigo}).where(loa_unidades_orcamentarias: {codigo: unidade_orcamentaria.codigo})
			end
			if !contratos.any? && projeto.contratos.any?
				unidades_de_todos_os_contratos_ids = projeto.contratos.pluck(:unidade_orcamentaria_do_exercicio_id)
				unidades_vinculadas = unidade_orcamentaria.unidades_orcamentaria_vinculada
						.where(unidade_orcamentaria_vinculada_id: unidades_de_todos_os_contratos_ids)
				if params[:fechado].present? && params[:fechado] == "true" && !params[:reconhecimento_de_divida].present?
					contratos = projeto.contratos.fechado.where(unidade_orcamentaria_do_exercicio_id: unidades_vinculadas.pluck(:unidade_orcamentaria_vinculada_id)) if unidades_vinculadas.any?
				else
					contratos = projeto.contratos.where(unidade_orcamentaria_do_exercicio_id: unidades_vinculadas.pluck(:unidade_orcamentaria_vinculada_id)) if unidades_vinculadas.any?
				end
			end
		else
			if params[:fechado].present? && params[:fechado] == "true" && !params[:reconhecimento_de_divida].present?
				contratos = Licitacao::Processo.find(params[:id]).contratos.fechado
			else
				contratos = Licitacao::Processo.find(params[:id]).contratos
			end
		end
		if params[:reconhecimento_de_divida].present? && params[:reconhecimento_de_divida] == "true"
			contratos = contratos.usado_no_reconhecimento_de_divida
		end

		render json: contratos.order(:numero), methods: [:descricao_contrato_de_obra, :cpf_ou_cnpj_e_nome, :pessoa_id]
	end

	# GET /licitacao/processos/1/unidades_orcamentarias
	def unidades_orcamentarias
		@processo = Processo.find( params[:id] )
		render json: @processo.unidades_orcamentarias
	end

	# GET /licitacao/processos/1/ganhadores_dos_lotes
	def ganhadores_dos_lotes
		@processo = Processo.find( params[:id] )
		render json: @processo.ganhadores_dos_lotes, methods: :empresa_nome
	end

	# GET /licitacao/processos/1
	def show
		@ids_duplicados = @processo.pessoas_do_projeto.group(:pessoa_id).having('count(pessoa_id) > 1').pluck(:pessoa_id)
	end

	# GET /licitacao/processos/1/edit
	def edit
		data_periodo = Date.new(contexto_atual.exercicio, 1, 1)
		@comissoes = Licitacao::Comissao.joins(:unidade_gestora, :membros_da_comissao).where(data_da_extincao: nil).where('orcamento_id = ? or orcamento_id is null', contexto_atual.id).where("loa_unidades_gestoras.data_encerramento >= ? or loa_unidades_gestoras.data_encerramento is null", data_periodo).where('de_parceria = ?', @processo.parceria_osc?).distinct.order(:id)
	end

	# PATCH/PUT /licitacao/processos/1
	def update
		if @processo.update(processo_params)
			redirect_to @processo, notice: 'Processo foi atualizado(a) com sucesso.'
		else
			data_periodo = Date.new(contexto_atual.exercicio, 1, 1)
			@comissoes = Licitacao::Comissao.joins(:unidade_gestora, :membros_da_comissao).where(data_da_extincao: nil).where('orcamento_id = ? or orcamento_id is null', contexto_atual.id).where("loa_unidades_gestoras.data_encerramento >= ? or loa_unidades_gestoras.data_encerramento is null", data_periodo).where('de_parceria = ?', @processo.parceria_osc?).distinct.order(:id)
			render :edit
		end
	end

	# PATCH/PUT /licitacao/processos/1/deleta_processo
	def deleta_processo
		return if bloqueia_usuario_com_base_em 'destroy'
		if @processo.voltar_para_aberto!
			redirect_to licitacao_projeto_path(@processo.id), notice: 'Processo deletado com sucesso!'
		else
			redirect_to licitacao_processo_path(@processo.id), notice: 'Não foi possível deletar o Processo.'
		end
	end

	# GET /licitacao/processos/1/editar_data_da_homologacao
	def editar_data_da_homologacao
		return if bloqueia_usuario_com_base_em 'update'
	end

	# PATCH	/licitacao/processos/1/atualiza_data_da_homologacao
	def atualiza_data_da_homologacao
		if @processo.atualiza_data_da_homologacao(params[:licitacao_processo][:data_da_homologacao].to_date)
			redirect_to @processo, notice: 'Processo foi atualizado(a) com sucesso.'
		else
			render :editar_data_da_homologacao
		end
	end

	# GET /licitacao/processos/1/editar_data_de_adjudicacao
	def editar_data_de_adjudicacao
		return if bloqueia_usuario_com_base_em 'update'
	end

	# PATCH	/licitacao/processos/1/atualiza_data_de_adjudicacao
	def atualiza_data_de_adjudicacao
		if @processo.atualiza_data_de_adjudicacao(params[:licitacao_processo][:data_de_adjudicacao].to_date)
			redirect_to @processo, notice: 'Processo foi atualizado(a) com sucesso.'
		else
			render :editar_data_de_adjudicacao
		end
	end

	# PATCH/PUT /licitacao/nao_enviar_para_sim
	def nao_enviar_para_sim
		if @processo.nao_envia_para_sim
			redirect_to @processo, notice: 'O processo foi marcado para não ser enviado para o SIM.'
		end
	end

	# PATCH/PUT /licitacao/enviar_para_sim
	def enviar_para_sim
		return if bloqueia_usuario_com_base_em 'nao_enviar_para_sim'
		if @processo.update_column(:envia_pro_sim, true)
			redirect_to @processo, notice: 'O processo foi marcado para ser enviado para o SIM.'
		end
	end

	# PATCH/PUT /licitacao/enviar_para_parecer
	def enviar_para_parecer
		if @processo.enviar_para_parecer!
			redirect_to @processo, notice: 'O processo foi enviado para o Parecer.'
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

	# PATCH /licitacao/processos/1/voltar_para_fase_de_lances
	def voltar_para_fase_de_lances
		return if bloqueia_usuario_com_base_em 'update'
		if @processo.voltar_para_fase_de_lances!
			redirect_to licitacao_processo_path(@processo), success: "O Processo foi reaberto com sucesso."
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

		# PATCH /licitacao/processos/1/voltar_para_enviado_para_comissao
		def voltar_para_enviado_para_comissao
			return if bloqueia_usuario_com_base_em 'update'
			if @processo.enviado_para_comissao!
				redirect_to licitacao_processo_path(@processo), success: "O Processo foi reaberto com sucesso."
			else
				mensagem_de_erro = if @processo.errors.any?
					"Ocorreu um erro, por favor confira se este está consistente"
				else
					"Não é possível passar da fase atual para a requisitada."
				end
				redirect_to @processo, alert: mensagem_de_erro
			end
		end

	# PATCH /licitacao/processos/1/voltar_para_aberto
	def voltar_para_aberto
		return if bloqueia_usuario_com_base_em 'update'
		if @processo.aberto!
			redirect_to licitacao_projeto_path(@processo), success: "O Projeto Básico foi reaberto com sucesso."
		else
			redirect_to licitacao_processo_path(@processo), alert: "Não foi possível reabrir o Projeto."
		end
	end

	# PATCH/PUT /licitacao/iniciar_processo
	def iniciar_processo
		if @processo.iniciar_processo!
			redirect_to @processo, notice: 'O processo foi iniciado.'
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

	def fracassar_processo
		if @processo.fracassar_processo!
			redirect_to @processo, notice: 'O processo foi marcado como fracassado.'
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

	# PATCH/PUT /licitacao/ir_para_sessao
	def ir_para_sessao
		if @processo.ir_para_sessao!
			redirect_to @processo, notice: 'O processo foi encaminhado para a fase de sessão.'
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

	def adjudicar
		if @processo.adjudicado!
			redirect_to @processo, notice: 'O processo foi adjudicado.'
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

	def desertar
		if @processo.desertar_processo!
			redirect_to @processo, notice: 'O processo foi desertado.'
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

	def encaminhar_parecer_final
		if @processo.encaminhar_parecer_final!
			redirect_to @processo, notice: 'O processo foi encaminhado ao parecer.'
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

	def enviar_para_homologacao
		if @processo.enviar_para_homologacao!
			redirect_to @processo, notice: 'O processo foi encaminhado para aguardando homologação.'
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			redirect_to @processo, alert: mensagem_de_erro
		end
	end


	# PATCH/PUT /licitacao/concluir_sessao
	def concluir_sessao
		if @processo.concluir_sessao!
			redirect_to @processo, notice: 'Sessão concluída.'
		else
			mensagem_de_erro = @processo.errors.any? ? @processo.errors.messages.values.join(",") : "Não é possível passar da fase atual para a requisitada."
			redirect_to @processo, alert: mensagem_de_erro
		end
	end

	# PATCH/PUT /licitacao/homologar
	def homologar
		if ( @processo.may_homologar? && @processo.homologar! ) || ( @processo.may_homologar_parcialmente? && @processo.homologar_parcialmente! )
			if @processo.pedido.projeto_simplificado? && !@processo.bid_obra_ou_servico
				redirect_to licitacao_projeto_path(@processo), notice: 'Projeto homologado com sucesso.'
			else
				redirect_to @processo, notice: 'Processo homologado com sucesso.'
			end
		else
			mensagem_de_erro = if @processo.errors.any?
				"Ocorreu um erro, por favor confira se este está consistente"
			else
				"Não é possível passar da fase atual para a requisitada."
			end
			if @processo.pedido.projeto_simplificado?
				redirect_to	licitacao_projeto_path(@processo), alert: mensagem_de_erro
			else
				redirect_to @processo, alert: mensagem_de_erro
			end
		end
	end

	#GET /licitacao/processos/1/licitantes
	def editar_licitantes
		@processo.pessoas_do_projeto.build if @processo.pessoas_do_projeto.empty?
		@pessoas = Base::Pessoa.includes(:tipo_de_pessoa).juridicas.fornecedores.where(ativo: :true)
	end

	#GET /licitacao/processos/1/busca_licitantes
	def busca_licitantes
		return if bloqueia_usuario_com_base_em 'editar_licitantes'
		@tipos_de_pessoa = Base::TipoDePessoa.all
		@q = Base::Pessoa.order(:id).ransack(query_params)
		@pessoas = @q.result(distinct: true)
		@categorias = Base::Categoria.where(id: @processo.pedido.categorias_do_pedido.pluck(:categoria_id))
		@subcategorias = Array.new

		if params[:q].present? && params[:q][:categorias_da_pessoa_categoria_id_eq].present?
			@subcategorias = Base::Categoria.find_by(id: params[:q][:categorias_da_pessoa_categoria_id_eq]).subcategorias rescue Array.new
		end

		if @pessoas.size > 100
			@qtd_removida = @pessoas.size - 100
			@pessoas = @pessoas.limit(100)
		end
	end

	#PATCH /licitacao/processos/1/adiciona_licitantes
	def adiciona_licitantes
		return if bloqueia_usuario_com_base_em 'editar_licitantes'
		if params[:pessoas] && params[:pessoas].size > 0
			quantidade = @processo.adiciona_licitantes(params[:pessoas])
			disponibiliza_dependencias_pessoas
			flash.now[:notice] = quantidade > 1 ? "#{quantidade} Licitantes adicionados com sucesso" : "#{quantidade} Licitante adicionado com sucesso"
			render :editar_licitantes

		else
			redirect_to busca_licitantes_licitacao_processo_path(@processo), alert: "Nenhum fornecedor foi selecionado."
		end
	end

	#PATCH /licitacao/processos/1/licitantes
	def atualizar_licitantes
		return if bloqueia_usuario_com_base_em 'editar_licitantes'

		pessoas_ids = []
		pessoas_params[:pessoas_do_projeto_attributes].to_h.each { |key, array|
			pessoas_ids << array[:pessoa_id].to_i if array[:pessoa_id].to_i != 0
		}
		@processo.assign_attributes(pessoas_params)
		if @processo.todos_os_licitantes_possuem_cnpj_diferente?(pessoas_ids) && @processo.save
			if params[:continuar_editando].present?
				disponibiliza_dependencias_pessoas
				flash.now[:notice] = "Licitantes cadastrados foram salvos com sucesso."
				render :editar_licitantes
			else
				redirect_to licitacao_processo_path(@processo) + "?tab=licitantes", notice: 'Processo foi atualizado com sucesso.'
			end
		else
			@pessoas = Base::Pessoa.includes(:tipo_de_pessoa).juridicas.fornecedores
			render :editar_licitantes
		end
	end

	#GET /licitacao/processos/1/editar_dados_do_sim
	def editar_dados_do_sim
		return if bloqueia_usuario_com_base_em 'update'
		disponibiliza_agentes_publicos_municipais
	end

	#PATCH /licitacao/processos/1/atualizar_dados_do_sim
	def atualizar_dados_do_sim
		@processo.assign_attributes( processo_params )
		if @processo.update_dados_do_sim
			redirect_to @processo, notice: 'Dados do SIM foram atualizados com sucesso.'
		else
			disponibiliza_agentes_publicos_municipais
			render :editar_dados_do_sim
		end
	end

	def fornecedores
		@pessoas_do_projeto = @processo.pessoas_do_projeto
		respond_to do |format|
			format.json
		end
	end

	def confirmar_cancelamento
		return if bloqueia_usuario_com_base_em 'cancelar'
	end

	def cancelar
		@processo.motivo_do_cancelamento = params[:licitacao_processo][:motivo_do_cancelamento]

		if @processo.cancelar!
			redirect_to @processo, notice: 'Processo foi cancelado com sucesso.'
		else
			render :confirmar_cancelamento
		end
	end

	def confirmar_revogacao
		return if bloqueia_usuario_com_base_em 'update'
	end

	def revogar
		@processo.justificativa_da_revogacao = params[:licitacao_processo][:justificativa_da_revogacao]

		if @processo.revogar!
			redirect_to @processo, notice: 'Processo foi revogado com sucesso.'
		else
			render :confirmar_revogacao
		end
	end

	private
	def testa_autorizacao_em_update
		return if bloqueia_usuario_com_base_em 'update'
	end

	def set_processo
		@processo = Processo.find( params[:id] )
	end

  def disponibiliza_configuracao
    @configuracao = Configuracao.last
  end

	def disponibiliza_agentes_publicos_municipais
		@agentes_publicos_municipais = Base::AgentePublicoMunicipal.all
	end

	# Permite apenas os parâmetros específicos
	def processo_params
		params.require(:licitacao_processo).permit(:numero_confirmado, :numero_do_processo, :comissao_id, :justificativa_da_revogacao, :data_de_envio_pro_sim, :data_de_autuacao, :agente_publico_municipal_id, :data_do_edital, :numero_do_edital, :data_da_homologacao, :data_de_adjudicacao, :responsavel_cotacao_sim_id, :responsavel_elaboracao_sim_id, :tipo_de_disputa_sim, :forma_de_contratacao_sim, :url_do_processo_eletronico, :pncp_id, :pncp_id_ata_sim)
	end

	def pessoas_params
		begin
			params.require(:licitacao_processo).permit(pessoas_do_projeto_attributes: [:id, :pessoa_id, :_destroy])
		rescue ActionController::ParameterMissing
			nil
		end
	end

	def acao_corresponde_ao_status_do_pedido?
		redirect_to @processo, alert: "Essa ação não é permitida nessa etapa" unless acao_permitida? @processo, action_name.to_sym
	end

	def valida_adicionar_remover_licitante
		begin
			@processo.valida_adicionar_remover_licitante
		rescue => e
			redirect_to @processo, alert: e.message
		end
	end

	def disponibiliza_dependencias_pessoas
		@pessoa = Base::Pessoa.new
		@pessoas = Base::Pessoa.includes(:tipo_de_pessoa).where(fornecedor: true)
	end

end
end
