class Contabilidade::ContasController < ApplicationController
	include ContabilidadeControllerConcern
	include ControllerConcern
	before_action :authenticate_usuario!
	before_action :autoriza_usuario!, except: [:retorna_dados_da_conta, :registros_contabeis]
	before_action :set_contabilidade, only: [:index, :new, :create]
	before_action :set_conta, except: [:index, :new, :create, :atualiza_saldos_de_contas]
	before_action :disponibiliza_dependencias, only: [:index, :new, :edit]

	def index
		@q = @contabilidade.contas.order(:codigo).search(params[:q])

		if request.format == 'json'
			# LISTA DE CONTAS QUE PODEM SER LISTADAS NO CADASTRO DE CONTAS EXTRA ORCAMENTARIAS
			if @q.classe_pcasp_eq.present?
				ids_rpps_circulante = @q.result.where("(codigo like '1144101%' and subitem in ('01', '02', '03', '04', '05', '06', '07', '08', '09'))
				OR (codigo like '1144102%' and subitem in ('01', '02')) OR (codigo like '1144103%' and subitem in ('01', '02', '03')) OR (codigo like '1144104%' and subitem in ('01', '02', '03'))
				OR (codigo like '114410500') OR (codigo like '114410600') OR (codigo like '114410700')  OR (codigo like '1144111%' and subitem in ('01', '02', '03', '04', '05', '06', '07'))
				OR (codigo like '1144112%' and subitem in ('01', '02')) OR (codigo like '1144113%' and subitem in ('01', '02', '03'))  OR (codigo like '1144114%' and subitem in ('01', '02', '03'))
				OR (codigo like '114411500') OR (codigo like '114411600') OR (codigo like '114411700') OR (codigo like '114413000') OR (codigo like '114419900')").ids rescue []

				ids_rpps_nao_circulante = @q.result.where("(codigo like '1223101%' and subitem in ('01', '02')) OR (codigo like '122310300') OR (codigo like '122310400') OR (codigo like '122310500')").ids rescue []
				ids_rpps_nao_circulante_sem_rpps = @q.result.where("codigo like any (array['121210101', '121210199', '121210601', '121210602', '121210603', '121210604', '121210605', '121210606', '121210607', '121210699', '121210900', '121220000', '121230000', '121240000', '121250000', '121310101', '121310102', '121310103', '121310109', '121310199', '121310201', '121310202', '121310300', '121310400', '121310801', '121319800', '121319901', '121319902', '121319903', '121319904', '121319999'])").ids rescue []

				if @q.classe_pcasp_eq == 2 && params[:q][:grupo_pcasp_eq] == "circulante"
					@contas = @q.result.where("(codigo like any (array['218810103', '218810105', '218810110', '218810111', '218810113', '218810114', '218810115', '218810116', '218810117', '218810199', '2188102%', '218810301', '218810302', '218810401', '218810402', '218810403', '218810404', '218810405', '218810499', '2188199%', '218820101', '218820104', '218820108', '218830102', '218830104', '218810801', '218810802', '218820109', '218820112', '218820199', '218820200', '218820300', '218820400', '218820800', '218829900', '218830106', '218830199', '218830200', '218830300', '218830400', '218830800', '218839900', '218840107', '218840109', '218840199', '218840200', '218840300', '218840400', '218840800', '218849900', '218850108', '218850109', '218850199', '218850200', '218850300', '218850400', '218850800', '218859900']))")
				elsif @q.classe_pcasp_eq == 1 && params[:q][:grupo_pcasp_eq] == "circulante" && !params[:investimento_rpps_marcado].to_boolean
					@contas = @q.result.where("(codigo like any (array['1138108%', '1138109%', '1138111%', '1138113%', '1138117%', '1138199%']))")
				elsif @q.classe_pcasp_eq == 1 && params[:q][:grupo_pcasp_eq] == "circulante" && params[:investimento_rpps_marcado].to_boolean
					#curto prazo
					@contas = @q.result.where("(codigo like any (array['114410101', '114410102', '114410103', '114410104', '114410105', '114410106', '114410107', '114410108', '114410109', '114410201', '114410202', '114410301', '114410302', '114410303', '114410401', '114410402', '114410403', '1144105%', '1144106%', '1144107%', '114411101', '114411102', '114411103', '114411104', '114411105', '114411106', '114411107', '114411108', '114411201', '114411202', '114411301', '114411302', '114411303', '114411401', '114411402', '114411403', '1144115%', '1144116%', '1144117%', '1144130%', '1144199%']))")
				elsif @q.classe_pcasp_eq == 1 && params[:q][:grupo_pcasp_eq] == "circulante" && params[:investimento_rpps_marcado].to_boolean
					#longo prazo
					@contas = @q.result.where("(codigo like any (array['122310101', '122310102', '1223103%', '1223104%', '1223105%']))")
				elsif @q.classe_pcasp_eq == 1 && params[:investimento_rpps_marcado].to_boolean && params[:q][:grupo_pcasp_eq] == "circulante"
					@contas = @q.result.where(id: ids_rpps_circulante)
				elsif @q.classe_pcasp_eq == 1 && params[:investimento_rpps_marcado].to_boolean && params[:q][:grupo_pcasp_eq] == "nao_circulante"
					@contas = @q.result.where(id: ids_rpps_nao_circulante)
				elsif @q.classe_pcasp_eq == 1 && params[:investimento_rpps_marcado].to_boolean == false && params[:q][:grupo_pcasp_eq] == "nao_circulante"
					@contas = @q.result.where(id: ids_rpps_nao_circulante_sem_rpps)
				elsif @q.classe_pcasp_eq == 1 && params[:q][:grupo_pcasp_eq] == "circulante"
					@contas = @q.result.where("(codigo like '11381%') or (codigo like '11351%')").where.not(id: ids_rpps_circulante.ids)
				elsif @q.classe_pcasp_eq == 2 && params[:q][:grupo_pcasp_eq] == "circulante"
					@contas = @q.result.where("codigo like '2188%'").where.not(id: ids_rpps_circulante)
				elsif @q.classe_pcasp_eq == 1 && params[:q][:grupo_pcasp_eq] == "nao_circulante"
					@contas = @q.result.where("(codigo like '12381%')").where.not(id: ids_rpps_nao_circulante)
				elsif @q.classe_pcasp_eq == 2 && params[:q][:grupo_pcasp_eq] == "nao_circulante"
					@contas = @q.result.where("codigo like '2288%'").where.not(id: ids_rpps_nao_circulante)
				else
					@contas = @q.result(distinct: false)
				end
			end

		else
			if params[:exibir_somente_com_saldo].present? && params[:exibir_somente_com_saldo] == "true"
				@exibir_somente_com_saldo = params[:exibir_somente_com_saldo]
				@contas = @q.result(distinct: false).select{ |conta|  conta if conta.saldo_agregado != 0}.paginate(page: params[:page], per_page: 20)
			else
				@exibir_somente_com_saldo = 'false'
				@contas = @q.result(distinct: false).paginate(page: params[:page], per_page: 20)
			end
		end

		respond_to do |format|
			format.html
			format.json { render json: @contas, methods: :codigo_formatado_e_nome }
		end
	end

	def show
		@unidades_orcamentarias = @conta.unidades_orcamentaria_utilizadas.order(:nome)
		@sub_contas = contexto_atual.sub_contas_pcasp.sort_by{ |sub_conta| sub_conta.codigo_formatado }

		@q = @conta.movimentacoes_do_plano_de_contas_com_contas_filhas.search(params[:q])
		@movimentacoes = @q.result(distinct: false).paginate(page: params[:page], per_page: 20)
	end

	def new
		if params[:conta_pai_id].present?
			disponibiliza_conta_pai( params[:conta_pai_id] )
			preenche_label_de_codigo( @conta_pai )
			@conta = @contabilidade.contas.new
		else
			redirect_to contabilidade_contas_path( exercicio: contabilidade_atual.exercicio ), alert: 'Selecione uma conta da lista, para adicionar um novo detalhamento.'
		end
	end

	def create
		if params[:conta_pai_id].present?
			@conta = @contabilidade.contas.new( conta_params )
			@conta.conta_pai_id = params[:conta_pai_id]
			if @conta.save
				atualiza_unidades_orcamentarias_com_id_da_conta( @conta, params[:unidades_orcamentarias].values ) if params[:unidades_orcamentarias].present?
				redirect_to @conta, notice: 'Novo detalhamento de conta adicionado com sucesso.'
			else
				disponibiliza_dependencias
				disponibiliza_conta_pai( params[:conta_pai_id] )
				preenche_label_de_codigo( @conta_pai )
				if @conta.codigo
					quantidade_de_digitos = @conta.classificacao_com_niveis_preenchidos.values.size > 5 ? 2 : 1
					@conta.codigo = conta_params[:codigo].rjust(quantidade_de_digitos, '0') if conta_params[:codigo].present?
				end
				render :new
			end
		else
			redirect_to contabilidade_contas_path( exercicio: contabilidade_atual.exercicio ), alert: 'Selecione uma conta da lista, para adicionar um novo detalhamento.'
		end
	end

	def edit
		@codigo_formatado = @conta.codigo_formatado
		preenche_label_de_codigo_edit( @conta )
		@conta.codigo = @conta.classificacao_com_niveis_preenchidos.values.last.to_s
	end

	def update
		attributes = conta_params
		conta = Contabilidade::Conta.find( @conta.id )
		if conta_params[:codigo].present?
			niveis_preenchidos = conta.classificacao_com_niveis_preenchidos.values
			niveis_preenchidos.pop
			codigo = gera_novo_codigo(niveis_preenchidos.join(''), conta_params[:codigo])
			attributes[:codigo] = codigo
		end

		if @conta.update( attributes )
			atualiza_unidades_orcamentarias_com_id_da_conta( @conta, params[:unidades_orcamentarias].values ) if params[:unidades_orcamentarias].present?
			redirect_to @conta, notice: 'Conta atualizada com sucesso.'
		else
			disponibiliza_dependencias
			@codigo_formatado = conta.codigo_formatado
			preenche_label_de_codigo_edit(conta)
			quantidade_de_digitos = conta.classificacao_com_niveis_preenchidos.values.size > 5 ? 2 : 1
			@conta.codigo = conta_params[:codigo].rjust(quantidade_de_digitos, '0') if conta_params[:codigo].present?
			render :edit
		end
	end

	def destroy
		mensagem = apaga_e_retorna_mensagem(@conta)
		redirect_to contabilidade_contas_path( exercicio: @conta.orcamento.exercicio ), mensagem
	end

	def registros_contabeis
		return if bloqueia_usuario_com_base_em 'create'
		@conta = Contabilidade::Conta.find( params[:id] )
		@unidades_orcamentarias = @conta.unidades_orcamentaria_utilizadas.order(:nome)
		@q = @conta.movimentacoes_do_plano_de_contas.order("data_de_lancamento desc, created_at desc").search(params[:q])
		@movimentacoes_do_plano_de_contas = @q.result(distinct: false).paginate(page: params[:page], per_page: 20)

		data_inicial = params[:q][:data_de_lancamento_gteq].to_date - 1.day rescue nil
		data_final = params[:q][:data_de_lancamento_lteq] rescue nil
		unidade_orcamentaria_id = params[:q][:unidade_orcamentaria_id_eq] rescue nil

		if data_inicial.present?
			@saldo_anterior = @conta.saldo_da_conta(data_inicial, unidade_orcamentaria_id)
		else
			@saldo_anterior = 0
		end

		@saldo_atual = @conta.saldo_da_conta(data_final, unidade_orcamentaria_id)
	end

	# GET /contas/:id/retorna_dados_do_detalhamento
	def retorna_dados_da_conta
		render json: {
			'descricao': @conta.descricao,
		}
	end

	# PATCH /contas/atualiza_saldos_de_contas
	def atualiza_saldos_de_contas
		contexto_atual.contas.ids.each do |conta_id|
			ActiveRecord::Base.connection.execute("( SELECT somar_valores_movimentacoes(#{conta_id}, #{contexto_atual.exercicio}) )");
		end

		redirect_to contabilidade_contas_path( exercicio: contexto_atual.exercicio )
	end

	private
	def disponibiliza_conta_pai conta_pai_id
		@conta_pai = Contabilidade::Conta.find( conta_pai_id )
	end

	def atualiza_unidades_orcamentarias_com_id_da_conta conta, unidades_orcamentarias_ids
		conta.unidades_orcamentarias.delete_all
		conta.unidades_orcamentarias << Loa::UnidadeOrcamentaria.where( id: unidades_orcamentarias_ids )
	end

	def disponibiliza_dependencias
		@unidades_orcamentarias = contabilidade_atual.unidades_orcamentarias.joins(:orgao).order('loa_orgaos.codigo, loa_unidades_orcamentarias.codigo')
	end

	def preenche_label_de_codigo conta_pai
		if params[:tipo] == "divida_ativa" || params[:tipo] == "provisoes"	|| params[:tipo] == "rpps"
			numero_de_registros = Contabilidade::Conta.where('conta_pai_id is not null AND LENGTH(codigo) < 6').count + 1
			novo_codigo = "1." + numero_de_registros.to_s.rjust(3, '0')

			@classificacao_com_niveis_preenchidos = novo_codigo
			@vem_com_codigo = 's'
		elsif params[:tipo] == "precatorio"
			@classificacao_com_niveis_preenchidos = params[:detalhamento_extra]
			@vem_com_codigo = 's'
		else
			@classificacao_com_niveis_preenchidos = []
			@vem_com_codigo = 'n'
		end
	end

	def preenche_label_de_codigo_edit conta
		niveis_preenchidos = conta.classificacao_com_niveis_preenchidos.values
		niveis_preenchidos.pop
		@classificacao_com_niveis_preenchidos = niveis_preenchidos.join('.') + "."
		nives_nao_preenchidos = conta.classificacao_niveis_nao_preenchidos.values
		@classificacao_niveis_nao_preenchidos = "."+ nives_nao_preenchidos.join('.') if nives_nao_preenchidos.present?
	end

	def set_contabilidade
		@contabilidade = Orcamento.find_by(exercicio: params[:exercicio])
	end

	def set_conta
		@conta = Contabilidade::Conta.find( params[:id] )
	end

	def gera_novo_codigo codigo_do_pai, novo_codigo
		if codigo_do_pai.length > 5
			return (codigo_do_pai + novo_codigo.rjust(2, '0')).ljust(9, '0')
		else
			return (codigo_do_pai + novo_codigo).ljust(9, '0')
		end
	end

	def conta_params
		params.require(:contabilidade_conta).permit(
			:codigo, :nome, :status, :descricao, :natureza_do_saldo, :registro_de_evento_contabil_obrigatorio, :atributo_de_conta, :nivel_de_consolidacao,
			:evento_contabil_id, :detalhamento_extra, :exibir_somente_com_saldo
		)
	end
end
