require 'rails_helper'
include ActiveSupport::Testing::TimeHelpers

RSpec.describe Ppa::PpasController, type: :controller do
	sign_in_admin
	set_ppa_id_na_sessao

	# Isso deve retornar o mínimo de atributos obrigatórios para criar um
	# Ppa::Ppa válido.
	let(:atributos_validos) {
		FactoryBot.attributes_for( :ppa_fortaleza_2014 )
	}

	let(:atributos_invalidos) {
		{ prefeito: '' }
	}

	describe "GET #index" do
 		it "atribui a lista de ppa_ppas à @ppa_ppas" do
			ppa = Ppa::Ppa.create! atributos_validos
			get :index
			expect(assigns(:ppa_ppas)).to include(ppa)
		end
	end

	describe "GET #show" do
		it "atribui a ppa_ppa requisitado(a) à @ppa_ppa" do
			FactoryBot.create(:configuracao)
			ppa = Ppa::Ppa.create! atributos_validos
			get :show, params: {id: ppa.to_param}
			expect(assigns(:ppa_ppa)).to eq(ppa)
		end
	end

	describe "GET #new" do
		it "atribui um(a) novo(a) ppa_ppa à @ppa_ppa" do
			get :new
			expect(assigns(:ppa_ppa)).to be_a_new(Ppa::Ppa)
		end
	end

	describe "GET #edit" do
		it "atribui o(a) ppa_ppa requisitado à @ppa_ppa" do
			ppa = Ppa::Ppa.create! atributos_validos
			get :edit, params: {id: ppa.to_param}
			expect(assigns(:ppa_ppa)).to eq(ppa)
		end
	end

	describe "GET #download_contexto" do
		context "Caso não exista contexto" do
			it "redireciona para o(a) ppa_ppa criado(a)" do
				ppa = Ppa::Ppa.create! atributos_validos
				get :download_contexto, {id: ppa.to_param}
				expect(response).to redirect_to(Ppa::Ppa.last)
			end
		end
	end

	describe "POST #create" do
		context "com parâmetros válidos" do
			it "cria um(a) novo(a) Ppa::Ppa" do
				expect {
					post :create, params: {ppa_ppa: atributos_validos}
				}.to change(Ppa::Ppa, :count).by(1)
			end

			it "atribui o(a) ppa_ppa recém criado(a) à @ppa_ppa" do
				post :create, params: {ppa_ppa: atributos_validos}
				expect(assigns(:ppa_ppa)).to be_a(Ppa::Ppa)
				expect(assigns(:ppa_ppa)).to be_persisted
			end

			it "redireciona para as configurações do criado(a)" do
				post :create, params: {:ppa_ppa => atributos_validos}
				expect(response).to redirect_to(configuracoes_ppa_ppa_path(Ppa::Ppa.last) )
			end
		end

		context "com parâmetros inválidos" do
			it "atribui um(a) ppa_ppa recém criado(a), mas não salvo(a), à @ppa_ppa" do
				post :create, params: {ppa_ppa: atributos_invalidos}
				expect(assigns(:ppa_ppa)).to be_a_new(Ppa::Ppa)
			end

			it "re-renderiza o template 'new'" do
				post :create, params: {ppa_ppa: atributos_invalidos}
				expect(response).to render_template("new")
			end
		end
	end

	describe "PUT #update" do
		context "com parâmetros válidos" do
			let(:novos_atributos) {
				{ prefeito: 'Nome novo do Prefeito' }
			}

			it "atualiza o(a) ppa_ppa requisitado(a)" do
				ppa = Ppa::Ppa.create! atributos_validos
				post :update, params: {id: ppa.id, ppa_ppa: novos_atributos}
				ppa.reload
				expect( ppa.prefeito ).to eq 'Nome novo do Prefeito'
			end

			it "atribui o(a) ppa_ppa requisitado(a) à @ppa_ppa" do
				ppa = Ppa::Ppa.create! atributos_validos
				post :update, params: {id: ppa.to_param, ppa_ppa: novos_atributos}
				expect(assigns(:ppa_ppa)).to eq(ppa)
			end

			it "atualiza os termos de uso do ppa pedindo confirmação do usuario" do
				ppa = Ppa::Ppa.create! atributos_validos
				post :update, params: {id: ppa.to_param, ppa_ppa: novos_atributos, liberar_temos_de_uso: 'true'}
				expect(assigns(:ppa_ppa)).to eq(ppa)
			end

			it "redireciona para o(a) ppa_ppa" do
				ppa = Ppa::Ppa.create! atributos_validos
				post :update, params: {id: ppa.to_param, ppa_ppa: novos_atributos}
				expect(response).to redirect_to(ppa)
			end
		end

		context "com parâmetros inválidos" do
			it "atribui o(a) ppa_ppa à @ppa_ppa" do
				ppa = Ppa::Ppa.create! atributos_validos
				post :update, params: {id: ppa.to_param, ppa_ppa: atributos_invalidos}
				expect(assigns(:ppa_ppa)).to eq(ppa)
			end

			it "re-renderiza o template 'edit'" do
				ppa = Ppa::Ppa.create! atributos_validos
				post :update, params: {id: ppa.to_param, ppa_ppa: atributos_invalidos}
				expect(response).to render_template("edit")
			end
		end
	end

	describe "DELETE #destroy" do
		it "destrói o(a) ppa_ppa requisitado(a)" do
			ppa = Ppa::Ppa.create! atributos_validos
			expect {
			delete :destroy, params: {:id => ppa.to_param, :senha_administrador => '123123123'}
			}.to change(Ppa::Ppa, :count).by(-1)
		end

		it "redireciona para a lista de ppa_ppas" do
			ppa = Ppa::Ppa.create! atributos_validos
			delete :destroy, params: {:id => ppa.to_param, :senha_administrador => '123123123'}
			expect(response).to redirect_to(ppa_ppas_url)
		end

		it "deletar ppa com eixos criado com a senha de adm" do
			ppa = Ppa::Ppa.create! atributos_validos
			FactoryBot.create(:eixo_sustentavel, :ppa_2010, ppa_id: ppa.id )
			delete :destroy, params: {:id => ppa.to_param, :senha_administrador => '123123123'}
			expect(response).to redirect_to(ppa_ppas_url)
		end

		it "tentar deletar ppa com programas criados usando com a senha de adm" do
			ppa = Ppa::Ppa.find_or_create_by atributos_validos
			orgao = FactoryBot.create(:orgao_secretaria_da_fazenda, :ppa_2010, ppa: ppa)
			FactoryBot.create(:programa_escolar, :ppa_2014, ppa: ppa, orgao: orgao)
			delete :destroy, params: {:id => ppa.to_param, :senha_administrador => '123123123'}
			expect(response).to redirect_to(ppa_ppa_path(ppa.id))
		end

		it "coloca nil no ppa_id caso seja o escolhido" do
			ppa = Ppa::Ppa.create! atributos_validos
			@request.session['contexto_id'] = ppa.id
			delete :destroy, params: {:id => ppa.to_param, :senha_administrador => '123123123'}
			expect(session[:contexto_id]).to eq(nil)
		end
	end

	describe "GET #configuracoes" do
		it "atribui as configurações no ppa na variável @configurações" do
			ppa = FactoryBot.create(:ppa_fortaleza_2014)
			get :configuracoes, id: ppa.id
			expect( assigns(:configuracoes) ).to be_a(RailsSettings::SettingObject)
		end

		it "renderiza a tela de configurações" do
			ppa = FactoryBot.create(:ppa_fortaleza_2014)
			get :configuracoes, id: ppa.id
			expect( response ).to render_template( 'configuracoes' )
		end
	end

	describe "PUT #configura_detalhamento_de_despesas_nas_iniciativas" do
		before(:each) do
			@ppa = FactoryBot.create(:ppa_fortaleza_2014)
		end
		it "configura detalhamento de despesas nas iniciativas" do
			allow( Ppa::Ppa ).to receive(:find).and_return( @ppa )
			expect( @ppa ).to receive( :detalhar_despesas_nas_iniciativas! )
			put :configura_detalhamento_de_despesas_nas_iniciativas, id: @ppa.id
		end

		it "redireciona para a tela de detalhes do PPA" do
			put :configura_detalhamento_de_despesas_nas_iniciativas, id: @ppa.id
			expect( response ).to redirect_to(configuracoes_ppa_ppa_path(@ppa))
		end

		context "quando configura o detalhamento de despesas nas iniciativas com sucesso" do
			it "rediciona para a tela de configurações com a mensagem de sucesso" do
				put :configura_detalhamento_de_despesas_nas_iniciativas, id: @ppa.id
				expect( controller).to set_flash[:notice].to 'Detalhamento de despesas nas iniciativas configurado com sucesso'
			end
		end

		context "quando configura o detalhamento de despesas nas iniciativas com sucesso" do
			cria_tipos_de_despesa
			it "rediciona para a tela de configurações com a mensagem de sucesso" do
				ppa = FactoryBot.create( :ppa_iniciativa_para_ensino_fundamental ).ppa
				put :configura_detalhamento_de_despesas_nas_iniciativas, id: ppa.id
				expect( controller).to set_flash[:alert].to( 'Ops! Esse PPA já tem iniciativas cadastradas' )
			end
		end
	end

	describe "PPA Participativo" do

		describe "GET #ativa_ppa_participativo" do
			it "ativa ppa participativo" do
				ppa = Ppa::Ppa.create! atributos_validos
				put :ativa_ppa_participativo, {id: ppa.to_param}
				ppa.reload
				expect( ppa.ppa_participativo_ativo ).to eq true
			end

			it "redireciona para o(a) ppa_ppa com votação liberada" do
				ppa = Ppa::Ppa.create! atributos_validos
				get :ativa_ppa_participativo, {id: ppa.to_param}
				expect(response).to redirect_to(ppa_ppa_path(ppa, ppa_participativo: true))
			end
		end

		describe "GET #desativa_ppa_participativo" do
			it "desativa liberaçao da votação de propostas" do
				ppa = Ppa::Ppa.create! atributos_validos
				put :desativa_ppa_participativo, {id: ppa.to_param}
				ppa.reload
				expect( ppa.ppa_participativo_ativo ).to eq false
			end
		end

		describe "GET #libera_votacao" do
			it "ativa liberaçao da votação de propostas" do
				ppa = FactoryBot.create( :ppa_fortaleza_2014, ppa_participativo_ativo: true )
				put :libera_votacao, {id: ppa.to_param}
				ppa.reload
				expect( ppa.libera_votacao ).to eq true
			end

			it "redireciona para o(a) ppa_ppa com votação liberada" do
				ppa = FactoryBot.create( :ppa_fortaleza_2014, ppa_participativo_ativo: true )
				put :libera_votacao, {id: ppa.to_param}
				expect(response).to redirect_to(ppa_ppa_path(ppa, ppa_participativo: true))
			end

			context 'quando o período de votação está definido para depois do dia atual' do
				it "define o início de votação para o dia atual" do
					travel_to Date.parse('02/01/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_votacao:  Date.parse('20/01/2017'), fim_do_periodo_de_votacao: Date.parse('30/01/2017'), ppa_participativo_ativo: true)
						ppa.save!(validate: false)

						put :libera_votacao, {id: ppa.to_param}
						ppa.reload
						expect(ppa.abertura_do_periodo_de_votacao).to eq Date.parse('02/01/2017')
						expect(ppa.libera_votacao).to be_truthy
					end
				end
			end

			context 'quando o período de votação já tiver passado' do
				it "retorna erro solicitando novo período" do
					travel_to Date.parse('02/02/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_votacao:  Date.parse('20/01/2017'), fim_do_periodo_de_votacao: Date.parse('30/01/2017'), ppa_participativo_ativo: true)
						ppa.save!(validate: false)
						put :libera_votacao, {id: ppa.to_param}
						ppa.reload
						expect(ppa.libera_votacao).to be_falsey
						alerta = "Não foi possível liberar o período de votação pois o período estabelecido anteriormente já passou. Por favor, configure um novo período na tela de configurações do PPA Participativo."
						expect(controller).to set_flash[:notice].to(alerta)
					end
				end
			end

			context 'quando o período de votação estiver acontecendo' do
				it "não faz nada" do
					travel_to Date.parse('22/01/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_votacao:  Date.parse('20/01/2017'), fim_do_periodo_de_votacao: Date.parse('30/01/2017'), ppa_participativo_ativo: true)
						ppa.save(validate: false)
						put :libera_votacao, {id: ppa.to_param}
						ppa.reload
						expect(ppa.libera_votacao).to be_truthy
					end
				end
			end
		end

		describe "GET #bloqueia_votacao" do
			it "desativa liberaçao da votação de propostas" do
				ppa = Ppa::Ppa.create! atributos_validos
				put :bloqueia_votacao, {id: ppa.to_param}
				ppa.reload
				expect( ppa.libera_votacao ).to eq false
			end

			it "redireciona para o(a) ppa_ppa com votação bloqueada" do
				ppa = Ppa::Ppa.create! atributos_validos
				get :bloqueia_votacao, {id: ppa.to_param}
				expect(response).to redirect_to(ppa_ppa_path(ppa, ppa_participativo: true))
			end

			context 'quando o período de votação já tiver passado' do
				it "libera_votacao permanece falso" do
					travel_to Date.parse('01/02/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_votacao:  Date.parse('01/01/2017'), fim_do_periodo_de_votacao: Date.parse('30/01/2017'))
						ppa.save!(validate: false)
						put :bloqueia_votacao, {id: ppa.to_param}
						ppa.reload
						expect(ppa.libera_votacao).to be_falsey
					end
				end
			end

			context 'quando o período de votação estiver acontecendo' do
				it 'define o fim da votação para o dia atual' do
					travel_to Date.parse('20/01/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_votacao:  Date.parse('01/01/2017'), fim_do_periodo_de_votacao: Date.parse('30/01/2017'), ppa_participativo_ativo: true)
						ppa.save!(validate: false)
						put :bloqueia_votacao, {id: ppa.to_param}
						ppa.reload
						expect(ppa.libera_votacao).to be_falsey
						expect(ppa.fim_do_periodo_de_votacao).to eq Date.parse('19/01/2017')
					end
				end
			end

			context 'ao tentar fechar no primeiro dia de votação' do
				it 'retorna mensagem' do
					travel_to Date.parse('01/01/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_votacao:  Date.parse('01/01/2017'), fim_do_periodo_de_votacao: Date.parse('30/01/2017'), libera_votacao: true, ppa_participativo_ativo: true)
						ppa.save!(validate: false)
						put :bloqueia_votacao, {id: ppa.to_param}
						ppa.reload
						alerta = "Período de votação fechado com sucesso."
						expect(controller).to set_flash[:notice].to(alerta)
					end
				end
			end
		end

		describe "GET #libera_propostas" do
			context "se a data de hoje for antes ou dentro do período de envio de propostas estabelecido" do
				it "ativa liberaçao do envio de propostas" do
					ppa = FactoryBot.create( :ppa_fortaleza_2014, ppa_participativo_ativo: true )
					put :libera_propostas, {id: ppa.to_param}
					ppa.reload
					expect( ppa.libera_propostas ).to eq true
				end

				it "redireciona para o(a) ppa_ppa com envio de propostas liberada" do
					ppa = FactoryBot.create( :ppa_fortaleza_2014, ppa_participativo_ativo: true )
					get :libera_propostas, {id: ppa.to_param}
					expect(response).to redirect_to(ppa_ppa_path(ppa, ppa_participativo: true))
				end
			end

			context 'quando o período de envio de propostas já tiver passado' do
				it "retorna erro solicitando novo período" do
					travel_to Date.parse('02/02/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_propostas:  Date.parse('20/01/2017'), fim_do_periodo_de_propostas: Date.parse('30/01/2017'), ppa_participativo_ativo: true)
						ppa.save!(validate: false)
						put :libera_propostas, {id: ppa.to_param}
						ppa.reload
						expect(ppa.libera_propostas).to be_falsey
						alerta = "Não foi possível liberar o período de envio de propostas pois o período estabelecido anteriormente já passou. Por favor, configure um novo período na tela de configurações do PPA Participativo."
						expect(controller).to set_flash[:notice].to(alerta)
					end
				end
			end

			context 'quando o período de envio de propostas estiver acontecendo' do
				it "não faz nada" do
					travel_to Date.parse('22/01/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_propostas:  Date.parse('20/01/2017'), fim_do_periodo_de_propostas: Date.parse('30/01/2017'), ppa_participativo_ativo: true)
						ppa.save!(validate: false)
						put :libera_propostas, {id: ppa.to_param}
						ppa.reload
						expect(ppa.libera_propostas).to be_truthy
					end
				end
			end
		end

		describe "GET #bloqueia_propostas" do
			it "desativa liberaçao do envio de propostas" do
				ppa = Ppa::Ppa.create! atributos_validos
				put :bloqueia_propostas, {id: ppa.to_param}
				ppa.reload
				expect( ppa.libera_votacao ).to eq false
			end

			it "redireciona para o(a) ppa_ppa com envio de propostas bloqueado" do
				ppa = Ppa::Ppa.create! atributos_validos
				put :bloqueia_propostas, {id: ppa.to_param}
				expect(response).to redirect_to(ppa_ppa_path(ppa, ppa_participativo: true))
			end

			context 'quando o período de envio de propostas já tiver passado' do
				it "libera_propostas permanece falso" do
					travel_to Date.parse('01/02/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_propostas:  Date.parse('01/01/2017'), fim_do_periodo_de_propostas: Date.parse('30/01/2017'))
						ppa.save!(validate: false)
						put :bloqueia_propostas, {id: ppa.to_param}
						ppa.reload
						expect(ppa.libera_propostas).to be_falsey
					end
				end
			end

			context 'quando o período de envio de propostas estiver acontecendo' do
				it 'define o fim do envio de propostas para o dia atual' do
					travel_to Date.parse('20/01/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_propostas:  Date.parse('01/01/2017'), fim_do_periodo_de_propostas: Date.parse('30/01/2017'), ppa_participativo_ativo: true)
						ppa.save!(validate: false)
						put :bloqueia_propostas, {id: ppa.to_param}
						ppa.reload
						expect(ppa.libera_propostas).to be_falsey
						expect(ppa.fim_do_periodo_de_propostas).to eq Date.parse('19/01/2017')
					end
				end
			end

			context 'ao tentar fechar no primeiro dia de envio de propostas' do
				it 'retorna erro' do
					travel_to Date.parse('01/01/2017') do
						ppa = FactoryBot.build( :ppa_fortaleza_2014, abertura_do_periodo_de_propostas:  Date.parse('01/01/2017'), fim_do_periodo_de_propostas: Date.parse('30/01/2017'), libera_propostas: true, ppa_participativo_ativo: true)
						ppa.save!(validate: false)
						put :bloqueia_propostas, {id: ppa.to_param}
						ppa.reload
						expect(ppa.abertura_do_periodo_de_propostas).to eq nil
						expect(ppa.fim_do_periodo_de_propostas).to eq nil
						alerta = "Período de propostas fechado com sucesso."
						expect(controller).to set_flash[:notice].to(alerta)
					end
				end
			end
		end

		describe 'PUT #finalizar_ppa' do
			let(:atributos_finalizacao) {
				{ data_da_legislacao: Date.current, legislacao: "12123" }
			}

			context 'quando o PPA não está consistente' do
				it "redireciona para o PPA atual" do
					ppa = Ppa::Ppa.last
					put :finalizar_ppa, {id: ppa.id, ppa_ppa: atributos_finalizacao}
					expect(response).to redirect_to(ppa)
				end

				it 'nem atualiza os valores' do
					put :finalizar_ppa, {id: @ppa.id, ppa_ppa: atributos_finalizacao}
					@ppa.reload
					expect(@ppa.legislacao).to be_nil
				end

				it "mostra mensagem de erro para o usuário" do
					ppa = Ppa::Ppa.last
					put :finalizar_ppa, {id: ppa.id, ppa_ppa: atributos_finalizacao}
					expect(controller).to set_flash[:alert].to('Existem inconsistências que impedem o PPA de ser fechado')
				end
			end

			context 'quando o PPA está consistente' do
				cria_tipos_de_despesa
				before(:each) do
						@ppa = Ppa::Ppa.last
						projecao = @ppa.projecao_de_receita
						# Criando coisas necessárias para a finalização
						FactoryBot.create :receita_corrente, origem: '0', codigo: '9000000000', projecao_de_receita_id: projecao.id
						receita = FactoryBot.create :receita, projecao_de_receita_id: projecao.id
						receita.calculo_por_exercicios.create(exercicio: 2017, total: 500, tipo: "projetado")
						iniciativa = FactoryBot.create :ppa_iniciativa_para_ensino_fundamental
						programa = iniciativa.objetivo.programa
						programa.projecoes_de_despesa.last.update(valor: 500)
						FactoryBot.create :indicador_escolas_construidas, :ppa_atual
						FactoryBot.create :ppa_quantitativo
				end

				it "redireciona para o PPA atual" do
					put :finalizar_ppa, {id: @ppa.id, ppa_ppa: atributos_finalizacao}
					expect(response).to redirect_to(@ppa)
				end

				it 'atualiza os valores' do
					put :finalizar_ppa, {id: @ppa.id, ppa_ppa: atributos_finalizacao}
					@ppa.reload
					expect(@ppa.legislacao).to eq "12123"
				end

				it "mostra mensagem de sucesso para o usuário" do
					put :finalizar_ppa, {id: @ppa.id, ppa_ppa: atributos_finalizacao}
					expect(controller).to set_flash[:notice].to('Plano Plurianual finalizado com sucesso.')
				end

				context 'mas a data de legislacao está em branco' do
					it "redireciona para o PPA atual" do
						ppa = Ppa::Ppa.last
						put :finalizar_ppa, {id: ppa.id, ppa_ppa: {legislacao: "12123"}}
						expect(response).to redirect_to(ppa)
					end

					it 'nem atualiza os valores' do
						put :finalizar_ppa, {id: @ppa.id, ppa_ppa: {legislacao: "12123"}}
						@ppa.reload
						expect(@ppa.legislacao).to be_nil
					end

					it "mostra mensagem de erro para o usuário" do
						ppa = Ppa::Ppa.last
						put :finalizar_ppa, {id: ppa.id, ppa_ppa: {legislacao: "12123"}}
						expect(controller).to set_flash[:alert].to('Data da Legislação é obrigatória.')
					end
				end
				context 'mas a legislacao está em branco' do
					it "redireciona para o PPA atual" do
						ppa = Ppa::Ppa.last
						put :finalizar_ppa, {id: ppa.id, ppa_ppa: {data_da_legislacao: Date.current}}
						expect(response).to redirect_to(ppa)
					end

					it 'nem atualiza os valores' do
						put :finalizar_ppa, {id: @ppa.id, ppa_ppa: {data_da_legislacao: Date.current}}
						@ppa.reload
						expect(@ppa.legislacao).to be_nil
					end

					it "mostra mensagem de erro para o usuário" do
						ppa = Ppa::Ppa.last
						put :finalizar_ppa, {id: ppa.id, ppa_ppa: {data_da_legislacao: Date.current}}
						expect(controller).to set_flash[:alert].to('Legislação é obrigatória.')
					end
				end
			end
		end
	end
end
