require 'rails_helper'

RSpec.describe Licitacao::ItemDoContrato, type: :model do
	it { is_expected.to belong_to(:item_do_lote).required }
	it { is_expected.to belong_to(:contrato).inverse_of(:itens_do_contrato).required }
	it { is_expected.to delegate_method(:item).to(:item_do_lote) }

	it { is_expected.to validate_presence_of(:item_do_lote_id) }

	# context "Quando Item do Contrato persiste" do
	# 	subject { FactoryBot.create :licitacao_item_do_contrato }
	# 	it { is_expected.to validate_uniqueness_of(:item_do_lote_id).scoped_to(:contrato_id) }
	# end

describe '#verifica_se_contrato_e_de_registro_de_preco' do
	context 'se o contrato for registro_de_preco' do
		it 'não retorna erro' do
			projeto = FactoryBot.create(:licitacao_projeto, registro_de_preco: true)
			pessoa_do_projeto = FactoryBot.create(:licitacao_pessoa_do_projeto, projeto_id: projeto.id)
			contratado = FactoryBot.create(:licitacao_contratado, pessoa_do_projeto: pessoa_do_projeto)
			contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, contratado: contratado)
			item = FactoryBot.create(:licitacao_item_do_contrato, quantidade: 2, contrato_id: contrato.id)
			item.update(quantidade: 5)
			expect(item.errors[:quantidade]).to_not include("Itens de um contrato que não é registro de preço não podem ser editados")
		end
	end
end

describe ':verifica_existencia_de_contrato_vigente_com_mesmo_item' do
	before(:each) do
		# allow_any_instance_of( Licitacao::Contrato ).to receive( :valida_data_pelo_exercicio ).and_return(true)
		#allow_any_instance_of( Licitacao::Contrato ).to receive( :valida_data_pela_data_da_ata_de_registro_de_preco ).and_return(true)

		@projeto = FactoryBot.create(:licitacao_projeto, :por_lote, registro_de_preco: true, data_do_projeto: -10.business_day.from_now, data_da_sessao: -10.business_day.from_now)
		@projeto.pedido.orcamento.update_column(:exercicio, Date.today.year)
		item_do_pedido = @projeto.pedido.itens_do_pedido.create(item_id: FactoryBot.create(:caderno).id)
		FactoryBot.create(:item_da_unidade_orcamentaria, quantidade: 10, item_do_pedido_id: item_do_pedido.id)
		@item_do_lote = @projeto.lotes.first.itens_do_lote.create!(item_do_pedido_id: item_do_pedido.id)
		@pessoa_do_projeto = FactoryBot.create(:licitacao_pessoa_do_projeto, projeto_id: @projeto.id)
	end
	# context 'quando existe contrato vigente com mesmo item' do
	# 	it 'retorna erro' do
	# 		contrato_um = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, pessoa_do_projeto_id: @pessoa_do_projeto.id, numero: '00066', data_do_contrato: 1.business_days.after(@projeto.data_do_projeto), inicio_da_vigencia: 2.business_days.after(@projeto.data_do_projeto), fim_da_vigencia: 10.business_days.after(@projeto.data_do_projeto))
	# 		contrato_um.itens_do_contrato.create!(item_do_lote: @item_do_lote, quantidade: 1)
	# 		contrato_dois = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, pessoa_do_projeto_id: @pessoa_do_projeto.id, numero: '00067', data_do_contrato: 1.business_days.after(@projeto.data_do_projeto), inicio_da_vigencia: 2.business_days.after(@projeto.data_do_projeto), fim_da_vigencia: 10.business_days.after(@projeto.data_do_projeto))
	# 		item_do_contrato = contrato_dois.itens_do_contrato.build(item_do_lote: @item_do_lote, quantidade: 1)
	# 		item_do_contrato.save
	# 		item_do_contrato.send(:verifica_existencia_de_contrato_vigente_com_mesmo_item)
	# 		expect(item_do_contrato.errors[:quantidade]).to include "Item já usado em outro contrato vigente"
	# 	end
	# end
	context 'quando não existe contrato vigente com mesmo item' do
		it 'salva' do
			orcamento = FactoryBot.create(:orcamento_2021)
			contrato_um = FactoryBot.build(:licitacao_contrato,:com_lotes_do_contrato, orcamento_id: orcamento, pessoa_do_projeto_id: @pessoa_do_projeto.id, numero: '00068', data_do_contrato: -2.business_days.after(@projeto.data_do_projeto), inicio_da_vigencia: -2.business_days.after(@projeto.data_do_projeto), fim_da_vigencia: -1.business_days.after(@projeto.data_do_projeto))
			contrato_um.save(validate: false)
			contrato_um.itens_do_contrato.create!(item_do_lote: @item_do_lote, quantidade: 1)
			contrato_dois = FactoryBot.build(:licitacao_contrato, :com_lotes_do_contrato, orcamento_id: orcamento, pessoa_do_projeto_id: @pessoa_do_projeto.id, numero: '00069', data_do_contrato: -2.business_days.after(@projeto.data_do_projeto), inicio_da_vigencia: 1.business_days.after(@projeto.data_do_projeto), fim_da_vigencia: 10.business_days.after(@projeto.data_do_projeto))
			contrato_dois.save(validate: false)
			item_do_contrato = contrato_dois.itens_do_contrato.build(item_do_lote: @item_do_lote, quantidade: 1)
			item_do_contrato.save
			item_do_contrato.send(:verifica_existencia_de_contrato_vigente_com_mesmo_item)
			expect(item_do_contrato.persisted?).to be_truthy
		end
	end
end

describe '#valida_quantidade_de_itens' do
	before(:each) do
		projeto = FactoryBot.create(:licitacao_projeto, registro_de_preco: true)
		item_do_pedido = FactoryBot.create(:item_do_pedido, pedido_id: projeto.pedido.id)
		FactoryBot.create(:item_da_unidade_orcamentaria, quantidade: 10, item_do_pedido_id: item_do_pedido.id)
		@item_do_lote = FactoryBot.create(:licitacao_item_do_lote, item_do_pedido_id: item_do_pedido.id)
		@pessoa_do_projeto = FactoryBot.create(:licitacao_pessoa_do_projeto, projeto_id: projeto.id)
		contratado = FactoryBot.create(:licitacao_contratado, pessoa_do_projeto: @pessoa_do_projeto)
		@contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, contratado: contratado)
	end

	context 'item do contrato não estava persistido' do
		it 'não retorna erro' do
			item = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 15, item_do_lote_id: @item_do_lote.id)
			item.save
			expect(item.errors[:quantidade]).to_not include("não pode ser maior que a quantidade de itens do pedido")
		end

		it 'retorna erro' do
			item = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 21, item_do_lote_id: @item_do_lote.id)
			item.save
			expect(item.errors[:quantidade]).to include("não pode ser maior que a quantidade de itens do pedido")
		end
	end

	context 'item do contrato já estava persistido' do
		it 'não retorna erro' do
			item = FactoryBot.create(:licitacao_item_do_contrato, quantidade: 15, item_do_lote_id: @item_do_lote.id, contrato_id: @contrato.id)
			item.reload
			item.quantidade = 5
			item.save
			expect(item.valid?).to be_truthy
		end

		it 'retorna erro' do
			item = FactoryBot.create(:licitacao_item_do_contrato, quantidade: 15, item_do_lote_id: @item_do_lote.id)
			item.reload
			item.quantidade = 21
			item.save

			expect(item.errors[:quantidade]).to include("não pode ser maior que a quantidade de itens do pedido")
		end
	end

	describe '#apaga_a_si_mesmo_se_quantidade_igual_a_zero' do
		it 'quando é zero' do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 0, contrato_id: @contrato.id, item_do_lote_id: @item_do_lote.id)
			item_do_contrato.save
			expect(item_do_contrato.persisted?).to be_falsey
		end

		it 'quando é nulo' do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: nil, contrato_id: @contrato.id, item_do_lote_id: @item_do_lote.id)
			item_do_contrato.save
			expect(item_do_contrato.persisted?).to be_falsey
		end

		it 'quando é maior que zero' do
			item_do_contrato = FactoryBot.create(:licitacao_item_do_contrato, quantidade: 15, item_do_lote_id: @item_do_lote.id)
			item_do_contrato.reload
			item_do_contrato.quantidade = 10
			item_do_contrato.save

			expect(item_do_contrato.persisted?).to be_truthy
		end
	end
end

	context "Quantidade do item do aditivo do empenho" do
		it "quando tem aditivo no empenho" do
			contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato)
			aditivo = FactoryBot.create(:licitacao_aditivo, contrato_id: contrato.id)
			item_do_aditivo = aditivo.itens_do_aditivo.build(aditivo_id: aditivo.id, item_do_lote_id: contrato.itens_do_contrato.last.item_do_lote_id, quantidade: 5)
			item_do_aditivo.save(validate: false)
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, item_do_lote_id: item_do_aditivo.item_do_lote_id, contrato_id: contrato.id)
			item_do_contrato.save(validate: false)
			empenho = FactoryBot.create(:empenho, contrato_id: contrato.id,
			vincula_processo_contrato: true,
			projeto_id: contrato.projeto_id,
			aditivo_id: aditivo.id)
			expect(item_do_contrato.quantidade_do_item_do_aditivo(empenho.id)).to eq 5
		end
		it "quando não tem aditivo no empenho" do
			FactoryBot.create(:configuracao, controlar_empenho_por_vigencia: true)
			contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato)
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, contrato_id: contrato.id)
			item_do_contrato.save(validate: false)
			empenho = FactoryBot.create(:empenho, contrato_id: contrato.id,
			vincula_processo_contrato: true,
			projeto_id: contrato.projeto_id)
			expect(item_do_contrato.quantidade_do_item_do_aditivo(empenho.id)).to eq 0
		end
	end

	context "Itens do empenho sem aditivo" do
		before(:each) do
			FactoryBot.create(:configuracao, controlar_empenho_por_vigencia: true)
		end
		it "Quando empenho não tem aditivo e possui itens" do
			contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato)
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, contrato_id: contrato.id)
			item_do_contrato.save(validate: false)
			empenho = FactoryBot.create(:empenho, contrato_id: contrato.id,
			vincula_processo_contrato: true,
			descrimina_itens_processo_ou_contrato: true,
			projeto_id: contrato.projeto_id)
			empenho.itens_do_empenho.build(item_id: item_do_contrato.item_do_lote.item_do_pedido.item_id, quantidade:1).save(validate: false)
			expect(item_do_contrato.itens_dos_empenho_descriminados_sem_aditivo).to include(empenho.itens_do_empenho.last)
		end
		it "Quando empenho possui aditivo" do
			contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato)
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, contrato_id: contrato.id)
			item_do_contrato.save(validate: false)
			empenho = FactoryBot.build(:empenho, contrato_id: contrato.id,
			vincula_processo_contrato: true,
			descrimina_itens_processo_ou_contrato: true,
			projeto_id: contrato.projeto_id,
			aditivo_id: 1)
			empenho.save(validate: false)
			empenho.itens_do_empenho.build(item_id: item_do_contrato.item_do_lote.item_do_pedido.item_id).save(validate: false)
			expect(item_do_contrato.itens_dos_empenho_descriminados_sem_aditivo).to_not include(empenho.itens_do_empenho.last)
		end
	end

	context "Quantidade total no periodo sem aditivo" do
		it "Quando não possui acrescimo ou redução" do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 10)
			expect(item_do_contrato.quantidade_total_do_periodo_sem_aditivo(Date.today, Date.today)).to eq 10
		end
		it "Quando possui acrescimo ou redução" do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 10)
			aditivo_de_acrescimo = FactoryBot.build(:licitacao_aditivo, contrato_id: item_do_contrato.contrato_id, modalidade: "acrescimo", status: Licitacao::Aditivo.status[:confirmado], data_do_aditivo: Date.today)
			aditivo_de_reducao = FactoryBot.build(:licitacao_aditivo, contrato_id: item_do_contrato.contrato_id, modalidade: "reducao", status: Licitacao::Aditivo.status[:confirmado], data_do_aditivo: Date.today)
			aditivo_de_acrescimo.save(validate: false)
			aditivo_de_reducao.save(validate: false)
			aditivo_de_acrescimo.itens_do_aditivo.build(quantidade: 40, item_do_lote_id: item_do_contrato.item_do_lote_id).save(validate: false)
			aditivo_de_reducao.itens_do_aditivo.build(quantidade: 20, item_do_lote_id: item_do_contrato.item_do_lote_id).save(validate: false)
			item_do_contrato.contrato.reload
			expect(item_do_contrato.quantidade_total_do_periodo_sem_aditivo(Date.today, Date.today + 1.day)).to eq 30
		end
	end

	context "Quantidade a empenhar no periodo sem aditivo" do
		it "Quando empenho tem item" do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 10)

			orcamento_da_despesa = Loa::OrcamentoDaDespesa.last
			sub_elemento = Contabilidade::SubElementoDeDespesa.last

			empenho = item_do_contrato.contrato.empenhos.build(data_do_empenho: Date.today, descrimina_itens_processo_ou_contrato: true, modalidade: 0, pessoa_id: item_do_contrato.contrato.pessoa.id, orcamento_da_despesa_id: orcamento_da_despesa.id, sub_elemento_de_despesa_id: sub_elemento.id)
			empenho.save(validate: false)
			empenho.itens_do_empenho.build(quantidade: 5, item_id: item_do_contrato.item_do_lote.item_do_pedido.item_id).save(validate: false)
			empenho.reload

			expect(item_do_contrato.quantidade_a_empenhar_no_periodo_sem_aditivo(Date.today, Date.today)).to eq 5
		end
		it "Quando empenho não tem item" do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 10)
			
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.last
			sub_elemento = Contabilidade::SubElementoDeDespesa.last

			empenho = item_do_contrato.contrato.empenhos.build(data_do_empenho: Date.today, descrimina_itens_processo_ou_contrato: true, modalidade: 0, pessoa_id: item_do_contrato.contrato.pessoa.id, orcamento_da_despesa_id: orcamento_da_despesa.id, sub_elemento_de_despesa_id: sub_elemento.id)
			empenho.save(validate: false)
			expect(item_do_contrato.quantidade_a_empenhar_no_periodo_sem_aditivo(Date.today, Date.today)).to eq 0
		end
	end

	context "Saldo para empenho sem aditivo" do
		it "Quando não tem valor empenhado" do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 10)
			expect(item_do_contrato.saldo_para_empenho_atual_sem_aditivo(Date.today)).to eq 10
		end
		it "Quando tem valor empenhado" do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 10)
			item_do_contrato.contrato.update_attribute(:inicio_da_vigencia, Date.today)
			item_do_contrato.contrato.update_attribute(:fim_da_vigencia, Date.today + 1.day)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.last
			sub_elemento = Contabilidade::SubElementoDeDespesa.last
			empenho = item_do_contrato.contrato.empenhos.build(data_do_empenho: Date.today, descrimina_itens_processo_ou_contrato: true, modalidade: 0, pessoa_id: item_do_contrato.contrato.pessoa.id, orcamento_da_despesa_id: orcamento_da_despesa.id, sub_elemento_de_despesa_id: sub_elemento.id)
			empenho.save(validate: false)
			empenho.itens_do_empenho.build(quantidade: 5, item_id: item_do_contrato.item_do_lote.item_do_pedido.item_id).save(validate: false)
			empenho.reload
			expect(item_do_contrato.saldo_para_empenho_atual_sem_aditivo(Date.today)).to eq 5
		end
		it "Quando tem empenhos de restos a pagar cancelados" do
			item_do_contrato = FactoryBot.build(:licitacao_item_do_contrato, quantidade: 10)
			item_do_contrato.contrato.update_attribute(:inicio_da_vigencia, Date.today)
			item_do_contrato.contrato.update_attribute(:fim_da_vigencia, Date.today + 1.day)
			orcamento_da_despesa = Loa::OrcamentoDaDespesa.last
			sub_elemento = Contabilidade::SubElementoDeDespesa.last
			empenho1 = item_do_contrato.contrato.empenhos.build(data_do_empenho: Date.today, descrimina_itens_processo_ou_contrato: true, modalidade: 0, pessoa_id: item_do_contrato.contrato.pessoa.id, orcamento_da_despesa_id: orcamento_da_despesa.id, sub_elemento_de_despesa_id: sub_elemento.id)
			empenho1.save(validate: false)
			empenho1.itens_do_empenho.build(quantidade: 5, valor_unitario: 10, item_id: item_do_contrato.item_do_lote.item_do_pedido.item_id).save(validate: false)
			empenho1.reload

			empenho2 = item_do_contrato.contrato.empenhos.build(data_do_empenho: Date.today, descrimina_itens_processo_ou_contrato: true, modalidade: 0, pessoa_id: item_do_contrato.contrato.pessoa.id, orcamento_da_despesa_id: orcamento_da_despesa.id, sub_elemento_de_despesa_id: sub_elemento.id, empenho_origem_id: empenho1.id, restos_a_pagar: true)
			empenho2.save(validate: false)
			empenho2.itens_do_empenho.build(quantidade: 5, valor_unitario: 10, item_id: item_do_contrato.item_do_lote.item_do_pedido.item_id).save(validate: false)
			empenho2.reload

			cancelamento_de_resto_a_pagar = Contabilidade::CancelamentoDeRestoAPagar.new(data: Date.today, orcamento: item_do_contrato.contrato.orcamento, status: 1, tipo: 0)
			cancelamento_de_resto_a_pagar.save(validate: false)

			restos_a_pagar_cancelados = empenho2.restos_a_pagar_cancelados.new(cancelamento_de_resto_a_pagar_id: cancelamento_de_resto_a_pagar.id, valor_cancelado: 50)
			restos_a_pagar_cancelados.save(validate: false)

			expect(item_do_contrato.saldo).to eq 10
		end
	end
end
