module Licitacao
	class ContratosController < ApplicationController
		include LicitacaoHelper
		include ControllerConcern
		include Licitacao::ContratosHelper
		include ContratoControllersConcern

		before_action -> { verifica_modulo_na_sessao(["licitacao", "controladoria", "administrativo", "obra", "contabilidade"]) }
		before_action :authenticate_usuario!

		before_action :autoriza_usuario!, except: [:editar_itens,:confirmar_cancelamento, :adicionar_dotacoes, :editar_dotacoes, :excluir_dotacao,
			:editar_data_de_envio_pro_sim, :atualizar_data_de_envio_pro_sim, :retornar_para_aberto, :editar_acoes_das_operacoes,
			:atualizar_acoes_das_operacoes, :editar_operacoes, :atualizar_operacoes, :editar_itens_dotacao_do_contrato,
			:atualiza_itens_dotacao_do_contrato, :editar_responsavel, :atualizar_responsavel, :retorna_dados_do_contrato,
			:editar_unidade_orcamentaria_do_exercicio, :atualizar_unidade_orcamentaria_do_exercicio, :solicitacoes, :cadastrar_responsavel_do_pedido, :envios_pncp
		]

		before_action :set_contrato, only: [:retorna_dados_do_contrato, :confirmar, :enviar_para_controladoria, :enviar_para_copfin, :finalizar,
			:cancelar,:confirmar_cancelamento,:edit, :update, :destroy, :editar_itens,:atualiza_itens,:quantidade_de_itens_disponiveis,
			:show, :editar_dotacoes, :atualiza_dotacoes, :nao_enviar_para_sim, :enviar_para_sim, :editar_data_de_envio_pro_sim,
			:atualizar_data_de_envio_pro_sim, :retornar_para_aberto, :editar_operacoes, :atualizar_operacoes,
			:editar_itens_dotacao_do_contrato, :atualiza_itens_dotacao_do_contrato, :adicionar_dotacoes, :editar_responsavel,
			:atualizar_responsavel, :editar_unidade_orcamentaria_do_exercicio, :atualizar_unidade_orcamentaria_do_exercicio,
			:editar_informacoes_do_sim, :atualizar_informacoes_do_sim, :cadastrar_responsavel_do_pedido, :atualizar_responsavel_do_pedido,
			:editar_data_da_solicitacao, :atualizar_data_da_solicitacao, :editar_informacoes_do_pncp, :atualizar_informacoes_do_pncp,
			:disponibiliza_dependencias_pncp
		]

		before_action :set_processo, only: [:editar_dotacoes, :new, :create]
		before_action :set_operacao_de_credito_do_contrato, only: [:editar_acoes_das_operacoes, :atualizar_acoes_das_operacoes]
		before_action :disponibiliza_dependencias, only: [:new, :create, :edit, :update]
		before_action :verifica_edicao_do_contrato, only: [:edit]
		before_action -> { verifica_acesso_usuario(@contrato) }, except: [:index, :new, :create, :envios_pncp]
		before_action -> {verifica_mes_bloqueado(@contrato) if @contrato.fechado? && @contrato.data_de_envio_pro_sim.present?}, only: [:cancelar, :confirmar_cancelamento, :edit, :update, :destroy, :editar_itens, :atualiza_itens, :editar_dotacoes,
			:atualiza_dotacoes, :nao_enviar_para_sim, :enviar_para_sim, :editar_data_de_envio_pro_sim, :atualizar_data_de_envio_pro_sim, :retornar_para_aberto, :editar_operacoes, :atualizar_operacoes,
			:editar_itens_dotacao_do_contrato, :atualiza_itens_dotacao_do_contrato, :adicionar_dotacoes, :editar_responsavel, :atualizar_responsavel, :editar_unidade_orcamentaria_do_exercicio,
			:atualizar_unidade_orcamentaria_do_exercicio, :editar_informacoes_do_sim, :atualizar_informacoes_do_sim, :cadastrar_responsavel_do_pedido, :atualizar_responsavel_do_pedido
		]
		before_action :disponibiliza_dependencias_pncp, only: [:editar_informacoes_do_pncp]

		# GET /licitacao/contratos
		def index

			# Usar nos selects dos filtros dos contratos
			@pessoas = Base::Pessoa.includes(:tipo_de_pessoa).fornecedores
			@orcamentos = Orcamento.all.order(exercicio: :desc)
			@unidades_por_usuario_ids = current_usuario.unidades_orcamentarias_por_usuario.pluck(:unidade_orcamentaria_id)
			@unidades_orcamentarias = Loa::UnidadeOrcamentaria.joins(orgao: :orcamento).where('loa_unidades_orcamentarias.id in (?)', @unidades_por_usuario_ids).order("orcamentos.exercicio DESC", "loa_unidades_orcamentarias.codigo", "loa_unidades_orcamentarias.nome" )
			@url_contratos = licitacao_contratos_path
			@contratos_filtro = Licitacao::Contrato.all

			if query_params["numero_eq"].present?
				if params[:criado_na_contabilidade].present?
					@action_contratos = "criado_na_contabilidade"
					@q = Licitacao::Contrato.joins(projeto: :pedido).where('licitacao_pedidos.criado_na_contabilidade = true').ransack( query_params.reject{ |key| key == "unidade_orcamentaria_do_exercicio_id_eq" } )
				else
					@action_contratos = "contrato"
					@q = Licitacao::Contrato.where.not(fim_da_vigencia: nil).ransack( query_params.reject{ |key| key == "unidade_orcamentaria_do_exercicio_id_eq" } )
				end
			else
				if params[:criado_na_contabilidade].present?
					@action_contratos = "criado_na_contabilidade"
					@q = Licitacao::Contrato.joins(projeto: :pedido).where('licitacao_pedidos.criado_na_contabilidade = true').where('unidade_orcamentaria_do_exercicio_id in (?)', @unidades_orcamentarias.pluck(:id)).order(data_do_contrato: :desc).ransack(query_params)
				else
					@action_contratos = "contrato"
					@q = Licitacao::Contrato.where.not(fim_da_vigencia: nil).order(data_do_contrato: :desc).ransack(query_params)
				end
			end

			if request.format.pdf?
				titulo1 = 'Relação de Contratos'
				titulo2 = ""
				titulo3 = ""
				if params[:q].present? && params[:q]["unidade_orcamentaria_do_exercicio_id_eq"].present?
					unidade_orcamentaria = Loa::UnidadeOrcamentaria.find(params[:q]["unidade_orcamentaria_do_exercicio_id_eq"])
					titulo2 += "Unidade Orçamentária: #{unidade_orcamentaria.codigo_e_nome} - "
				else
					titulo2 += "Unidade Orçamentária: CONSOLIDADO - "
				end
				if params[:q].present? && params[:q]["contratado_pessoa_do_projeto_pessoa_id_eq"].present?
					fornecedor = Base::Pessoa.find(params[:q]["contratado_pessoa_do_projeto_pessoa_id_eq"])
					titulo3 += "Fornecedor: #{fornecedor.nome_e_cpf_ou_cnpj} - "
				end

				# titulo2 += "De #{params[:q]["data_do_empenho_gteq"] rescue ''} Até #{params[:q]["data_do_empenho_lteq"] rescue ''} - " if params[:q].present? and (params[:q]["data_de_solicitacao_gteq"].present? || params[:q]["data_de_solicitacao_lteq"].present?)
				# titulo2 += "Nª do Contrato: #{params[:q][:contrato_numero_eq]} - " if params[:q].present? and params[:q][:contrato_numero_eq].present?
				# titulo3 += "Nº do Processo: #{params[:q][:projeto_numero_do_processo_eq]} - " if params[:q].present? and params[:q][:projeto_numero_do_processo_eq].present?
				# titulo3 += "Nº da Obra: #{params[:q][:contrato_obra_codigo_eq]} - " if params[:q].present? and params[:q][:contrato_obra_codigo_eq].present?
				@lista_contratos = @q.result(distinct: true).left_outer_joins(:aditivos).where("licitacao_contratos.unidade_orcamentaria_do_exercicio_id in (?) OR licitacao_aditivos.unidade_orcamentaria_id in (?)", current_usuario.unidades_orcamentarias.ids, current_usuario.unidades_orcamentarias.ids)
			else
				@contratos = @q.result(distinct: true).left_outer_joins(:aditivos).where("licitacao_contratos.unidade_orcamentaria_do_exercicio_id in (?) OR licitacao_aditivos.unidade_orcamentaria_id in (?)", current_usuario.unidades_orcamentarias.ids, current_usuario.unidades_orcamentarias.ids).order(created_at: :desc).paginate(page: params[:page], per_page: 10)
			end

			@configuracoes = Configuracao.last
			respond_to do |format|
				format.html
				format.json
				format.pdf do
					render pdf: "contratos",
					template: 'licitacao/contratos/index.pdf.slim',
					orientation: 'Landscape',
					header: {
						html: {
							template: 'layouts/_cabecalho_pdf.html.slim',
							locals: { titulo1: titulo1 , titulo2: titulo2, titulo3: titulo3 }
						},
						spacing: 0
					},
					footer: { right: '[page]', font_size: 8 },
					disable_smart_shrinking: true,
					dpi: '96',
					margin: @configuracoes.margens_customizadas(top: 4)
				end
			end
		end

		# GET /licitacao/contratos/new
		def new
			@lotes = []
			@contrato = Licitacao::Contrato.new

			if params[:ata_de_registro_de_preco_id]
				@ata_de_registro_de_preco = Licitacao::AtaDeRegistroDePrecos.find(params[:ata_de_registro_de_preco_id])
				@contrato.ata_de_registro_de_precos = @ata_de_registro_de_preco
			end
		end

		# GET /licitacao/contratos/1/edit
		def edit
			@lotes = []
			@processo = @contrato.projeto
			if @processo.pedido.projeto_simplificado.present? && !@processo.bid_obra_ou_servico
				@contrato.fornecedor_id = @contrato.try(:pessoa).try(:id)
			else
				@contrato.pessoa_do_projeto_id = @contrato.try(:pessoa_do_projeto).try(:id)
			end
		end

		# GET /licitacao/comissoes/1
		def show
			respond_to do |format|
				format.html
				format.json {render json: @contrato, methods: :valor_total_do_contrato}
			end
		end

		def quantidade_de_itens_disponiveis
			item_do_lote = Licitacao::ItemDoLote.find( params[:item_do_lote_id] )
			render json: {quantidade: item_do_lote.saldo_por_unidade(@contrato.unidade_orcamentaria.id).to_f}
		end

		# PATCH/PUT /licitacao/nao_enviar_para_sim
		def nao_enviar_para_sim
			if @contrato.nao_envia_pro_sim
				redirect_to @contrato, notice: 'O contrato 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 @contrato.update_column(:envia_pro_sim, true)
				redirect_to @contrato, notice: 'O contrato foi marcado para ser enviado para o SIM.'
			end
		end

		# POST /licitacao/contratos
		# REFACTOR: lógica deve ficar no modelo.
		def create
			@lotes = []
			@orcamentos_da_despesa = []
			@contrato = Licitacao::Contrato.new(contrato_params)
			@contrato.orcamento = contexto_atual

			if contrato_params[:ata_de_registro_de_preco_id]
				@ata_de_registro_de_preco = Licitacao::AtaDeRegistroDePrecos.find(contrato_params[:ata_de_registro_de_preco_id])
			end

			if @contrato.projeto.pedido.criado_na_contabilidade.present?
				@contrato.envia_pro_sim = false
			end

			if @contrato.save
				redirect_to @contrato, notice: 'Contrato foi criado com sucesso.'
			else
				render :new
			end
		end

		# GET /licitacao/pedidos/1/cancelar
		def confirmar_cancelamento
			return if bloqueia_usuario_com_base_em 'cancelar'
		end

		# PATCH /licitacao/pedidos/1/cancelar
		def cancelar
			@contrato.motivo_do_cancelamento = cancelamento_params[:motivo_do_cancelamento]
			if @contrato.cancelar!
				redirect_to @contrato, notice: 'Contrato foi cancelado com sucesso.'
			else
				render :confirmar_cancelamento
			end
		end

		def finalizar
			if @contrato.fechar!
				redirect_to @contrato, notice: 'Contrato foi finalizado com sucesso.'
			else
				redirect_to @contrato, alert: 'Não foi possivel finalizar o contrato.'
			end
		end

		# PATCH/PUT /licitacao/contratos/1
		def update
			@lotes = []
			
			if @contrato.ata_de_registro_de_precos.present? && contrato_params["lotes_do_contrato_attributes"].present?
				ids_presentes = []
				contrato_params["lotes_do_contrato_attributes"].each do |key|
					id_do_lote = key[1]["lote_id"].to_i
					ids_presentes << id_do_lote
				end
				@contrato.lotes_marcados_para_excluir = @contrato.lotes_do_contrato.where.not(lote_id: ids_presentes).pluck(:lote_id)
				@contrato.lotes_do_contrato.where(lote_id: @contrato.lotes_marcados_para_excluir).delete_all if @contrato.lotes_marcados_para_excluir.any?
				@contrato.itens_do_contrato.joins(item_do_lote: :lote).where("licitacao_lotes.id = ?", @contrato.lotes_marcados_para_excluir).delete_all if @contrato.lotes_marcados_para_excluir.any?
			end

			if !@contrato.aberto? && @contrato.ata_de_registro_de_preco_id.blank?
				redirect_to @contrato, notice: 'Não é possivel editar contrato cancelado ou fechado'
			elsif @contrato.update( contrato_params )
				redirect_to @contrato, notice: 'Contrato foi atualizado(a) com sucesso.'
			else
				render :edit
			end
		end

		def enviar_para_controladoria
			if @contrato.enviado_para_controladoria!
				redirect_to @contrato, notice: 'O contrato foi encaminhado para a controladoria com sucesso.'
			else
				redirect_to @contrato, alert: 'Não foi possível encaminhar o contrato. Por favor, confira se ele contém erros'
			end
		end

		# PATCH/PUT /controladoria/contratos/1/encaminhar_para_comite_programacao_financeira
		def enviar_para_copfin
			if @contrato.enviado_para_copfin!
				redirect_to @contrato, success: 'O contrato foi encaminhado para o COPFIN com sucesso.'
			else
				redirect_to @contrato, alert: 'Não foi possível encaminhar o contrato. Por favor, confira se ele contém erros'
			end
		end

		# PATCH/PUT /controladoria/contratos/1/confirmar
		def confirmar
			if @contrato.confirmado!
				redirect_to @contrato, success: 'O contrato foi confirmado com sucesso.'
			else
				redirect_to @contrato, alert: 'Não foi possível confirmar o contrato. Por favor, confira se ele contém erros'
			end
		end

		#GET	/licitacao/contratos/1/dotacoes_contrato
		def editar_dotacoes
			return if bloqueia_usuario_com_base_em 'atualiza_dotacoes'
			if params[:dotacao_id].present? && !params[:dotacao_id].nil?
				@orcamento_da_despesa_do_contrato = @contrato.orcamentos_da_despesa_do_contrato.find(params[:dotacao_id])
			else
				@orcamento_da_despesa_do_contrato = @contrato.orcamentos_da_despesa_do_contrato.build
			end
			carrega_select_box_dotacao
		end

		#PATCH	/licitacao/contratos/1/atualiza_dotacoes
		def adicionar_dotacoes
			@orcamento_da_despesa_do_contrato = @contrato.orcamentos_da_despesa_do_contrato.new(dotacao_params)
			if @orcamento_da_despesa_do_contrato.save
				redirect_to licitacao_contrato_path(@contrato, tab: "dotacoes_do_contrato"), success: 'Dotação foi adicionada com sucesso.'
			else
				carrega_select_box_dotacao
				render :editar_dotacoes
			end
		end

		#PATCH	/licitacao/contratos/1/atualiza_dotacoes
		def atualiza_dotacoes
			@orcamento_da_despesa_do_contrato = @contrato.orcamentos_da_despesa_do_contrato.find(dotacao_params[:id])
			if @orcamento_da_despesa_do_contrato.update(dotacao_params)
				redirect_to licitacao_contrato_path(@contrato, tab: "dotacoes_do_contrato"), success: 'Dotação foi atualizada com sucesso.'
			else
				carrega_select_box_dotacao
				render :editar_dotacoes
			end
		end

		#DELETE	/licitacao/contratos/excluir_dotacao/1
		def excluir_dotacao
			return if bloqueia_usuario_com_base_em 'atualiza_dotacoes'
			orcamento_da_despesa_do_contrato = Licitacao::OrcamentoDaDespesaDoContrato.find(params[:orcamento_da_despesa_do_contrato_id])

			if Configuracao.last.implantacao?
				redirect_to licitacao_contrato_path(orcamento_da_despesa_do_contrato.contrato) + "?tab=dotacoes_do_contrato", success: "Dotação deletada com sucesso" unless acao_permitida? orcamento_da_despesa_do_contrato.contrato, action_name.to_sym
				mensagem = apaga_e_retorna_mensagem(orcamento_da_despesa_do_contrato)
			else
				redirect_to licitacao_contrato_path(orcamento_da_despesa_do_contrato.contrato) + "?tab=dotacoes_do_contrato", alert: "Essa ação não é permitida nessa etapa" unless acao_permitida? orcamento_da_despesa_do_contrato.contrato, action_name.to_sym
				mensagem = apaga_e_retorna_mensagem(orcamento_da_despesa_do_contrato)
				redirect_to licitacao_contrato_path(orcamento_da_despesa_do_contrato.contrato) + "?tab=dotacoes_do_contrato", mensagem
			end
		end

		#GET /licitacao/pedidos/1/fornecedores
		def editar_itens
			return if bloqueia_usuario_com_base_em 'atualiza_itens'
			if @contrato.ata_de_registro_de_precos.present?
				if @contrato.ata_de_registro_de_precos.processo.pedido.projeto_simplificado?
					itens = @contrato.itens_da_ata_por_lote
				else
					itens = @contrato.itens_da_ata_por_lote_do_fornecedor_vencedor
				end
				itens.each do |item_da_ata|
					item_do_contrato = @contrato.itens_do_contrato.find_by(item_do_lote_id: item_da_ata.item_do_lote.id)
					valor_unitario = item_da_ata.item_do_lote.preco_unitario
					@contrato.itens_do_contrato.build(item_do_lote_id: item_da_ata.item_do_lote.id) unless item_do_contrato.present?
				end
			else
				@contrato.itens_dos_lotes.ativos.distinct.each do |item_do_lote|
					quantidade = item_do_lote.saldo.to_f
					item_do_contrato = @contrato.itens_do_contrato.find_by(item_do_lote_id: item_do_lote.id)
					valor_unitario = item_do_lote.preco_unitario
					total = quantidade * valor_unitario
					@contrato.itens_do_contrato.build(item_do_lote_id: item_do_lote.id, quantidade: quantidade, valor: valor_unitario, total: total) unless item_do_contrato.present?
				end
			end
		end

		#PATCH /licitacao/pedidos/1/fornecedores
		def atualiza_itens
			if @contrato.update(contrato_params)
				redirect_to licitacao_contrato_path(@contrato), notice: 'Itens atualizados com sucesso.'
			else
				@itens_do_lote = @contrato.itens_dos_lotes
				render :editar_itens
			end
		end

		# DELETE /licitacao/contratos/1
		def destroy
			mensagem = apaga_e_retorna_mensagem(@contrato)
			if @contrato.de_ata?
				redirect_to  licitacao_ata_de_registro_de_precos_path(@contrato.ata_de_registro_de_precos), mensagem
			else
				redirect_to licitacao_processo_path(@contrato.projeto), mensagem
			end
		end

		# GET /licitacao/contratos/1/editar_data_de_envio_pro_sim
		def editar_data_de_envio_pro_sim
			return if bloqueia_usuario_com_base_em 'update'
		end

		# PATCH /licitacao/contratos/1/atualizar_data_de_envio_pro_sim
		def atualizar_data_de_envio_pro_sim
			if @contrato.update_data_de_envio_pro_sim(contrato_params[:data_de_envio_pro_sim]) && !contrato_params[:data_de_envio_pro_sim].blank?
				redirect_to @contrato, notice: 'Contrato foi atualizado com sucesso.'
			else
				render :editar_data_de_envio_pro_sim
			end
		end

		# GET /licitacao/contratos/1/editar_unidade_orcamentaria_do_exercicio
		def editar_unidade_orcamentaria_do_exercicio
			return if bloqueia_usuario_com_base_em 'update'
			disponibiliza_unidades_orcamentarias_do_exercicio
		end

		# PATCH /licitacao/contratos/1/atualizar_unidade_orcamentaria_do_exercicio
		def atualizar_unidade_orcamentaria_do_exercicio
			if !contrato_params[:unidade_orcamentaria_do_exercicio_id].blank? && @contrato.update_unidade_orcamentaria_do_exercicio(contrato_params[:unidade_orcamentaria_do_exercicio_id])
				redirect_to @contrato, notice: 'Contrato foi atualizado com sucesso.'
			else
				disponibiliza_unidades_orcamentarias_do_exercicio
				render :editar_unidade_orcamentaria_do_exercicio
			end
		end

		# GET /licitacao/contratos/1/editar_responsavel
		def editar_responsavel
			return if bloqueia_usuario_com_base_em 'update'

			@responsaveis = @contrato.pessoa_do_projeto.pessoa.responsaveis
		end

		# PATCH /licitacao/contratos/1/atualizar_responsavel
		def atualizar_responsavel
			if @contrato.update(contrato_params)
				redirect_to @contrato, notice: 'Contrato foi atualizado com sucesso.'
			else
				@responsaveis = @contrato.pessoa_do_projeto.pessoa.responsaveis
				flash[:alert] = 'Não foi possivel atualizar os dados do responsável'
				render :editar_responsavel
			end
		end
		# GET /licitacao/contratos/:contrato_id/retorna_dados_do_contrato
		def retorna_dados_do_contrato
			render json: {
				'fornecedor': @contrato.pessoa.nome,
				'modalidade_da_licitacao': @contrato.projeto.modalidade_de_licitacao,
				'descricao_do_contrato': @contrato.obra.present? ? @contrato.descricao_contrato_de_obra : @contrato.numero,
				'objeto': @contrato.try(:projeto).try(:pedido).try(:objeto)
			}
		end

		# PATCH	/licitacao/contratos/1/retornar_para_aberto
		def retornar_para_aberto
			if @contrato.retornar_para_aberto!
				redirect_to @contrato, success: 'O contrato foi retornado para edição.'
			else
				redirect_to @contrato, alert: 'Não foi possível retornar o contrato. Por favor, confira se ele contém erros'
			end
		end

		#GET /licitacao/contratos/1/operacoes
		def editar_operacoes
			return if bloqueia_usuario_com_base_em 'update'
			if @contrato.operacoes_de_credito_do_contrato.empty?
				@contrato.operacoes_de_credito_do_contrato.build
			end
			@operacoes_de_credito = Obra::OperacaoDeCredito.all.joins(conta_bancaria: [fontes_de_recursos_da_conta_bancaria: :fonte_de_recurso]).where(base_fontes_de_recursos: {id: @contrato.fontes_de_recursos_de_operacao_de_credito.map(&:id)})
		end

		#PATCH /licitacao/contratos/1/operacoes
		def atualizar_operacoes
			if @contrato.update( operacoes_de_credito_params )
				redirect_to licitacao_contrato_path(@contrato) + "?tab=operacoes_de_credito", notice: 'Contrato foi atualizado com sucesso.'
			else
				render :editar_operacoes
			end
		end

		#GET /licitacao/contratos/1/acoes_das_operacoes
		def editar_acoes_das_operacoes
			return if bloqueia_usuario_com_base_em 'update'
			if @operacao_de_credito_do_contrato.acoes_da_operacao_de_credito_do_contrato.empty?
				@operacao_de_credito_do_contrato.acoes_da_operacao_de_credito_do_contrato.build
			end
			@componentes_da_operacao_de_credito = @operacao_de_credito_do_contrato.contrato.componentes_da_operacao_de_credito
		end

		#PATCH /licitacao/contratos/1/acoes_das_operacoes
		def atualizar_acoes_das_operacoes
			if @operacao_de_credito_do_contrato.update( acoes_da_operacao_de_credito_params )
				redirect_to licitacao_contrato_path(@operacao_de_credito_do_contrato.contrato) + "?tab=operacoes_de_credito", notice: 'Contrato foi atualizado com sucesso.'
			else
				@componentes_da_operacao_de_credito = @operacao_de_credito_do_contrato.contrato.componentes_da_operacao_de_credito
				render :editar_acoes_das_operacoes
			end
		end

		#GET /licitacao/contratos/1/itens_dotacao_do_contrato/1
		def editar_itens_dotacao_do_contrato
			return if bloqueia_usuario_com_base_em 'atualiza_dotacoes'
			@orcamento_da_despesa_do_contrato = Licitacao::OrcamentoDaDespesaDoContrato.find(params[:orcamento_da_despesa_do_contrato_id])
			disponibiliza_itens_do_contrato_da_dotacao(@contrato)
			if params[:todos].present? && params[:todos] == "true"
				itens_do_contrato_existentes = @orcamento_da_despesa_do_contrato.itens_do_orcamento_da_despesa_do_contrato.map(&:item_do_contrato)
				itens_do_contrato_restantes = @contrato.itens_do_contrato - itens_do_contrato_existentes
				itens_do_contrato_restantes.each do |item|
					@orcamento_da_despesa_do_contrato.itens_do_orcamento_da_despesa_do_contrato.build(item_do_contrato: item)
				end
			end
			if @orcamento_da_despesa_do_contrato.itens_do_orcamento_da_despesa_do_contrato.empty?
				@orcamento_da_despesa_do_contrato.itens_do_orcamento_da_despesa_do_contrato.build
			end
		end

		#PATCH /licitacao/contratos/1/atualiza_itens_dotacao_do_contrato/1
		def atualiza_itens_dotacao_do_contrato
			return if bloqueia_usuario_com_base_em 'atualiza_dotacoes'

			@orcamento_da_despesa_do_contrato = Licitacao::OrcamentoDaDespesaDoContrato.find(params[:orcamento_da_despesa_do_contrato_id])

			if @orcamento_da_despesa_do_contrato.update(itens_dotacao_params)
				redirect_to licitacao_contrato_path(@orcamento_da_despesa_do_contrato.contrato, tab: "dotacoes_do_contrato"), notice: 'Itens da dotação adicionados com sucesso.'
			else
				disponibiliza_itens_do_contrato_da_dotacao(@orcamento_da_despesa_do_contrato.contrato)
				render :editar_itens_dotacao_do_contrato
			end
		end

		def solicitacoes
			orcamento = query_params["orcamento_id_eq"].blank? ? contexto_atual : Orcamento.find(query_params["orcamento_id_eq"])

			# Usar nos selects dos filtros dos contratos
			@pessoas = Base::Pessoa.includes(:tipo_de_pessoa).fornecedores
			@orcamentos = Orcamento.all.order(exercicio: :desc)
			@unidades_por_usuario_ids = current_usuario.unidades_orcamentarias_por_usuario.pluck(:unidade_orcamentaria_id)
			@unidades_orcamentarias = orcamento.unidades_orcamentarias.where('loa_unidades_orcamentarias.id in (?)', @unidades_por_usuario_ids).order(:codigo, :nome)

			contratos = current_usuario.desenvolvedor? ? orcamento.contratos.where(fim_da_vigencia: nil) : current_usuario.contratos.where(fim_da_vigencia: nil)
			contratos.where('unidade_orcamentaria_do_exercicio_id in (?)', @unidades_orcamentarias.pluck(:id))

			@q = contratos.order(data_da_solicitacao: :desc).ransack(query_params)
			@contratos = @q.result(distinct: false).paginate(page: params[:page], per_page: 10)
		end

		def editar_informacoes_do_sim
		end

		def editar_informacoes_do_pncp
		end

		def atualizar_informacoes_do_sim
			@contrato.assign_attributes(contrato_params)

			if  @contrato.valida_se_ja_houve_envio_do_sim == false && @contrato.save(validate: false)
				redirect_to @contrato, notice: 'Informações do SIM modificadas com sucesso'
				@contrato.obra.update_column(:data_de_envio_pro_sim, @contrato.data_de_envio_pro_sim) if @contrato.obra.present?
			else
				render :editar_informacoes_do_sim
			end
		end

		def atualizar_informacoes_do_pncp
			@contrato.assign_attributes(contrato_params)
			if @contrato.save(validate: false)
				@contrato.update_column(:enviar_para_pncp, true)
				redirect_to @contrato, notice: 'Informações do PNCP modificadas com sucesso'
			else
				render :editar_informacoes_do_pncp
			end
		end

		def cadastrar_responsavel_do_pedido
			return if bloqueia_usuario_com_base_em 'update'
			@pessoas = ::Base::AgentePublicoMunicipal.joins(:pessoa)
		end

		def atualizar_responsavel_do_pedido
			return if bloqueia_usuario_com_base_em 'update'
			if @contrato.update(contrato_params)
				redirect_to @contrato, notice: 'Contrato atualizado com sucesso'
			else
				@pessoas = ::Base::AgentePublicoMunicipal.all.includes(:pessoa)
				render :cadastrar_responsavel_do_pedido
			end
		end

		def atualizar_data_da_solicitacao
			if @contrato.update(contrato_params)
				redirect_to @contrato, notice: 'Data de Solicitação atualizada com sucesso.'
			else
				render :editar_data_da_solicitacao
			end
		end

		def envios_pncp
			@pessoas = Base::Pessoa.includes(:tipo_de_pessoa).fornecedores
			@orcamentos = Orcamento.all.order(exercicio: :desc)
			@unidades_por_usuario_ids = current_usuario.unidades_orcamentarias_por_usuario.pluck(:unidade_orcamentaria_id)
			@unidades_orcamentarias = Loa::UnidadeOrcamentaria.joins(orgao: :orcamento).where('loa_unidades_orcamentarias.id in (?)', @unidades_por_usuario_ids).order("orcamentos.exercicio DESC", "loa_unidades_orcamentarias.codigo", "loa_unidades_orcamentarias.nome" )
			@url_contratos = licitacao_envios_pncp_path

			if query_params["numero_eq"].present?
				@action_contratos = "contrato"
				@q = Licitacao::Contrato.where.not(fim_da_vigencia: nil).where(enviar_para_pncp: true).ransack( query_params.reject{ |key| key == "unidade_orcamentaria_do_exercicio_id_eq" } )
			else
				@action_contratos = "contrato"
				@q = Licitacao::Contrato.where.not(fim_da_vigencia: nil).where(enviar_para_pncp: true).order(data_do_contrato: :desc).ransack(query_params)
			end

			@contratos = @q.result(distinct: true).left_outer_joins(:aditivos).where("licitacao_contratos.enviar_para_pncp = true AND licitacao_contratos.unidade_orcamentaria_do_exercicio_id  in (?) OR licitacao_aditivos.unidade_orcamentaria_id in (?)", current_usuario.unidades_orcamentarias.ids, current_usuario.unidades_orcamentarias.ids).paginate(page: params[:page], per_page: 10)

			respond_to do |format|
				format.html
				format.json
			end
		end

		private
		def set_contrato
			@contrato = Contrato.find( params[:id] )
		end

		def set_processo
			@processo = Licitacao::Processo.find_by_id( params[:projeto_id] )
		end

		def set_operacao_de_credito_do_contrato
			@operacao_de_credito_do_contrato = Licitacao::OperacaoDeCreditoDoContrato.find(params[:id])
		end

		def disponibiliza_itens_do_contrato_da_dotacao( contrato )
			@itens_do_contrato = contrato.itens_do_contrato.map do |item_do_contrato|
				[
					item_do_contrato.id,
					item_do_contrato.try(:item).try(:codigo_e_descricao_do_item),
					{
						"data-qtd-contratada" => item_do_contrato.quantidade_total.to_f.valor_contabil,
						"data-saldo-vincular" => @orcamento_da_despesa_do_contrato.saldo_a_vincular_por_item_do_contrato(item_do_contrato).to_f.valor_contabil,
						"data-valor-unitario" => item_do_contrato.valor_unitario.to_f.valor_financeiro
					}
				]
			end
		end

		def disponibiliza_unidades_orcamentarias_do_exercicio
			cod_orgao = @contrato.try(:unidade_orcamentaria_por_pedido).try(:unidade_orcamentaria).try(:orgao).try(:codigo)
			cod_unidade = @contrato.try(:unidade_orcamentaria_por_pedido).try(:unidade_orcamentaria).try(:codigo)
			@unidades_orcamentarias_equivalentes = Loa::UnidadeOrcamentaria.joins(:orgao)
				.where(codigo: cod_unidade, loa_orgaos: {codigo: cod_orgao, orcamento_id: @contrato.orcamento.id}).distinct

			@unidades_orcamentarias_vinculadas = @contrato.try(:orcamento).try(:unidades_orcamentarias)
			.joins(:unidades_orcamentaria_vinculada)
			.where('loa_unidades_orcamentaria_vinculada.unidade_orcamentaria_vinculada_id = ?', @contrato.try(:unidade_orcamentaria).try(:id))
			.distinct

			@unidades_orcamentarias = @unidades_orcamentarias_equivalentes + @unidades_orcamentarias_vinculadas
			@unidades_orcamentarias = @unidades_orcamentarias.uniq
		end

		def disponibiliza_dependencias
			@processo = Licitacao::Projeto.find_by_id(params[:projeto_id]) || @contrato.projeto
			tipo_de_parcerias = ['termo_de_colaboracao', 'termo_de_fomento', 'acordo_de_cooperacao']
			@tipos_de_contratos = Licitacao::Contrato.tipos_de_contratos.select{|tipo| tipo_de_parcerias.include?(tipo)} if @processo.parceria_osc?
			@tipos_de_contratos = Licitacao::Contrato.tipos_de_contratos.select{|tipo| !tipo_de_parcerias.include?(tipo)} unless @processo.parceria_osc?

			if params[:ata_de_registro_de_preco_id].present? || (params[:licitacao_contrato].present? && params[:licitacao_contrato][:ata_de_registro_de_preco_id]) || @contrato.present? && @contrato.de_ata?
				ata_id = params[:ata_de_registro_de_preco_id] || params[:licitacao_contrato].present? && params[:licitacao_contrato][:ata_de_registro_de_preco_id] || @contrato.ata_de_registro_de_preco_id

				@ata_de_registro_de_preco = Licitacao::AtaDeRegistroDePrecos.find_by_id(ata_id)
				@unidades_por_usuario_ids = current_usuario.unidades_orcamentarias_por_usuario.pluck(:unidade_orcamentaria_id)

				if @ata_de_registro_de_preco.processo.pedido.verifica_acesso_do_usuario_principal(current_usuario)
					unidades_da_ata = @ata_de_registro_de_preco.unidades_orcamentarias.where('loa_unidades_orcamentarias.id in (?)', @unidades_por_usuario_ids)
					@unidades_orcamentarias = @processo.pedido.unidades_orcamentarias_por_pedido.joins(:unidade_orcamentaria).where('loa_unidades_orcamentarias.id IN (?)', unidades_da_ata.ids)
				else
					@unidades_orcamentarias = @processo.pedido.unidades_orcamentarias_por_pedido.joins(:unidade_orcamentaria).where('loa_unidades_orcamentarias.id in (?)', @unidades_por_usuario_ids)
				end
			else
				@unidades_orcamentarias = @processo.pedido.unidades_orcamentarias_por_pedido
			end

			if @processo.pedido.projeto_simplificado.present? && !@processo.bid_obra_ou_servico && ( @ata_de_registro_de_preco.nil? || (@ata_de_registro_de_preco.present? && @ata_de_registro_de_preco.ganhadores.empty? ) )
				@ganhadores = (@contrato && @contrato.importado_do_tcm?) ? [@contrato.pessoa_do_projeto] : Base::Pessoa.includes(:tipo_de_pessoa).all
			elsif @ata_de_registro_de_preco.present?
				@ganhadores = []
				if @processo.pedido.projeto_simplificado.present? && !@processo.bid_obra_ou_servico
					@ganhadores = Base::Pessoa.where(id: @ata_de_registro_de_preco.ganhadores.distinct.pluck(:pessoa_id))
				else
					@ganhadores = @ata_de_registro_de_preco.ganhadores.distinct
				end
			else
				@ganhadores = (@contrato && @contrato.importado_do_tcm?) ? [@contrato.pessoa_do_projeto] : @processo.ganhadores_dos_lotes
			end
		end

		def disponibiliza_dependencias_pncp
			@tipos_de_contrato_pncp = Licitacao::Contrato.tipo_contrato_pncps_i18n
			@tipo_de_processo_pncp = Licitacao::Contrato.tipo_processo_pncps_i18n
		end

		def carrega_select_box_dotacao
			@unidades_orcamentarias = @contrato.projeto.unidades_orcamentarias
			@elementos_de_despesa_por_subacao = []
			@orcamentos_da_despesa = []
			@sub_elementos_de_despesa = []
			@subacoes = []
			if @contrato.unidade_orcamentaria_do_exercicio.present?
				projeto = @contrato.projeto if @contrato.projeto.present?
				unidade_orcamentaria = @contrato.unidade_orcamentaria_do_exercicio

				if @orcamento_da_despesa_do_contrato.present? && @orcamento_da_despesa_do_contrato.persisted?

					@orcamento_da_despesa_do_contrato.subacao_id = @orcamento_da_despesa_do_contrato.subacao.try(:id)
					@orcamento_da_despesa_do_contrato.elemento_de_despesa_por_subacao_id =  @orcamento_da_despesa_do_contrato.elemento_de_despesa_por_subacao.try(:id)
					clausulas = { unidade_orcamentaria_id: unidade_orcamentaria.id }
					@subacoes = Loa::Subacao.joins(:elementos_de_despesa_por_subacao).where(clausulas).distinct
					@elementos_de_despesa_por_subacao = Loa::ElementoDeDespesaPorSubacao.includes(:elemento_de_despesa).where(subacao_id:  @orcamento_da_despesa_do_contrato.try(:orcamento_da_despesa).try(:elemento_de_despesa_por_subacao).try(:subacao_id) ).order('base_elementos_de_despesa.codigo').all
					@orcamentos_da_despesa = Loa::OrcamentoDaDespesa.where( elemento_de_despesa_por_subacao_id:  @orcamento_da_despesa_do_contrato.try(:orcamento_da_despesa).try(:elemento_de_despesa_por_subacao_id) ).order(:fonte_de_recursos_id)
					elemento_de_despesa_por_subacao = Loa::ElementoDeDespesaPorSubacao.where( id: @orcamento_da_despesa_do_contrato.try(:orcamento_da_despesa).try(:elemento_de_despesa_por_subacao_id) ).first
					@sub_elementos_de_despesa = Contabilidade::SubElementoDeDespesa.ativos.where( elemento_de_despesa_id: elemento_de_despesa_por_subacao.try(:elemento_de_despesa_id) )

				elsif params[:licitacao_orcamento_da_despesa_do_contrato].present?

					@orcamento_da_despesa_do_contrato.subacao_id =  params[:licitacao_orcamento_da_despesa_do_contrato][:subacao_id]
					@orcamento_da_despesa_do_contrato.elemento_de_despesa_por_subacao_id =  params[:licitacao_orcamento_da_despesa_do_contrato][:elemento_de_despesa_por_subacao_id]
					clausulas = { unidade_orcamentaria_id: unidade_orcamentaria.id }
					@subacoes = Loa::Subacao.joins(:elementos_de_despesa_por_subacao).where(clausulas).distinct
					@elementos_de_despesa_por_subacao = Loa::ElementoDeDespesaPorSubacao.includes(:elemento_de_despesa).where(subacao_id:  params[:licitacao_orcamento_da_despesa_do_contrato][:subacao_id] ).order('base_elementos_de_despesa.codigo').all
					@orcamentos_da_despesa = Loa::OrcamentoDaDespesa.where( elemento_de_despesa_por_subacao_id:  params[:licitacao_orcamento_da_despesa_do_contrato][:elemento_de_despesa_por_subacao_id]).order(:fonte_de_recursos_id)
					elemento_de_despesa_por_subacao = Loa::ElementoDeDespesaPorSubacao.where( id: params[:licitacao_orcamento_da_despesa_do_contrato][:elemento_de_despesa_por_subacao_id]).first
					@sub_elementos_de_despesa = Contabilidade::SubElementoDeDespesa.ativos.where( elemento_de_despesa_id: elemento_de_despesa_por_subacao.try(:elemento_de_despesa_id) )
				end

				if projeto.present? && projeto.orcamentos_da_despesa_por_projetos.any? && Configuracao.last.comprometimento_de_dotacoes?
					orcamentos_do_projeto = projeto.orcamentos_da_despesa_por_projetos.joins(orcamento_da_despesa: { elemento_de_despesa_por_subacao: :subacao }).where('loa_subacoes.unidade_orcamentaria_id = ?', unidade_orcamentaria.id)
					if orcamentos_do_projeto.any?
						@subacoes = orcamentos_do_projeto.map{|orcamento| orcamento.orcamento_da_despesa.elemento_de_despesa_por_subacao.subacao}
					else
						clausulas = { unidade_orcamentaria_id: unidade_orcamentaria.id }
						@subacoes = Loa::Subacao.joins(:elementos_de_despesa_por_subacao).where(clausulas).distinct
					end
				elsif !@orcamento_da_despesa_do_contrato.persisted?
					clausulas = { unidade_orcamentaria_id: unidade_orcamentaria.id }
					@subacoes = Loa::Subacao.joins(:elementos_de_despesa_por_subacao).where(clausulas).distinct
				end
			end
		end

		# Permite apenas os parâmetros específicos
		def contrato_params
			params.require(:licitacao_contrato).permit(
				:fornecedor_id, :responsavel_fornecedor_id, :projeto_id, :data_da_solicitacao, :pessoa_do_projeto_id,
				:cpf_do_responsavel, :nome_do_responsavel, :unidade_orcamentaria_por_pedido_id, :lote_id,
				:ata_de_registro_de_preco_id, :texto_do_contrato, :modelo_do_documento_id, :status,
				:contrato_id, :numero, :discriminacao_obrigatoria_de_itens, :valor, :data_do_contrato, :tipo_de_contrato, :form_principal,
				:modalidade, :inicio_da_vigencia, :fim_da_vigencia, :objeto, :justificativa, :data_de_envio_pro_sim, :unidade_orcamentaria_do_exercicio_id,
				:responsavel_do_pedido_id,:compra_cnpj, :compra_ano, :compra_sequencial, :tipo_contrato_pncp, :tipo_processo_pncp, :quantidade_parcelas_pncp,
				:valor_parcela_pncp, :contratos_vigentes, :contratos_vencidos,
				itens_do_contrato_attributes: [:id, :item_do_lote_id, :quantidade, :contrato_id, :valor, :total, :_destroy],
				lotes_do_contrato_attributes: [:id, :lote_id, :contrato_id, :_destroy]
			)
		end

		def operacoes_de_credito_params
			params.require(:licitacao_contrato).permit(operacoes_de_credito_do_contrato_attributes: [:id, :operacao_de_credito_id, :_destroy])
		end

		def acoes_da_operacao_de_credito_params
			params.require(:licitacao_operacao_de_credito_do_contrato).permit(acoes_da_operacao_de_credito_do_contrato_attributes: [:id, :componente_da_operacao_de_credito_id, :acao_do_componente_id, :valor_da_acao, :_destroy])
		end

		def dotacao_params
			params.require(:licitacao_orcamento_da_despesa_do_contrato).permit(:id, :subacao_id, :elemento_de_despesa_por_subacao_id, :sub_elemento_de_despesa_id, :orcamento_da_despesa_id, :valor )
		end

		def cancelamento_params
			params.require(:licitacao_contrato).permit(:motivo_do_cancelamento).merge(status: 'cancelado')
		end

		def itens_dotacao_params
			begin
				params.require(:licitacao_orcamento_da_despesa_do_contrato).permit(
					itens_do_orcamento_da_despesa_do_contrato_attributes: [
						:id, :item_do_contrato_id, :quantidade, :total_por_item, :_destroy
					]
				)
			rescue ActionController::ParameterMissing
				nil
			end
		end

		def verifica_edicao_do_contrato
			redirect_to @contrato, alert: "Contrato não pode ser editado nessa etapa" unless @contrato.pode_editar? || Configuracao.last.implantacao?
		end

	end
end
