module Base
	class ContasBancariasController < ApplicationController
		include ControllerConcern
		before_action :authenticate_usuario!
		before_action :autoriza_usuario!,  except: [:registro_bancario]
		before_action :set_conta_bancaria, only: [:show, :edit, :update, :destroy, :get_saldo, :get_unidades_orcamentarias, :movimentacoes, :ativar]
		before_action :disponibiliza_dependencias, only: [:new, :edit, :index, :registros_bancarios, :show]
		before_action :disponibiliza_convenio, only: [:new ,:edit , :create , :update]

		# GET /base/contas_bancarias
		def index
			if params[:inativacao] == "1"
				@q = Base::ContaBancaria.left_outer_joins(agencia: :banco).includes(agencia: :banco).order("CAST(regexp_replace(regexp_replace(replace(upper(numero_da_conta), 'X', '0'), '[-.()* ]+', '', 'g'), '[^0-9]+' , '', 'g')	as numeric(15, 0)) ASC").ransack(query_params)
			else
				@q = Base::ContaBancaria.where(data_de_inativacao: nil).left_outer_joins(agencia: :banco).includes(agencia: :banco).order("CAST(regexp_replace(regexp_replace(replace(upper(numero_da_conta), 'X', '0'), '[-.()* ]+', '', 'g'), '[^0-9]+' , '', 'g')	as numeric(15, 0)) ASC").ransack(query_params)
			end
			@contas_bancarias = @q.result(distinct: false).sort_by{|conta| [conta.sigla, conta.numero_da_conta.gsub(/-(.*)/, "").gsub(/[,.-]/, '').gsub(/[Xx]/, '0').to_i]}.paginate(page: params[:page], per_page: 20)
			@contas_bancarias_modal = Base::ContaBancaria.all.sort_by{|conta| [conta.sigla, conta.numero_da_conta.gsub(/-(.*)/, "").gsub(/[,.-]/, '').gsub(/[Xx]/, '0').to_i]}
		end

		# GET /base/contas_bancarias/1
		def show
			@conta_bancaria_por_unidades_orcamentarias = @conta_bancaria.contas_bancarias_por_unidade_orcamentaria.order('principal desc, id')

			@exibir_fonte_de_recursos = true if params[:exibir_fontes].present?

			if params[:contabilidade_movimentacao_da_conta_bancaria].present?
				for_ransack = Hash.new
				movimentacoes_da_conta_bancaria_do_orcamento = Base::ContaBancaria.find(params[:id]).movimentacoes_do_exercicio(contexto_atual)
				
				for_ransack["data_da_movimentacao_gteq"] = params[:contabilidade_movimentacao_da_conta_bancaria][:data_inicial].present? ? params[:contabilidade_movimentacao_da_conta_bancaria][:data_inicial] : Date.today
				for_ransack["data_da_movimentacao_lteq"] = params[:contabilidade_movimentacao_da_conta_bancaria][:data_final].present? ? params[:contabilidade_movimentacao_da_conta_bancaria][:data_final] : Date.today


				@data_inicial = for_ransack["data_da_movimentacao_gteq"]
				@data_final = for_ransack["data_da_movimentacao_lteq"]
				@q = movimentacoes_da_conta_bancaria_do_orcamento.ransack(for_ransack)

				@movimentacoes_do_periodo = @q.result(distinct: false).order(data_da_movimentacao: :asc).paginate(page: params[:page], per_page: 50)
				@saldo_anterior = movimentacoes_da_conta_bancaria_do_orcamento.where('data_da_movimentacao < ?', @data_inicial.to_date).sum(:valor)
				@saldo_final = @saldo_anterior + @movimentacoes_do_periodo.sum{|f| f.valor.to_d}
				params[:tab] = 'movimentacoes'
			else
				@movimentacoes_do_periodo = Array.new
			end
		
		end

		# GET /base/contas_bancarias/new
		def new
			if params[:agencia_id].present?
				@agencia = Base::Agencia.find(params[:agencia_id])
				@conta_bancaria = @agencia.contas_bancarias.new
			else
				@conta_bancaria = Base::ContaBancaria.new
			end

			@conta_bancaria.orcamento_id = contexto_atual.id
		end

		# GET /base/contas_bancarias/1/edit
		def edit
			@conta_bancaria.orcamento_id = contexto_atual.id
		end

		def registros_bancarios
			@q = Base::ContaBancariaPorUnidadeOrcamentaria.left_outer_joins(conta_bancaria: {agencia: :banco}).order("base_contas_bancarias.conta_caixa_pcasp DESC, base_bancos.sigla ASC, base_contas_bancarias.numero_da_conta ASC  ").joins(unidade_orcamentaria: :orgao).where("loa_orgaos.orcamento_id =?", contexto_atual.id).ransack(query_params)
			@contas_bancaria_por_unidades_orcamentarias = @q.result(distinct: false).sort_by{|conta_por_unidade| [conta_por_unidade.conta_bancaria.sigla, conta_por_unidade.conta_bancaria.numero_da_conta.gsub(/-(.*)/, "").gsub(/[,.-]/, '').gsub(/[Xx]/, '0').to_i]}.paginate(page: params[:page], per_page: 20)
		end

		def registro_bancario
			return if bloqueia_usuario_com_base_em 'registros_bancarios'
			@conta_bancaria_por_unidade_orcamentaria =  Base::ContaBancariaPorUnidadeOrcamentaria.find( params[:conta_bancaria_por_unidade_orcamentaria] )
			
			if params[:contabilidade_movimentacao_da_conta_bancaria].present?
				for_ransack = Hash.new
				movimentacoes_da_conta_bancaria_do_orcamento = @conta_bancaria_por_unidade_orcamentaria.conta_bancaria.movimentacoes_do_exercicio(contexto_atual)
				
				for_ransack["data_da_movimentacao_gteq"] = params[:contabilidade_movimentacao_da_conta_bancaria][:data_inicial].present? ? params[:contabilidade_movimentacao_da_conta_bancaria][:data_inicial] : Date.today
				for_ransack["data_da_movimentacao_lteq"] = params[:contabilidade_movimentacao_da_conta_bancaria][:data_final].present? ? params[:contabilidade_movimentacao_da_conta_bancaria][:data_final] : Date.today


				@data_inicial = for_ransack["data_da_movimentacao_gteq"]
				@data_final = for_ransack["data_da_movimentacao_lteq"]
				@q = movimentacoes_da_conta_bancaria_do_orcamento.ransack(for_ransack)

				
				@movimentacoes_do_periodo = @q.result(distinct: false)
				@saldo_anterior = movimentacoes_da_conta_bancaria_do_orcamento.where('data_da_movimentacao < ?', @data_inicial).sum(:valor)
				@saldo_final = @saldo_anterior + @movimentacoes_do_periodo.sum{|f| f.valor.to_d}
				params[:tab] = 'movimentacoes'
			else
				@movimentacoes_do_periodo = Array.new
			end
		end

		# POST /base/contas_bancarias
		def create
			if params[:agencia_id].present?
				@agencia = Base::Agencia.find(params[:agencia_id])
				@conta_bancaria = @agencia.contas_bancarias.new(conta_bancaria_params.merge(tipo: :unidade_orcamentaria))
			else
				@conta_bancaria = Base::ContaBancaria.new(conta_bancaria_params.merge(tipo: :unidade_orcamentaria))
			end
			@conta_bancaria.logado_na_contabilidade = true if logado_na_contabilidade?

			if conta_bancaria_params[:contas_bancarias_por_unidade_orcamentaria_attributes].present? && @conta_bancaria.contas_bancarias_por_unidade_orcamentaria.size == 1 && @conta_bancaria.contas_bancarias_por_unidade_orcamentaria.map{ |f| f.principal == false }.all?
				@conta_bancaria.contas_bancarias_por_unidade_orcamentaria.first.principal = true
			end

			if @conta_bancaria.save
				# forçando salvar a fonte. Por algum motivo no create não salva
				if @conta_bancaria.fontes_de_recursos_da_conta_bancaria.empty? && conta_bancaria_params[:fontes_de_recursos_da_conta_bancaria_attributes].present?
					conta_bancaria_params[:fontes_de_recursos_da_conta_bancaria_attributes].each do |parametros_da_fonte|
						@conta_bancaria.fontes_de_recursos_da_conta_bancaria.create(fonte_de_recurso_id: parametros_da_fonte[1][:fonte_de_recurso_id])
					end
				end
				redirect_to @conta_bancaria, notice: 'Conta bancária foi criada com sucesso.'
			else
				disponibiliza_dependencias
				render :new
			end
		end

		# PATCH/PUT /base/contas_bancarias/1
		def update
			@conta_bancaria.logado_na_contabilidade = true if logado_na_contabilidade?
			if @conta_bancaria.update( conta_bancaria_params )
				redirect_to @conta_bancaria, notice: 'Conta bancária foi atualizada com sucesso.'
			else
				disponibiliza_dependencias
				flash.now[:alert] = 'Não foi possível atualizar a conta.' + @conta_bancaria.errors.full_messages.join(',')
				render :edit
			end
		end

		# DELETE /base/contas_bancarias/1
		def destroy
			@conta_bancaria.exclusao_completa = true
			mensagem = apaga_e_retorna_mensagem(@conta_bancaria)
			redirect_to base_contas_bancarias_path, mensagem
		end

		# PATCH /base/contas_bancarias/1
		def ativar
			@conta_bancaria.logado_na_contabilidade = true if logado_na_contabilidade?
			@conta_bancaria.data_de_inativacao = nil
			if @conta_bancaria.save
				redirect_to @conta_bancaria, notice: 'Conta bancária foi ativada com sucesso.'
			end
		end

		def get_saldo
			params = get_saldo_params
			saldo = @conta_bancaria.contas_bancarias_por_unidade_orcamentaria.find_by(unidade_orcamentaria_id: params[:unidade_orcamentaria_id]).try(:saldo_atual)

			respond_to do |format|
				format.json { render json: {saldo: saldo.to_f} }
			end
		end

		def get_unidades_orcamentarias
			unidades_orcamentarias = @conta_bancaria.unidades_orcamentarias.order(:id)

			respond_to do |format|
				format.json { render json: {unidades_orcamentarias: unidades_orcamentarias} }
			end
		end

		def retorna_registro
			@registro = Base::ContaBancariaPorUnidadeOrcamentaria.where(conta_bancaria_id: params[:id_banco] , principal: true).all
			render json: {
				'id': @registro.ids
			}
		end

		def disponibiliza_convenio
			@convenios = Contabilidade::ConvenioBancario.all
		end

		def movimentacoes
			@q = Contabilidade::MovimentacaoDaContaBancaria.joins(conta_bancaria_por_unidade_orcamentaria: :conta_bancaria).where("base_contas_bancarias.id = ? and (conciliada is false or conciliada is null)", params[:id]).order("data_da_movimentacao DESC").ransack(query_params)
			@movimentacoes_da_conta_bancaria = @q.result(distinct: false).limit(200)
			render json: @movimentacoes_da_conta_bancaria
		end

		private
		def set_conta_bancaria
			@conta_bancaria = Base::ContaBancaria.find( params[:id] )
		end

		def disponibiliza_dependencias
			@configuracao = Configuracao.last
			@tipos_de_conta_bancaria = Base::ContaBancaria.tipo_de_contas

			if contexto_atual.exercicio >= 2022
				@tipos_de_conta_pcasp = Base::ContaBancaria.tipos_de_conta_pcasp_i18n.reject { |k| k.eql?('conta_caixa') || k.eql?('conta_movimento_plano_financeiro') || k.eql?('conta_movimento_plano_previdenciario') }.invert.sort
			else
				@tipos_de_conta_pcasp = Base::ContaBancaria.tipos_de_conta_pcasp_i18n.reject { |k| k.eql?('conta_caixa') || k.eql?('conta_movimento_fundo_em_reparticao') || k.eql?('conta_movimento_fundo_em_capitalizacao') }.invert.sort
			end

			@funcoes = contexto_atual.funcoes
			@fontes_de_recursos = contexto_atual.fontes_de_recursos.order(:codigo)
			@unidades_orcamentarias = contexto_atual.unidades_orcamentarias.order(:codigo, :nome)
			@bancos = Base::Banco.order(:numero_do_banco)
			@agencias = []
			@agencias = (@conta_bancaria && @conta_bancaria.banco_id.present?) ? Base::Agencia.where(banco_id: @conta_bancaria.banco_id) : []
		end

		# Permite apenas os parâmetros específicos
		def conta_bancaria_params
			params.require(:base_conta_bancaria).permit(
				:numero_da_conta, :data_de_abertura, :tipo_de_conta, :funcao_id, :agencia_id, :banco_id, :data_de_inativacao, :inativacao,
				:descricao_do_vinculo, :saldo_de_implantacao, :nomenclatura, :operacao, :tipo_de_conta_pcasp, :convenio_bancario_id, 
				:convenio_para_boletos, :exibir_na_api, :orcamento_id, :codigo_ug, :codigo_gestao,
				fontes_de_recursos_da_conta_bancaria_attributes: [
					:id,
					:fonte_de_recurso_id,
					:conta_bancaria_id,
					:saldo_inicial,
					:_destroy
				],
				contas_bancarias_por_unidade_orcamentaria_attributes: [
					:id,
					:conta_bancaria_id,
					:unidade_orcamentaria_id,
					:principal,
					:data_de_abertura,
					:_destroy
				]
			)
		end

		def get_saldo_params
			params.permit(
				:unidade_orcamentaria_id
			)
		end
	end
end
