require 'rails_helper'

RSpec.describe Projecao::CalculoDeProjecoesController, type: :controller do
	sign_in_admin
	set_ppa_id_na_sessao

	let(:atributos_validos) {
		FactoryBot.attributes_for( :calculo_de_projecao_para_2017 )
	}

	let(:atributos_invalidos) {
		{exercicio_destino: 9999}
	}

	let(:projecao_id) {
		ppa = Ppa::Ppa.first
		ppa.projecao_de_receita.id
	}

	describe '#disponibiliza_dependencias' do
		context 'quando a projeção é de ppa' do
			before(:each) do
				ppa = Ppa::Ppa.last
				@projecao = ppa.projecao_de_receita
				@projecao.update(receitas_importadas: true)

			end
			it 'atribui todos os anos da projeção em exercicios_base' do
				get :new
				expect(assigns(:exercicios_base)).to eq(@projecao.exercicios)
			end
			it 'atribui os anos de projeção em exercicios_destino' do
				get :new
				expect(assigns(:exercicios_destino)).to eq(@projecao.exercicios_destino)
			end
		end
		context 'quando a projeção é de orçamento' do
			set_orcamento_na_sessao
			before(:each) do
				orcamento = Orcamento.last
				@projecao = orcamento.projecao_de_receita
			end
			it 'atribui os anos de projeção em exercicios_base' do
				get :new
				expect(assigns(:exercicios_base)).to eq(@projecao.exercicios_destino)
			end
			it 'atribui os anos de projeção menos o primeiro em exercicios_destino' do
				get :new
				expect(assigns(:exercicios_destino)).to eq(@projecao.exercicios_destino.drop(1))
			end
		end
	end

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

	describe "GET #new" do
		it "atribui um(a) novo(a) calculo_de_projecao à @calculo_de_projecao" do
			Ppa::Ppa.first.projecao_de_receita.update(receitas_importadas: true)
			get :new
			expect(assigns(:calculo_de_projecao)).to be_a_new(Projecao::CalculoDeProjecao)
		end
	end

	describe "GET #edit" do
		context 'quando não há receitas calculadas' do
			it "atribui o(a) calculo_de_projecao requisitado à @calculo_de_projecao" do
				calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
				get :edit, params: { id: calculo_de_projecao.to_param }

				expect(assigns(:calculo_de_projecao)).to eq(calculo_de_projecao)
			end
		end

		context 'quando há receitas calculadas' do
			it 'retorna para o show e mostra mensagem de alerta' do
				calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
				calculo_de_projecao.projecao_de_receita.update(receitas_importadas: true)

				receita_do_calculo = FactoryBot.build :projecao_receita_do_calculo_de_projecao, calculo_de_projecao_id: calculo_de_projecao.id
				receita_do_calculo.save
				get :edit, params: { id: calculo_de_projecao.to_param }

				expect(response).to redirect_to(calculo_de_projecao)
				expect(flash[:alert]).to eq 'Já existem receitas calculadas com o exercício base e exercício destino, então não é mais possível editar o cálculo de projeção.'
			end
		end
	end

	describe "POST #create" do
		before :each do
			Ppa::Ppa.first.projecao_de_receita.update(receitas_importadas: true)
		end

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

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

			it "redireciona para o(a) calculo_de_projecao criado(a)" do
				post :create, params: {:projecao_calculo_de_projecao => atributos_validos}
				expect(response).to redirect_to(Projecao::CalculoDeProjecao.last)
			end
		end

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

			it "re-renderiza o template 'new'" do
				post :create, params: { projecao_calculo_de_projecao: 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) {
				{
					exercicio_base: 2016,
					exercicio_destino: 2018
				}
			}

			it "atualiza o(a) calculo_de_projecao requisitado(a)" do
				calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
				calculo_de_projecao.projecao_de_receita.update(receitas_importadas: true)
				post :update, params: {id: calculo_de_projecao.to_param, projecao_calculo_de_projecao: novos_atributos}
				calculo_de_projecao.reload
				expect(calculo_de_projecao.exercicio_destino).to eq(2018)
			end

			it "atribui o(a) calculo_de_projecao requisitado(a) à @calculo_de_projecao" do
				calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
				calculo_de_projecao.projecao_de_receita.update(receitas_importadas: true)
				post :update, params: {id: calculo_de_projecao.to_param, projecao_calculo_de_projecao: atributos_validos}
				expect(assigns(:calculo_de_projecao)).to eq(calculo_de_projecao)
			end

			it "redireciona para o(a) calculo_de_projecao" do
				calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
				calculo_de_projecao.projecao_de_receita.update(receitas_importadas: true)
				post :update, params: {id: calculo_de_projecao.id, projecao_calculo_de_projecao: atributos_validos}
				expect(response).to redirect_to(calculo_de_projecao)
			end
		end

		context "com parâmetros inválidos" do
			it "atribui o(a) calculo_de_projecao à @calculo_de_projecao" do
				calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
				calculo_de_projecao.projecao_de_receita.update(receitas_importadas: true)
				post :update, params: {id: calculo_de_projecao.to_param, projecao_calculo_de_projecao: atributos_invalidos}
				expect(assigns(:calculo_de_projecao)).to eq(calculo_de_projecao)
			end

			it "re-renderiza o template 'edit'" do
				calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
				calculo_de_projecao.projecao_de_receita.update(receitas_importadas: true)
				post :update, params: {id: calculo_de_projecao.to_param, projecao_calculo_de_projecao: atributos_invalidos}
				expect(response).to render_template("edit")
			end
		end
	end

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

		it "redireciona para a lista de calculo_de_projecoes" do
			calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
			delete :destroy, params: {:id => calculo_de_projecao.to_param}
			calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
			expect(response).to redirect_to(projecao_projecao_de_receita_path(anchor: "tab_calculo"))
		end
	end

	describe 'DELETE #remover_receitas_do_calculo' do
		before do
			request.env['HTTP_REFERER'] = root_url
		end

		it 'remove todas as receitas selecionadas para o cálculo' do
			calculo_de_projecao = Projecao::CalculoDeProjecao.create! atributos_validos
			delete :remover_receitas_do_calculo, id: calculo_de_projecao.id
			expect(calculo_de_projecao.receitas_dos_calculos_de_projecao.count).to eq(0)
		end
	end
end
