class Administrativo::LiquidacoesController < ApplicationController
	include ControllerConcern
	include AdministrativoControllersConcern
	include Contabilidade::LiquidacaoHelper


	before_action -> { verifica_modulo_na_sessao(["administrativo", "controladoria"]) }
	before_action :authenticate_usuario!
	before_action :autoriza_usuario!
	before_action :set_liquidacao, except: [:index, :new, :create]
	before_action :verifica_status_da_liquidacao, only: [:edit, :update, :destroy]
	before_action :disponibiliza_dependencias, only: [:new, :create, :edit, :update]
	before_action :disponibiliza_dependencias_obra, only: [:edit, :update]
	before_action :disponibiliza_dependencias_empenhos, only: [:new, :create]
	before_action -> { usuario_pode_visualizar?(@liquidacao) }, except: [:index, :new, :create]
	before_action -> {verifica_mes_bloqueado(@liquidacao)}, only: [:edit, :destroy, :confirmar_liquidacao, :retornar_para_solicitado]
	before_action -> {redirect_back(fallback_location: root_path, alert: "Não é possível excluir a liquidação") if !@liquidacao.pode_excluir?}, only:[:destroy]


	# GET /administrativo/liquidacoes
	def index
		@tipo_de_restos = Contabilidade::Liquidacao.status_restos_a_pagares
		@fontes_de_recursos = contexto_atual.fontes_de_recursos

		if params[:restos_a_pagar].present?
			@liquidacoes = current_usuario.liquidacoes.menor_ou_igual(exercicio_atual)
		else
			@liquidacoes = current_usuario.liquidacoes.do_exercicio(exercicio_atual)
		end

		unless current_usuario.desenvolvedor?
			@liquidacoes = @liquidacoes.joins(empenho: [orcamento_da_despesa: [elemento_de_despesa_por_subacao: [subacao: :unidade_orcamentaria]]]).where(loa_unidades_orcamentarias: {id: current_usuario.unidades_orcamentarias_por_usuario.pluck(:unidade_orcamentaria_id) }).distinct
		end

		@q =
			if params[:veio_da_mensagem_retornado_pela_contabilidade].present?
				@liquidacoes.search("status_eq" => "9")
			elsif params[:veio_da_mensagem_retornado_pela_controladoria].present?
				@liquidacoes.search("status_eq" => "10")
			elsif params[:restos_a_pagar].present?
				@url_liquidacoes = administrativo_liquidacao_restos_a_pagar_path
				@action_liquidacoes = "restos_a_pagar"
				@liquidacoes.where(restos_a_pagar: true).select('contabilidade_liquidacoes.*, CASE WHEN NOT data_da_liquidacao is NULL 
					THEN contabilidade_liquidacoes.data_da_liquidacao 
					ELSE contabilidade_liquidacoes.data_de_solicitacao END AS data_order_liq').order('data_order_liq DESC').search(params[:q])
			else
				@url_liquidacoes = administrativo_liquidacoes_path
				@liquidacoes.select('contabilidade_liquidacoes.*,CASE WHEN NOT data_da_liquidacao is NULL THEN data_da_liquidacao ELSE contabilidade_liquidacoes.data_de_solicitacao END AS data_order_liq').where.not(restos_a_pagar: true).order('data_order_liq DESC').search(params[:q])
			end

		if params["liquidacao_sem_itens_do_empenho"].eql?("true")
			@liquidacao_sem_itens_do_empenho = true

			@liquidacoes = @q.result(distinct: true)
			.joins("INNER JOIN contabilidade_empenhos ON contabilidade_liquidacoes.empenho_id = contabilidade_empenhos.id INNER JOIN contabilidade_itens_da_nota_fiscal ON contabilidade_itens_da_nota_fiscal.liquidacao_id = contabilidade_liquidacoes.id LEFT OUTER JOIN contabilidade_itens_do_empenho ON contabilidade_itens_do_empenho.empenho_id = contabilidade_empenhos.id")
				.where("( contabilidade_itens_do_empenho.id is NULL OR (NOT contabilidade_itens_da_nota_fiscal.item_id IN (SELECT contabilidade_itens_do_empenho.item_id from contabilidade_itens_do_empenho) ) )")
					.paginate(page: params[:page], per_page: 10)
		else
			@liquidacao_sem_itens_do_empenho = false
			@liquidacoes = @q.result(distinct: false).mae_e_regular.paginate(page: params[:page], per_page: 10)
		end

		@status = Contabilidade::Liquidacao.status

		if current_usuario.desenvolvedor?
			@unidades_gestoras = contexto_atual.unidades_gestoras.order("loa_unidades_gestoras.codigo::integer")
		else
			@unidades_gestoras = contexto_atual.unidades_gestoras.joins(:unidades_orcamentarias).where(loa_unidades_orcamentarias: {id: current_usuario.unidades_orcamentarias_por_usuario.pluck(:unidade_orcamentaria_id)} ).order("loa_unidades_gestoras.codigo::integer").uniq
		end

		@pessoas = Base::Pessoa.order(:nome)
		@tipos_de_nota_fiscal = Contabilidade::Liquidacao.nota_fiscal_tipos.sort_by{ |tipo| tipo }

		if request.format.pdf?
			titulo2 = ""
			titulo3 = ""
			if params[:q].present? && params[:q]["empenho_orcamento_da_despesa_elemento_de_despesa_por_subacao_subacao_unidade_orcamentaria_unidade_gestora_id_eq"].present?
				unidade_gestora = Loa::UnidadeGestora.find(params[:q]["empenho_orcamento_da_despesa_elemento_de_despesa_por_subacao_subacao_unidade_orcamentaria_unidade_gestora_id_eq"])
				titulo2 += "Unidade Gestora: #{unidade_gestora.codigo_e_nome} - "
			else
				titulo2 += "Unidade Gestora: CONSOLIDADO - "
			end
			if params[:q].present? && params[:q]["empenho_pessoa_id_eq"].present?
				fornecedor = Base::Pessoa.find(params[:q]["empenho_pessoa_id_eq"])
				titulo3 += "Fornecedor: #{fornecedor.nome_e_cpf_ou_cnpj} - "
			end

			titulo2 += "Data: #{params[:q]["data_da_liquidacao_eq"]} - " if params[:q].present? and params[:q]["data_da_liquidacao_eq"].present?
			titulo2 += "Nº do Empenho: #{params[:q][:empenho_numero_do_empenho_eq]} - " if params[:q].present? and params[:q][:empenho_numero_do_empenho_eq].present?
			titulo3 += "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][:empenho_projeto_numero_do_processo_eq]} - " if params[:q].present? and params[:q][:empenho_projeto_numero_do_processo_eq].present?
			
			@lista_liquidacoes = @q.result(distinct: false)
		end

		@configuracoes = Configuracao.last
		respond_to do |format|
			format.html

			format.pdf do
				render pdf: "liquidacoes",
				template: 'contabilidade/liquidacoes/index.pdf.slim',
				orientation: 'Landscape',
				header: {
					html: {
						template: 'layouts/_cabecalho_pdf.html.slim',
						locals: { titulo1: 'Relação de Liquidações' , 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 /administrativo/liquidacoes/new
	def new
		if params[:empenho_id].present?
			@empenho = Contabilidade::Empenho.find(params[:empenho_id])
			valida_condicoes_para_realizar_uma_liquidacao( @empenho )
			@liquidacao = @empenho.liquidacoes.new
			@liquidacao.orcamento = @empenho.orcamento
			@medicoes_da_obra = medicoes_da_obra_quando_liquida_uma_medicao( @liquidacao.empenho )
			@liquidacao.nota_fiscal_tipo = "sem_nota"
		else
			@liquidacao = contexto_atual.liquidacoes.new
			@liquidacao.nota_fiscal_tipo = "sem_nota"
		end

		if params[:atributos].present?
			reconstroi_gerador(@liquidacao, params[:atributos])
		end
	end

	# POST /administrativo/liquidacoes
	def create
		ActiveRecord::Base.transaction do
			@empenho = Contabilidade::Empenho.find(params[:empenho_id])
			@liquidacao = @empenho.liquidacoes.new(liquidacao_params.merge(status: :solicitado))
			@liquidacao.logado_na_contabilidade = false

			if params[:empenho_id].present? && params[:contabilidade_liquidacao][:restos_a_pagar] == "false"
				@liquidacao.orcamento = @empenho.orcamento
			else
				@liquidacao.orcamento = contexto_atual
			end

			if @liquidacao.save
				if @liquidacao.mae?
					redirect_to administrativo_liquidacao_path(@liquidacao), notice: 'A liquidação foi criada com sucesso.'
				else
					redirect_to administrativo_editar_itens_liquidacao_path(@liquidacao), notice: 'A liquidação foi criada com sucesso.'
				end
			else

				if params[:contabilidade_liquidacao][:restos_a_pagar].present? && params[:contabilidade_liquidacao][:restos_a_pagar] == "true"
					params[:restos_a_pagar] = true
				end

				@medicoes_da_obra = medicoes_da_obra_quando_liquida_uma_medicao( @liquidacao.empenho )
				flash.now[:alert] = 'Não foi possível criar a liquidação, verifique as informações.'
				render :new
			end
		end
	end

	# GET /administrativo/liquidacoes/1
	def show
		if @liquidacao.liquidacao_mae.present?
			if logado_na_contabilidade?
				redirect_to contabilidade_liquidacao_path(@liquidacao.liquidacao_mae), notice: 'Liquidações salvas com sucesso'
			elsif logado_no_administrativo?
				redirect_to administrativo_liquidacao_path(@liquidacao.liquidacao_mae), notice: 'Liquidações salvas com sucesso'
			elsif logado_na_controladoria?
				redirect_to controladoria_liquidacao_path(@liquidacao.liquidacao_mae), notice: 'Liquidações salvas com sucesso'
			end
		end
	end

	# GET /administrativo/liquidacoes/1/edit
	def edit
		@empenho = @liquidacao.empenho
	end

	# PATCH/PUT /administrativo/liquidacoes/1
	def update
		@empenho = @liquidacao.empenho
		@liquidacao.logado_na_contabilidade = false

		if @liquidacao.restos_a_pagar?
			@liquidacao.restos_a_pagar = true
		end

		if @liquidacao.update(liquidacao_params)
			redirect_to administrativo_liquidacao_path(@liquidacao), notice: 'Liquidação foi atualizada com sucesso.'
		else
			@medicoes_da_obra = medicoes_da_obra_quando_liquida_uma_medicao( @liquidacao.empenho )
			flash.now[:alert] = 'Não foi possível atualizar a liquidação, verifique as informações.'
			render :edit
		end
	end

	# DELETE /administrativo/liquidacoes/1
	def destroy
		mensagem = apaga_e_retorna_mensagem(@liquidacao)
		if params[:index].present?
			redirect_to rota_liquidacoes,mensagem
		else
			@empenho = Contabilidade::Empenho.find(@liquidacao.empenho_id)
			redirect_to empenho_path(@empenho), mensagem
		end
	end

	# PATCH/PUT /administrativo/liquidacoes/1/enviar_para_controladoria
	def enviar_para_controladoria
		if @liquidacao.enviar_para_controladoria!
			redirect_to administrativo_liquidacao_url(@liquidacao), success: 'A liquidação foi encaminhada para a controladoria com sucesso.'
		else
			redirect_to administrativo_liquidacao_url(@liquidacao), alert: 'Não foi possível encaminhar a liquidação. Por favor, confira se ela contém erros'
		end
	end

	# PATCH/PUT /administrativo/liquidacoes/1/enviar_para_contabilidade
	def enviar_para_contabilidade
		if @liquidacao.enviar_para_contabilidade!
			redirect_to administrativo_liquidacao_url(@liquidacao), success: 'A liquidação foi enviada para a contabilidade.'
		else
			redirect_to administrativo_liquidacao_url(@liquidacao), alert: 'Não foi possível encaminhar a liquidação. Por favor, confira se ele contém erros'
		end
	end

	# PATCH/PUT /administrativo/liquidacoes/1/confirmar_liquidacao
	def confirmar_liquidacao
		@liquidacao.data_da_liquidacao = params[:contabilidade_liquidacao][:data_da_liquidacao].to_date
		@liquidacao.controle_cronologico = params[:contabilidade_liquidacao][:controle_cronologico] if params[:contabilidade_liquidacao][:controle_cronologico].present?
		@liquidacao.previsao_de_pagamento = params[:contabilidade_liquidacao][:previsao_de_pagamento].to_date if params[:contabilidade_liquidacao][:previsao_de_pagamento].present?

		if @liquidacao.save
			if @liquidacao.confirmar!
				redirect_to administrativo_liquidacao_url(@liquidacao), success: 'A liquidação foi confirmada.'
			else
				redirect_to administrativo_liquidacao_url(@liquidacao), alert: 'Não foi possível confirmar a liquidação. Por favor, confira se ela contém erros'
			end
		else
			redirect_to administrativo_liquidacao_url(@liquidacao), alert: 'Não foi possível confirmar a liquidação. ' + @liquidacao.errors.full_messages.join(',')
		end
	end

	# PATCH /liquidacoes/1/retornar_para_solicitado
	def retornar_para_solicitado
		@liquidacao.status = Contabilidade::Liquidacao.status[:solicitado]
		if @liquidacao.save(validate: false)
			redirect_to administrativo_liquidacao_url(@liquidacao), success: 'A liquidação foi retornada para edição.'
		else
			redirect_to administrativo_liquidacao_url(@liquidacao), alert: 'Não foi possível retornar a liquidação. Por favor, confira se ela contém erros.'
		end
	end

	def aguardar_notas_fiscais
		if @liquidacao.aguardar_notas_fiscais!
			redirect_to administrativo_liquidacao_path(@liquidacao), success: 'A liquidação está Aguardando as Notas Fiscais' 
		else
			redirect_to administrativo_liquidacao_path(@liquidacao), alert: 'Não fo possível Aguardar as Notas Fiscais. Por favor, verique se ela contém erros.'
		end
	end

	private
	def set_liquidacao
		@liquidacao = Contabilidade::Liquidacao.find(params[:id])
	end

	def disponibiliza_dependencias
		@meses = Contabilidade::Liquidacao.meses_da_folha
		@anos_de_competencia = Orcamento.all.order(exercicio: :desc)
		@meses_de_competencia = Contabilidade::Liquidacao.meses_de_competencia
		@tipos_de_nota_fiscal = Contabilidade::Liquidacao.nota_fiscal_tipos.sort_by{ |tipo| tipo }
		@orcamentos = Orcamento.all.order(exercicio: :desc).where("orcamentos.exercicio < ?", contexto_atual.exercicio)

		if params[:contabilidade_liquidacao].present? && params[:contabilidade_liquidacao][:orcamento_do_empenho_id].present?
			contexto_selecionado = Orcamento.find_by_id(params[:contabilidade_liquidacao][:orcamento_do_empenho_id])
			@unidades_orcamentarias = contexto_selecionado.unidades_orcamentarias
		else
			@unidades_orcamentarias = []
		end
	end

	def disponibiliza_dependencias_empenhos
		if params[:contabilidade_liquidacao].present? && params[:contabilidade_liquidacao][:unidade_orcamentaria_id].present?  && params[:contabilidade_liquidacao][:orcamento_do_empenho_id].present?
			@empenhos = Contabilidade::Empenho.includes(:pessoa).confirmados.joins(orcamento_da_despesa: { elemento_de_despesa_por_subacao: :subacao }).where(loa_subacoes: { unidade_orcamentaria_id: params[:contabilidade_liquidacao][:unidade_orcamentaria_id] }).select { |empenho| empenho.saldo > 0 }
		else
			@empenhos = contexto_atual.empenhos.includes(:pessoa).confirmado
		end
	end

	def disponibiliza_dependencias_obra
		set_liquidacao
		if @liquidacao.try(:persisted?) && @liquidacao.medicao_da_obra.present?
			@medicoes_da_obra = [@liquidacao.medicao_da_obra]
		else
			@medicoes_da_obra = []
		end
	end

	def valida_condicoes_para_realizar_uma_liquidacao empenho
		if empenho.saldo <= 0
			redirect_to empenho_path(empenho), alert: 'O Empenho não possui mais saldo a liquidar.'
		elsif !empenho.confirmado?
			redirect_to empenho_path(empenho), alert: 'Não é possível criar liquidações sem antes confirmar o empenho.'
		# elsif empenho.de_uma_obra? && !empenho.obra_possui_medicoes?
		# 	redirect_to empenho_path(empenho), alert: 'Empenho é de uma obra, mas a obra não possui medições para serem liquidadas. Por favor, cadastre medições na obra, para poder liquidar.'
		# Validação removida a pedido do Lukas (Módulos podem ser vendidos separadamente)
		end
	end

	def medicoes_da_obra_quando_liquida_uma_medicao empenho
		(empenho && empenho.de_uma_obra? && empenho.obra_possui_medicoes?) ? empenho.obra.medicoes_da_obra.confirmada.select { |medicao| !medicao.foi_liquidada? } : []
	end

	def verifica_status_da_liquidacao
		if @liquidacao.enviado_para_controladoria? || @liquidacao.enviado_para_contabilidade? || @liquidacao.recebido? ||	@liquidacao.enviado_para_o_financeiro? || @liquidacao.recebido_pelo_financeiro? || 	@liquidacao.enviado_para_administrativo? || @liquidacao.autorizado?
			redirect_back(fallback_location: administrativo_liquidacao_path(@liquidacao), alert: 'Essa liquidação está aguardando aprovação, portanto não pode ser editada ou excluída.')
		end
	end

	# Permite apenas os parâmetros específicos
	def liquidacao_params
		params.require(:contabilidade_liquidacao).permit( :tipo_de_reconhecimento_do_passivo, :restos_a_pagar,
			:status, :mes_de_competencia, :ano_de_competencia, :numero, :empenho_id, :medicao_da_obra_id,
			:data_de_solicitacao, :valor, :mes_da_folha, :ano_da_folha, :numero_da_fatura, :tipo_da_folha, :data_de_emissao_da_folha,
			:historico, :nota_fiscal_numero, :descrimina_itens_processo_ou_empenho, :nota_fiscal_tipo, :de_multiplas_notas_fiscais, 
			:orcamento_id, :status_restos_a_pagar, :controle_cronologico, :previsao_de_pagamento
		)
	end
end
