require 'rails_helper'


RSpec.describe Licitacao::LancesController, type: :controller do
	sign_in_admin
	cria_configuracao_default
	set_licitacao_na_sessao

	describe "GET #show" do
		it "atribui o lote requisitado a @lote" do
			lote = FactoryBot.create :licitacao_lote
			get :show, params: {lote_id: lote.to_param}
			expect(assigns(:lote)).to eq(lote)
		end

		context 'caso não hajam licitantes no projeto' do
			it 'redireciona para processo e exibe erro' do
				lote = FactoryBot.create :licitacao_lote
				lote.processo.pessoas_do_projeto.destroy_all
				get :show, params: {lote_id: lote.to_param}
				expect(response).to redirect_to(licitacao_processo_path(lote.processo, tab: "lotes"))
				expect(flash[:alert]).to include "Adicione pelo menos um licitante para acessar a tela de lances."
			end
		end

		context 'quando modalidade permite lances (pregao_presencial)' do
			it 'renderiza show' do
				processo = FactoryBot.create :licitacao_processo, :por_lote, modalidade_de_licitacao: :pregao_presencial
				get :show, params: {lote_id: processo.lotes.first.to_param}
				expect(response).to render_template("show")
			end
		end

		context 'quando modalidade não permite lances (convite)' do
			it 'redireciona para o processo' do
				Licitacao::Lote.define_attribute_methods
				allow_any_instance_of(Licitacao::Lote).to receive(:lances_abertos).and_return(false)
				processo = FactoryBot.create :licitacao_processo, :por_item, modalidade_de_licitacao: :convite
				lote = processo.lotes.first
				get :show, params: {lote_id: lote.to_param}
				expect(response).to redirect_to(licitacao_processo_path(processo))
			end
		end
	end

	describe "GET #edit" do
		it "atribui a rodada requisitada à rodada" do
			rodada = FactoryBot.create :licitacao_rodada
			get :edit, params: {lote_id: rodada.lote.id, numero_rodada: rodada.numero	}
			expect(assigns(:rodada)).to eq(rodada)
		end

		context 'caso a rodada esteja concluída' do
			it 'redireciona para o index de lances' do
				rodada = FactoryBot.create :licitacao_rodada
				allow_any_instance_of(Licitacao::Rodada).to receive(:concluida?).and_return(true)
				get :edit, params: { lote_id: rodada.lote.id, numero_rodada: rodada.numero }
				expect(response).to redirect_to(licitacao_mostrar_lances_path(rodada.lote))
				expect(flash[:alert]).to include "Essa rodada não pode ser editada pois está concluída."
			end
		end
	end

	describe "PUT #update" do
		let(:rodada) {
			projeto = FactoryBot.create(:licitacao_projeto, :por_lote)
			lote = projeto.lotes.second
			lote.update_column(:lances_abertos, true)
			lote.rodadas.create
		}

		let(:novos_atributos) {
			{
				lances_attributes: {
						'0': {
							id: rodada.lances.first.id,
							valor: 10.23
						},

						'1': {
							id: rodada.lances.second.id,
							valor: 9.23
						}
				}
			}
		}
		context "com parâmetros válidos" do
			before(:each) do
				allow_any_instance_of( Licitacao::Lance ).to receive( :deve_ser_menor_que_o_menor_valor_da_rodada_anterior ).and_return(true)
				allow_any_instance_of( Licitacao::Rodada ).to receive( :lances_obedecem_ordem_decrescente ).and_return(true)
			end

			it "atualiza os lances da rodada" do
				post :update, params: {lote_id: rodada.lote.id, numero_rodada: rodada.numero, licitacao_rodada: novos_atributos}
				rodada.reload
				expect(rodada.lances.first.valor).to eq 10.23
			end

			it "atribui o lance requisitado à @lance" do
				post :update, params: {lote_id: rodada.lote.id, numero_rodada: rodada.numero, licitacao_rodada: novos_atributos}
				expect(assigns(:rodada)).to eq(rodada)
			end

			it "cria uma nova rodada e redireciona para o form dela" do
				post :update, params: {lote_id: rodada.lote.id, numero_rodada: rodada.numero, licitacao_rodada: novos_atributos, manter_form: true}
				expect(response).to redirect_to(licitacao_editar_lances_path(rodada.lote,rodada.lote.rodadas.last.numero))
			end

			it "redireciona para a lista de rodadas" do
				post :update, params: {lote_id: rodada.lote.id, numero_rodada: rodada.numero, licitacao_rodada: novos_atributos}
				expect(response).to redirect_to( licitacao_mostrar_lances_path(rodada.lote) )
			end
		end

		context "com parâmetros inválidos" do
			let(:atributos_invalidos) {
				{
					lances_attributes: {
							'0': {
								id: rodada.lances.first.id,
								valor: -1
							}
					}
				}
			}
			it "atribui o lance à @lance" do
				post :update, params: {lote_id: rodada.lote.id, numero_rodada: rodada.numero, licitacao_rodada: atributos_invalidos}
				expect(assigns(:rodada)).to eq(rodada)
			end

			it "re-renderiza o template 'edit'" do
				post :update, params: { lote_id: rodada.lote.id, numero_rodada: rodada.numero, licitacao_rodada: atributos_invalidos }
				expect(response).to render_template("edit")
			end
		end
	end

	describe "#verifica_desistencia" do
		let(:rodada) {
			projeto = FactoryBot.create(:licitacao_projeto, :por_lote)
			lote = projeto.lotes.second
			lote.update_column(:lances_abertos, true)
			lote.rodadas.create
		}

		let(:lances_com_desistencia_de_todos) {
			{
				lances_attributes: {
						'0': {
							id: rodada.lances.first.id,
							valor: 10.23,
							desistir: "1"
						},

						'1': {
							id: rodada.lances.second.id,
							valor: 9.23,
							desistir: "1"
						}
				}
			}
		}
		context "quando todos os licitantes desistem na mesma rodada" do
			before(:each) do
				allow_any_instance_of( Licitacao::Lance ).to receive( :deve_ser_menor_que_o_menor_valor_da_rodada_anterior ).and_return(true)
				allow_any_instance_of( Licitacao::Rodada ).to receive( :lances_obedecem_ordem_decrescente ).and_return(true)
			end

			it "retorna erro e redireciona para a tela da rodada atual" do
				post :update, params: {lote_id: rodada.lote.id, numero_rodada: rodada.numero, licitacao_rodada: lances_com_desistencia_de_todos}
				expect(response).to redirect_to(licitacao_editar_lances_path(rodada.lote, rodada.lote.rodadas.last.numero))
				expect(flash[:alert]).to include "Não é possível desistir todos os licitantes na mesma rodada"
			end
		end
	end

end
