require 'rails_helper'

RSpec.describe Licitacao::Aditivo, type: :model do
	it { is_expected.to belong_to(:contratado).class_name('Licitacao::Contratado').inverse_of(:contrato).dependent(:destroy) }
	it { is_expected.to belong_to(:contrato).class_name('Licitacao::Contrato').inverse_of(:aditivos) }
	it { is_expected.to belong_to(:legislacao).class_name('Base::Legislacao') }
	it { is_expected.to belong_to(:unidade_orcamentaria).class_name('Loa::UnidadeOrcamentaria') }
	it { is_expected.to belong_to(:orgao).class_name('Loa::Orgao') }
	it { is_expected.to belong_to(:orcamento).class_name('Orcamento') }
	it { is_expected.to belong_to(:arquivo).class_name('Tcm::Arquivo') }

	it { is_expected.to have_many(:itens_do_aditivo).class_name('Licitacao::ItemDoAditivo').dependent(:destroy) }
	it { is_expected.to have_many(:itens_do_aditivo_de_mudanca).class_name('Licitacao::ItemDoAditivoDeMudanca').dependent(:destroy) }
	it { is_expected.to have_many(:itens_do_lote_do_contrato).through(:contrato) }
	it { is_expected.to have_many(:orcamentos_da_despesa_do_aditivo).class_name('Licitacao::OrcamentoDaDespesaDoAditivo').inverse_of(:aditivo).dependent(:destroy) }
	it { is_expected.to have_many(:orcamentos_da_despesa).through(:orcamentos_da_despesa_do_aditivo) }

	it { is_expected.to delegate_method(:obra).to(:contrato) }

	[:modalidade, :contrato_id, :legislacao_id].each do |atributo|
		it { is_expected.to validate_presence_of atributo }
	end

	[:data_do_aditivo].each do |atributo|
		before { allow(subject).to receive(:confirmado?).and_return(true)}
		it { is_expected.to validate_presence_of atributo }
	end

	[:inicio_da_vigencia, :fim_da_vigencia].each do |atributo|
		before { allow(subject).to receive(:por_prazo?).and_return(true) }
		it { is_expected.to validate_presence_of atributo }
	end

	describe "valida presença do campo objeto" do
		context "quando o contrato do aditivo for de parceria" do
			before { allow(subject).to receive(:parceria?).and_return(true) }
			it { is_expected.to validate_presence_of(:objeto) }
		end
		context "quando o aditivo for de alteração contratual" do
			before { allow(subject).to receive(:alteracao_contratual?).and_return(true) }
			it { is_expected.to validate_presence_of(:objeto) }
		end
		context "quando o aditivo for de mudança de item" do
			before { allow(subject).to receive(:mudanca_de_item?).and_return(true) }
			it { is_expected.to validate_presence_of(:objeto) }
		end
	end

	describe "#valida_data_do_aditivo" do
		before{
			@contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, data_do_contrato: "19/10/2016")
		}
		context "quando a data do aditivo for anterior à data do contrato" do
			it "não permite salvar o aditivo e retorna erro" do
				aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, data_do_aditivo: "18/10/2016")
				aditivo.validate
				expect(aditivo.errors[:data_do_aditivo]).to include("não pode ser anterior à data do contrato (#{@contrato.data_do_contrato})")
			end
		end
		context "quando a data do aditivo for igual à data do contrato" do
			it "permite salvar o aditivo sem erros" do
				aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, data_do_aditivo: "19/10/2016")
				aditivo.validate
				expect(aditivo.errors[:data_do_aditivo]).to be_empty
			end
		end
		context "quando a data do aditivo for posterior à data do contrato" do
			it "permite salvar o aditivo sem erros" do
				aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, data_do_aditivo: "21/10/2016")
				aditivo.validate
				expect(aditivo.errors[:data_do_aditivo]).to be_empty
			end
		end
	end

	describe "#valida_inicio_da_vigencia_do_prazo_com_data_final_do_contrato" do
		context "quando o contrato não possui nenhum aditivo de prazo" do
			before(:each) do
				configuracao = FactoryBot.create(:configuracao, controlar_empenho_por_vigencia: false)
				@contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, fim_da_vigencia: "21/10/2016")
			end
			it "não permite salvar o aditivo e retorna erro se o início da vigência for anterior à data final do contrato" do

				aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "20/10/2016")
				aditivo.validate
				expect(aditivo.errors[:inicio_da_vigencia]).to include("Deve ser um dia posterior ao fim da vigência do contrato principal ou do último aditivo de prazo (#{@contrato.data_final_de_acordo_com_aditivos})")
			end
			it "não permite salvar o aditivo e retorna erro se o início da vigência for igual à data final do contrato" do
				aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "21/10/2016")
				aditivo.validate
				expect(aditivo.errors[:inicio_da_vigencia]).to include("Deve ser um dia posterior ao fim da vigência do contrato principal ou do último aditivo de prazo (#{@contrato.data_final_de_acordo_com_aditivos})")
			end
			it "permite salvar o aditivo sem erros se o início da vigência for posterior à data final do contrato" do
				aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "22/10/2016")
				aditivo.validate
				expect(aditivo.errors[:inicio_da_vigencia]).to be_empty
			end
		end
		context "quando o contrato já possui um aditivo de prazo" do
			before(:each) do
				configuracao = FactoryBot.create(:configuracao, controlar_empenho_por_vigencia: false)
				@contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, fim_da_vigencia: "21/10/2016")
				@ultimo_aditivo_de_prazo = Licitacao::Aditivo.create(FactoryBot.attributes_for(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "23/10/2016", fim_da_vigencia: "22/10/2017", status: :confirmado))
			end
			it "não permite salvar o aditivo e retorna erro se o início da vigência for anterior ao fim da vigência do último aditivo de prazo" do
				aditivo = Licitacao::Aditivo.new(FactoryBot.attributes_for(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "21/10/2017", fim_da_vigencia: "22/10/2018", status: :confirmado))
				aditivo.validate
				expect(aditivo.errors[:inicio_da_vigencia]).to include("Deve ser um dia posterior ao fim da vigência do contrato principal ou do último aditivo de prazo (#{@contrato.data_final_de_acordo_com_aditivos})")
			end
			it "não permite salvar o aditivo e retorna erro se o início da vigência for igual ao fim da vigência do último aditivo de prazo" do
				aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "22/10/2017", fim_da_vigencia: "22/10/2018", status: :confirmado)
				aditivo.validate
				expect(aditivo.errors[:inicio_da_vigencia]).to include("Deve ser um dia posterior ao fim da vigência do contrato principal ou do último aditivo de prazo (#{@contrato.data_final_de_acordo_com_aditivos})")
			end
			it "permite salvar o aditivo sem erros se o início da vigência for posterior ao fim da vigência do último aditivo de prazo" do
				aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "23/10/2017", fim_da_vigencia: "22/10/2018")
				aditivo.validate
				expect(aditivo.errors[:inicio_da_vigencia]).to be_empty
			end
		end
	end

	describe "#valida_fim_da_vigencia_por_prazo" do
		context "quando o fim da vigência for anterior ao início da vigência do prazo" do
			it "não permite salvar o aditivo e retorna erro" do
				aditivo = FactoryBot.build(:licitacao_aditivo, inicio_da_vigencia: "29/11/2016", fim_da_vigencia: "28/11/2016")
				aditivo.validate
				expect(aditivo.errors[:fim_da_vigencia]).to include("deve ser posterior ao início da vigência")
			end
		end
		context "quando o fim da vigência for igual ao início da vigência do prazo" do
			it "permite salvar o aditivo sem erros" do
				aditivo = FactoryBot.build(:licitacao_aditivo, inicio_da_vigencia: "29/11/2016", fim_da_vigencia: "29/11/2016")
				aditivo.validate
				expect(aditivo.errors[:fim_da_vigencia]).to include("deve ser posterior ao início da vigência")
			end
		end
		context "quando o fim da vigência for posterior ao início da vigência do prazo" do
			it "permite salvar o aditivo sem erros" do
				aditivo = FactoryBot.build(:licitacao_aditivo, inicio_da_vigencia: "29/11/2016", fim_da_vigencia: "30/11/2016")
				aditivo.validate
				expect(aditivo.errors[:fim_da_vigencia]).to be_empty
			end
		end
	end

	describe "#gerar_numero" do
		context "quando são criados 3 aditivos em sequência" do
			it "deve ordenar os aditivos sequencialmente" do
				contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato)
				aditivo_um = FactoryBot.create(:licitacao_aditivo, contrato_id: contrato.id, modalidade: "acrescimo")
				aditivo_dois = FactoryBot.create(:licitacao_aditivo, contrato_id: contrato.id, modalidade: "mudanca_de_item")
				aditivo_tres = FactoryBot.create(:licitacao_aditivo, contrato_id: contrato.id, modalidade: "por_prazo")

				expect(aditivo_um.numero).to eq 1
				expect(aditivo_dois.numero).to eq 2
				expect(aditivo_tres.numero).to eq 3
			end
		end
	end

	describe "#reordenar_numero" do
		context "quando já existem 3 aditivos e o do meio é deletado" do
			it "deve reordenar o sequencial do último" do
				contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato)
				aditivo_um = FactoryBot.create(:licitacao_aditivo, contrato_id: contrato.id, modalidade: "acrescimo")
				aditivo_dois = FactoryBot.create(:licitacao_aditivo, contrato_id: contrato.id, modalidade: "mudanca_de_item")
				aditivo_tres = FactoryBot.create(:licitacao_aditivo, contrato_id: contrato.id, modalidade: "por_prazo")

				aditivo_dois.destroy

				aditivo_um.reload
				aditivo_tres.reload
				expect(aditivo_um.numero).to eq 1
				expect(aditivo_tres.numero).to eq 2
			end
		end
	end

	context "Válida Se Existe Aditivo do Mesmo Tipo Aberto" do
		before(:each) do
			@contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, fim_da_vigencia: "21/10/2016")
		end
		it "Quando Existe Aditivo em Aberto" do
			aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 0)
			aditivo.save
			@contrato.reload
			segundo_aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "22/11/2016")
			segundo_aditivo.validate
			expect(segundo_aditivo.errors[:modalidade]).to include("Já existe um aditivo de #{segundo_aditivo.localizar(:modalidade)} pendente de confirmação, é necessário confirmar ou cancelar antes de cadastrar um novo aditivo do mesmo tipo")
		end
		it "Quando Não Existe Aditivo em Aberto" do
			aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 1)
			aditivo.save
			@contrato.reload
			segundo_aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "22/11/2016")
			segundo_aditivo.validate
			expect(segundo_aditivo.errors[:modalidade]).to be_empty
		end
	end

	context "Valor a Empenhar do Aditivo de Prazo" do
		it "Quando Aditivo tem itens, aditivos de reajustes no período, empenhos" do
			@contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, fim_da_vigencia: "21/10/2016")
			Configuracao.new(controlar_empenho_por_vigencia: true).save(validate: false)

			item_do_contrato_a_usar = @contrato.itens_do_contrato.first
			item_do_contrato_a_usar.update_column(:valor, 10)
			
			aditivo = FactoryBot.build(:licitacao_aditivo, contrato_id: @contrato.id, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 0)
			aditivo.save
			aditivo.reload			
			item_do_aditivo = FactoryBot.build(:licitacao_item_do_aditivo, quantidade: 11, aditivo_id: aditivo.id, item_do_lote_id: item_do_contrato_a_usar.id, total: 110)
			item_do_aditivo.save

			aditivo_reajuste = Licitacao::Aditivo.new(contrato_id: @contrato.id, data_do_aditivo: "23/10/2016", modalidade: 3, status: 1)
			aditivo_reajuste.save(validate: false)
			item_do_aditivo_de_reajuste = Licitacao::ItemDoAditivo.new(aditivo_id: aditivo_reajuste.id, item_do_lote_id: item_do_contrato_a_usar.item_do_lote_id, quantidade: 11, valor_adicionado: 0.5, total: 5.5)
			item_do_aditivo_de_reajuste.save(validate: false)
			
			empenho = Contabilidade::Empenho.new(data_do_empenho: "23/10/2016", contrato_id: @contrato.id, aditivo_id: aditivo.id, descriminacao_obrigatoria_de_itens: true, modalidade: 1)
			empenho.save(validate: false)
			item_do_empenho = Contabilidade::ItemDoEmpenho.new(empenho_id: empenho.id, item_id: item_do_contrato_a_usar.item_do_lote.item_do_pedido.item.id, quantidade: 6, valor_unitario: 10.5, total: 63)
			item_do_empenho.save(validate: false)

			expect(aditivo.valor_a_empenhar).to eq 142.4
		end
	end

	describe "#legislacao_obriga_itens" do
		context "Quando obriga" do
			it "Quando é legislacao ARTIGO 57 § 1° INCISO II" do
				aditivo = FactoryBot.create(:licitacao_aditivo, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 1)
				aditivo.legislacao.update_attribute(:tipo_de_artigo, "art57_ii")
				expect(aditivo.legislacao_obriga_itens?).to be_truthy
			end
		end
		context "Quando não obriga" do
			it "Quando não é legislação ARTIGO 57 § 1° INCISO II" do
				aditivo = FactoryBot.create(:licitacao_aditivo, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 1)
				aditivo.legislacao.update_attribute(:tipo_de_artigo, "art24_ii")
				expect(aditivo.legislacao_obriga_itens?).to be_falsey
			end
			it "Quando não tem legislação" do
				aditivo = FactoryBot.create(:licitacao_aditivo, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 1)
				aditivo.update_attribute(:legislacao_id, nil)
				expect(aditivo.reload.legislacao_obriga_itens?).to be_falsey
			end
		end
	end

	describe "#atende_as_exigencias_da_legislacao" do
		context "Quando atende" do
			it "Quando é legislação ARTIGO 57 § 1° INCISO II  e tem itens" do
				aditivo = FactoryBot.create(:licitacao_aditivo, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 1)
				aditivo.legislacao.update_attribute(:tipo_de_artigo, "art57_ii")
				FactoryBot.build(:licitacao_item_do_aditivo, aditivo_id: aditivo.id).save(validate: false)
				expect(aditivo.reload.atende_as_exigencias_da_legislacao?).to be_truthy
			end
			it "Quando não tem legislação" do
				aditivo = FactoryBot.create(:licitacao_aditivo, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 1)
				aditivo.update_attribute(:legislacao_id, nil)
				expect(aditivo.reload.atende_as_exigencias_da_legislacao?).to be_truthy
			end
			it "Quando tem legislação mas não é a ARTIGO 57 § 1° INCISO II" do
				aditivo = FactoryBot.create(:licitacao_aditivo, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 1)
				aditivo.legislacao.update_attribute(:tipo_de_artigo, "art24_ii")
				expect(aditivo.reload.atende_as_exigencias_da_legislacao?).to be_truthy
			end
		end
		context "Quando não atende" do
			it "Quando é legislação ARTIGO 57 § 1° INCISO II e não tem itens" do
				aditivo = FactoryBot.create(:licitacao_aditivo, inicio_da_vigencia: "22/10/2016", fim_da_vigencia: "22/11/2016", status: 1)
				aditivo.legislacao.update_attribute(:tipo_de_artigo, "art57_ii")
				expect(aditivo.reload.atende_as_exigencias_da_legislacao?).to be_falsey
			end
		end
	end
end
