class ApplicationController < ActionController::Base
	include ContextoConcern
	include RequisicaoDeRelatorioConcern
	
	layout :define_layout

	protect_from_forgery prepend: true, with: :exception

	add_flash_types :error, :info, :warning, :success

	respond_to :html, :json

	before_action :verifica_bloqueio_geral, unless: proc { self.action_name == 'bloqueio_geral' }
	before_action :configure_permitted_parameters, if: :devise_controller?
	before_action :set_raven_context, if: lambda{ Rails.env.production? }
	before_action :setar_contexto_atual_para_modelo
	before_action :executar_relatorio_em_segundo_plano

	helper_method :esta_autorizado?
	helper_method :verifica_administrador
	helper_method :verifica_autorizacao_para_status_de_orcamento
	helper_method :subacao_ou_acao_correspondente
	helper_method :configuracao
	helper_method :verifica_autorizacao

	def configuracao
		Configuracao.includes(:parametrizacao_modulos).last
	end

	def setar_contexto_atual_para_modelo
		Thread.current[:contexto_atual] = contexto_atual
	end

	def manter_form_apos_cadastro?
		params[:manter_form].present?
	end

	def esta_autorizado?(nome_da_acao, nome_do_controle = controller_path, status_objeto = nil )
		return true
	end

	def verifica_administrador
		current_usuario.perfil.nome.downcase == 'administrador'
	end

	def subacao_ou_acao_correspondente subacao
		orcamento_atual && orcamento_atual.trabalha_com_subacao? ? subacao : subacao.acao
	end

	def verifica_bloqueio_geral
		unless (controller_name == 'usuarios' || controller_name == 'lotes' || controller_name == 'sessions') || current_usuario&.desenvolvedor?
			redirect_to bloqueio_geral_path if configuracao.sistema_bloqueado?
		end
	end

	def info_for_paper_trail
		{
			usuario_id: current_usuario.try( :id ),
			ip: request.remote_ip,
			user_agent: request.user_agent
		}
	end

	def bloquear_orcamento
		#alterado de acordo com o chamado S#209
		if contexto_atual.encerrado?
			if params[:action] == "new"
				acao = "o cadastro"
			elsif params[:action] == "edit"
				acao = "a alteração"
			elsif params[:action] == "destroy"
				acao = "a exclusão"
			else
				acao = "a ação"
			end
			if contexto_atual.enviado_para_votacao?
				texto = "PLOA está EM VOTAÇÃO."
			elsif contexto_atual.aprovado?
				texto = "PLOA está APROVADO."
			elsif contexto_atual.encerrado?
				texto = "LOA está ENCERRADO."
			end
			redirect_back(fallback_location: orcamento_path(contexto_atual), alert: "Não é possivel realizar " + acao + " pois " + texto)
		end
	end

	private

	def set_raven_context
		#Sentry.set_user(id: current_usuario.try(:id)) # or anything else in session
		#Raven.extra_context(params: params.to_unsafe_h, url: request.url)
	end

	def after_sign_in_path_for(resource)
		seleciona_modulo_path
	end

	def after_sign_out_path_for(resource_or_scope)
		if resource.class == PpaParticipativo::Cidadao
			ppa_participativo_path
		else
			new_usuario_session_path
		end
	end

	def define_layout
		if devise_controller? && resource_name == :cidadao
			"ppa_participativo/application"
		else
			"application"
		end
	end

	def configure_permitted_parameters
		campos_permitidos = [:nome_completo, :nome_de_usuario] if resource_name == :usuario
		campos_permitidos = [:nome, :cpf_cnpj, :aceitou_os_termos_de_uso] if resource_name == :cidadao

		devise_parameter_sanitizer.permit(:sign_up, keys: campos_permitidos)
		devise_parameter_sanitizer.permit(:sign_in, keys: [:email, :cpf])
		devise_parameter_sanitizer.permit(:account_update, keys: campos_permitidos)
	end

	def renderiza_404
		render file: 'public/404.html', status: :not_found and return
	end

	def autoriza_usuario!( action = action_name, controller = controller_path, format = request.format )
		unless Rails.env.test?
			return if action == "almoxarifados_por_unidade_orcamentaria" && controller == "pesquisas"
			unless verifica_autorizacao(action, controller, format)
				render 'inicio/acesso_negado', layout: false
			end
		end
	end

	def verifica_autorizacao(action = action_name, controller = controller_path, format = request.format)
		return true if self.verifica_administrador # retorna true se usuario atual é administrador
		return true if format.js? || format.json?
		return true if controller.to_s.include?("Relatorio")
		return true if controller.to_s.include?("relatorios")
		# ajuste temporário para resolver o problema de redirecionamento de página onde muda o controller
		return true if controller == ("contabilidade/fiscalizacoes")
		return modulo = Acesso::Modulo.find_by(nome_do_modulo: "loa")  if controller == ("orcamentos")
		return controle = Acesso::Controle.find_by(nome_do_controle: "loa/orcamentos") if controller == ("orcamentos")
		
		modulo = Acesso::Modulo.find_by(nome_do_modulo: controller.to_s.split("/")&.first&.gsub('_', '')) 
		
		unless modulo.present?
			modulo = Acesso::Modulo.find_by(nome_do_modulo: 'administracao')
		end
			
		controle = Acesso::Controle.find_by(nome_do_controle: controller.to_s.gsub("_", "")) 
		permissao = current_usuario.perfil.permissoes.joins(controle: :modulo).find_by(acesso_modulos: { id: modulo&.id }, controle: controle, permitido: true)
		
		return permissao.present?
	end

	alias_method :bloqueia_usuario_com_base_em, :autoriza_usuario!

	def acao_acessivel_no_modulo?(acao:, controller:, modulo:)
		!(PERMISSAO_POR_MODULO.has_key?(controller) && PERMISSAO_POR_MODULO[controller].has_key?(modulo)) || acao.in?(PERMISSAO_POR_MODULO[controller][modulo].to_a)
	end

	def verifica_se_tem_contexto_valido_na_sessao!
		redirect_to contexto_path if contexto_atual.blank? || (contexto_atual == contabilidade_atual)
	end

	def verifica_autorizacao_para_status_de_orcamento(status_objeto = nil)
		!(contexto_atual.is_a?(Orcamento) && (status_objeto == 'aberto' && contexto_atual.status == 'fechado'))
	end

	def verifica_autorizacao_para_status_de_orcamento_helper(status_objeto = nil)
		if contexto_atual.class.to_s == 'Orcamento'
			redirect_to acesso_negado_path if status_objeto == 'aberto' && contexto_atual.status == 'fechado'
			return false
		end
	end

	def setar_contexto_portal_da_transparencia(orcamento_id)
		session[:contexto_tipo] = "Orcamento"
		session[:contexto_id] = orcamento_id
	end

	def alias_da_acao(action)
		alias_das_acoes = {
			'show' => 'read',
			'index' => 'read',
			'new' => 'create',
			'edit' => 'update',
			'edit_password' => 'update_password',
			'configura_detalhamento_de_despesas_nas_iniciativas' => 'configuracoes',
			'prepara_importacao' => 'importar'
		}

		alias_das_acoes[action] || action
	end

	def lista_de_acoes_de_mudancas
		['edit', 'update', 'new', 'create', 'destroy', 'finalizar_ppa', 'new_copiar_calculos_de_projecoes', 'configuracoes', 'remover_receitas_do_calculo', 'recalcular_valor_das_receitas', 'importar_receitas_para_projecao', 'create_interna', 'update_interna']
	end

	def verifica_acesso_usuario objeto
		redirect_to({action: 'index'}, alert: "Você não possui acesso a esse #{objeto.class.name.demodulize.underscore.humanize}") unless current_usuario.visualiza?(objeto)
	end

	def query_params
		query = params[:q] || {}
		Hash[query.each { |key, value| [key, value.strip] }]
	end

	def verifica_mes_bloqueado(objeto)
		if objeto.present? && objeto.mes_bloqueado?
			redirect_to request.env["HTTP_REFERER"], alert: "O mês do objeto está bloqueado, solicite o desbloqueio ao administrador"
		end
	end
end
