require 'rails_helper'
require 'licitacao_helper'

RSpec.configure do |c|
  c.include LicitacaoHelper
end

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

	describe "GET #listar_itens" do
		it "atribui a lista de lista_de_itens à @itens" do
			projeto = FactoryBot.create :licitacao_projeto
			item_do_lote = FactoryBot.create :licitacao_item_do_lote, lote_id: projeto.lotes.first.id
			allow_any_instance_of(Licitacao::Projeto).to receive(:aberto?).and_return(true)
			get :listar_itens, {projeto_id: projeto.id}
			expect(assigns(:itens)).to include(item_do_lote)
		end

		it "redireciona para @processo se processo não está na fase correta" do
			item_do_lote = FactoryBot.create :licitacao_item_do_lote
			item_do_lote.lote.projeto.update(status: "homologado")
			get :listar_itens, {projeto_id: item_do_lote.lote.projeto.id}
			expect(response).to redirect_to( licitacao_projeto_path(item_do_lote.lote.projeto) )
		end
	end

	describe 'POST #criar_lotes' do
		it 'cria um novo lote caso tenha mais de um item no lote' do
			item_um =  FactoryBot.create :caderno
			item_dois =  FactoryBot.create :caderno, descricao: 'caderno palta dupla'

			projeto = FactoryBot.create :licitacao_projeto

			item_do_pedido_um = FactoryBot.create :item_do_pedido, item_id: item_um.id, pedido_id: projeto.pedido.id
			item_do_pedido_dois = FactoryBot.create :item_do_pedido, item_id: item_dois.id, pedido_id: projeto.pedido.id

			lote = Licitacao::Lote.where(projeto_id: projeto.id).first

			item_do_lote_um = FactoryBot.create :licitacao_item_do_lote, lote_id: lote.id, item_do_pedido_id: item_do_pedido_um.id
			FactoryBot.create :licitacao_item_do_lote, lote_id: lote.id, item_do_pedido_id: item_do_pedido_dois.id

			post :criar_lotes, {projeto_id: projeto.id, itens: [item_do_lote_um.id]}
			expect(projeto.lotes.count).to be 1
		end
	end

	describe "GET #confirmar_anulacao_item" do
		context 'quando o projeto está aberto' do
			it "atribui o(a) pedido requisitado à @pedido" do
				item_do_lote = FactoryBot.create :licitacao_item_do_lote
				lote = item_do_lote.lote
				get :confirmar_anulacao_item, { lote_id: lote.id, id: item_do_lote.id }
				expect(assigns(:item_do_lote)).to eq(item_do_lote)
			end
		end

		context 'quando o projeto não está aberto' do
			it 'redireciona para @projeto' do
				projeto = FactoryBot.create :licitacao_projeto, :por_lote, status: :em_sessao
				lote = FactoryBot.create :licitacao_lote, projeto_id: projeto.id
				item_do_lote = FactoryBot.create :licitacao_item_do_lote, lote_id: lote
				get :confirmar_anulacao_item, { lote_id: lote.id, id: item_do_lote.id }
				expect(response).to redirect_to licitacao_projeto_path(projeto)
			end
		end
	end

	describe "PATCH #update" do
		before(:each) do
			@lote = FactoryBot.create :licitacao_lote, lances_abertos: false
			allow_any_instance_of(Licitacao::Projeto).to receive(:status).and_return(:aberto)
		end
		context "com parâmetros válidos" do
			let(:licitacao_criterio) {
				{criterio_de_julgamento: "maior_desconto"}
			}

			it "atualiza e configura o lote" do
				patch :update, {id: @lote.id, licitacao_lote: licitacao_criterio}
				@lote.reload
				expect(@lote.criterio_de_julgamento).to eq "maior_desconto"
			end
		end
	end

	describe "PATCH #anular_item" do
		before(:each) do
			@item_do_lote = FactoryBot.create :licitacao_item_do_lote
			allow_any_instance_of(Licitacao::Projeto).to receive(:status).and_return(:aberto)
		end
		context "com parâmetros válidos" do
			let(:atributos_anulacao) {
				{motivo_da_anulacao: "motivo convincente"}
			}

			it "atualiza o item do lote requisitado" do
				patch :anular_item, {id: @item_do_lote.id, lote_id: @item_do_lote.lote.id, licitacao_item_do_lote: atributos_anulacao}
				@item_do_lote.reload
				expect(@item_do_lote.motivo_da_anulacao).to eq "motivo convincente"
			end

			it "muda status do item do lote para 'anulado'" do
				patch :anular_item, {id: @item_do_lote.to_param, lote_id: @item_do_lote.lote.id, licitacao_item_do_lote: atributos_anulacao}
				@item_do_lote.reload
				expect(@item_do_lote.anulado?).to be_truthy
			end

			it "muda status do item_por_pessoa do lote para 'anulado'" do
				item_por_pessoa1 =  FactoryBot.create(:item_do_projeto_por_pessoa, item_do_lote_id: @item_do_lote.id)
				item_por_pessoa2 =  FactoryBot.create(:item_do_projeto_por_pessoa, item_do_lote_id: @item_do_lote.id)
				patch :anular_item, {id: @item_do_lote.to_param, lote_id: @item_do_lote.lote.id, licitacao_item_do_lote: atributos_anulacao}
				@item_do_lote.reload
				item_por_pessoa1.reload
				item_por_pessoa2.reload
				expect(item_por_pessoa1.valido?).to be_falsey
				expect(item_por_pessoa2.valido?).to be_falsey
			end

			it "redireciona para o item do lote" do
				patch :anular_item, {id: @item_do_lote.to_param, lote_id: @item_do_lote.lote.id, licitacao_item_do_lote: atributos_anulacao}
				expect(response).to redirect_to licitacao_projeto_path(@item_do_lote.lote.projeto, tab: "lotes")
			end
		end

		context "com parâmetros inválidos" do
			let(:atributos_anulacao_invalidos) {
				{motivo_da_anulacao: ""}
			}
			it "atribui o item do lote à @item_do_lote" do
				put :anular_item, {id: @item_do_lote.to_param, lote_id: @item_do_lote.lote.id, licitacao_item_do_lote: atributos_anulacao_invalidos}
				expect(assigns(:item_do_lote)).to eq(@item_do_lote)
			end

			it "re-renderiza o template 'confirmar_anulacao'" do
				put :anular_item, {id: @item_do_lote.to_param, lote_id: @item_do_lote.lote.id, licitacao_item_do_lote: atributos_anulacao_invalidos}
				expect(response).to render_template("confirmar_anulacao_item")
			end
		end
	end

	describe 'PATCH #alternar_cadastro_de_lances' do
		let(:processo) {
			FactoryBot.create :licitacao_processo, :por_lote
		}
		let(:processo_por_item) {
			FactoryBot.create :licitacao_processo, forma_de_agrupamento: :por_item
		}
		context 'quando o lote está com cadastro de lances fechado' do
			context 'e o projeto é válido (pregao_presencial)' do
				let(:processo) { FactoryBot.create :licitacao_projeto, modalidade_de_licitacao: "pregao_presencial", forma_de_agrupamento: :por_lote, status: :em_sessao }
				it 'abre cadastro de lances' do
					lote = FactoryBot.create :licitacao_lote, :completo, lances_abertos: false, projeto_id: processo.id
					cria_pessoas_do_projeto_e_propostas
					patch :alternar_cadastro_de_lances, {lote_id: lote.id}
					expect(response).to redirect_to licitacao_mostrar_lances_path(lote)
					expect(lote.reload.lances_abertos).to be_truthy
				end
			end
			context 'e o projeto não é válido (convite)' do
				it 'retorna erro e mantem fechado' do
					lote = FactoryBot.create :licitacao_lote, lances_abertos: false, projeto_id: processo_por_item.id
					lote.projeto.convite!
					cria_pessoas_do_projeto_e_propostas
					patch :alternar_cadastro_de_lances, {lote_id: lote.id}
					expect(response).to redirect_to licitacao_mostrar_lances_path(lote)
					expect(flash[:alert]).to include "A validação falhou: Lances abertos não pode ser verdadeiro caso modalidade de licitação seja convite"
					expect(lote.reload.lances_abertos).to be_falsey
				end
			end
		end
		context 'quando o lote está com cadastro de lances aberto' do
			it 'fecha cadastro de lances' do
				lote = FactoryBot.create :licitacao_lote, :completo, lances_abertos: false
				cria_pessoas_do_projeto_e_propostas
				#abre o lance
				patch :alternar_cadastro_de_lances, {lote_id: lote.id}

				#cria rodada final com lance final
				ultima_rodada = lote.rodadas.create
				ultima_rodada.save(validate: false)
				ultima_rodada.lances.update_all(valor: 10)

				ultima_rodada.lances.first.delete
				ultima_rodada.update_column(:desempate, true)

				#fecha o lance
				patch :alternar_cadastro_de_lances, {lote_id: lote.id}
				expect(response).to redirect_to licitacao_mostrar_lances_path(lote)
				#expect(flash[:success]).to include "Cadastro de lances fechado com sucesso!"
				expect(lote.reload.lances_abertos).to be_falsey
			end
		end
	end

	describe '#lotes_por_ganhador' do
		context 'quando o formato é JS' do
			it 'retorna um JS' do
				xhr :get, :lotes_por_ganhador, ganhador_id: 2, format: :js
				expect(response.status).to eq 200
				expect(response.headers["Content-Type"]).to eq "text/javascript; charset=utf-8"
			end
		end
	end

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

		context 'quando o lote não possui licitantes' do
			it 'redireciona para processo e exibe erro' do
				lote = FactoryBot.create :licitacao_lote
				lote.processo.pessoas_do_projeto.destroy_all
				get :define_ganhador, {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 definir o ganhador"
			end
		end
	end

	describe 'PATCH #salvar_ganhador' do
		let(:processo) {
			FactoryBot.create :licitacao_processo, :por_lote, status: "em_sessao"
		}
		let(:lote){
			lote = processo.lotes.first
			lote.tecnica_e_preco!
			lote
		}

		context 'com parâmetros inválidos' do
			let(:ganhador_params) {
				{ ganhador_id: "", justificativa: "" }
			}
			it 'retorna mensagem de erro' do
				patch :salvar_ganhador, {lote_id: lote.id, licitacao_lote: ganhador_params}
				lote.validate
				expect(lote.errors[:ganhador_id]).to include "não pode ficar em branco"
				expect(lote.errors[:justificativa]).to include "não pode ficar em branco"
			end
		end

		context 'com parâmetros válidos' do
			let(:ganhador) {
				lote.pessoas_do_projeto_do_lote.first.pessoa_do_projeto
			}
			let(:ganhador_params) {
				{	ganhador_id: ganhador.id,
					justificativa: "Justificativa para o ganhador"
				}
			}
			it 'salva o ganhador e redireciona para o @processo' do
				expect(lote.ganhador).to be_nil
				patch :salvar_ganhador, {lote_id: lote.id, licitacao_lote: ganhador_params}
				expect(response).to redirect_to(licitacao_processo_path(lote.processo, tab: "lotes"))
				lote.reload
				expect(lote.ganhador).to eq (ganhador)
			end
		end
	end

	describe 'PATCH #salvar_ganhador_menor_preco' do
		let(:processo) {
			FactoryBot.create :licitacao_processo, :tomada_de_precos, status: "em_sessao"
		}

		it "salva o ganhador e redireciona para @processo com mensagem de sucesso" do
			"pending"
		end

		it "não salva o ganhador e redireciona para @processo com mensagem de erro" do
			"pending"
		end

	end

	describe 'PATCH #desertar_lote' do
		let(:processo) {
			FactoryBot.create :licitacao_processo, :por_lote, status: "em_sessao"
		}

		it "deserta o lote e redireciona para o @processo com mensagem de sucesso" do
			lote = processo.lotes.first
			patch :desertar_lote, {lote_id: lote.id}
			expect(response).to redirect_to(licitacao_processo_path(lote.processo, tab: "lotes"))
			expect(flash[:notice]).to include "Lote foi desertado com sucesso"
		end

		it "não deserta e redireciona para o @processo com mensagem de erro" do
			lote = processo.lotes.first
			allow_any_instance_of(Licitacao::Lote).to receive(:deserto!).and_return(false)
			patch :desertar_lote, {lote_id: lote.id}
			expect(response).to redirect_to(licitacao_processo_path(lote.processo, tab: "lotes"))
			expect(flash[:alert]).to include "Não foi possível desertar o lote"
		end
	end

  describe 'PATCH #fracassar_lote' do
		let(:processo) {
			FactoryBot.create :licitacao_processo, :por_lote, status: "em_sessao"
		}

		it "fracassa o lote e redireciona para o @processo com mensagem de sucesso" do
			lote = processo.lotes.first
			patch :fracassar_lote, {lote_id: lote.id}
			expect(response).to redirect_to(licitacao_processo_path(lote.processo, tab: "lotes"))
			expect(flash[:notice]).to include "Lote foi fracassado com sucesso"
		end
  end

	describe 'PATCH #excluir_rodada_de_lances' do

    let(:processo) {
			FactoryBot.create :licitacao_processo, :por_lote
		}

		it "exclui rodada de lances e redireciona com mensagem de sucesso" do
      lote = FactoryBot.create :licitacao_lote, :completo, lances_abertos: true, projeto_id: processo.id
      cria_pessoas_do_projeto_e_propostas

      rodada_zero = lote.rodadas.build(numero: 0)
      rodada_zero.save(validate: false)
      rodada = lote.rodadas.build(numero: 1)
      rodada.save(validate: false)

      patch :excluir_rodada_de_lances, {lote_id: lote.id}
      expect(response).to redirect_to licitacao_mostrar_lances_path(lote)
		end
	end

end
