require 'rails_helper'

RSpec.describe Contabilidade::ItemDoEmpenho, type: :model do
	cria_configuracao_default

	it{ is_expected.to belong_to(:empenho).required }
	it{ is_expected.to belong_to(:item).class_name('Base::Item').required }
	it{ is_expected.to delegate_method(:descricao_do_item).to(:item)}
	it{ is_expected.to delegate_method(:codigo_e_descricao).to(:item)}

	[:empenho_id, :item_id, :quantidade, :valor_unitario, :total].each do |atributo|
		before { allow(subject).to receive(:limite_do_total_digitado_pelo_calculo).and_return(true) }
		subject { FactoryBot.build_stubbed(:item_do_empenho_caderno) }
		it{ is_expected.to validate_presence_of(atributo) }
	end

	before(:each) do
		configuracao = Configuracao.last
		configuracao.update(valida_saldo_da_dotacao_no_empenho: true)
	end

	describe 'validar numeriladade e maior que 0' do
		subject { FactoryBot.build_stubbed(:item_do_empenho_caderno) }
		it { is_expected.to validate_numericality_of(:quantidade).is_greater_than(0) }
		it { is_expected.to validate_numericality_of(:valor_unitario).is_greater_than(0) }
		it { is_expected.to validate_numericality_of(:total).is_greater_than(0) }
	end

	describe '#item_do_pedido' do
		context 'se empenho possui licitação' do
			it 'retorna item do pedido correspondente ao item do empenho' do
				empenho = FactoryBot.create :empenho, :derivado_de_licitacao
				item_do_empenho = FactoryBot.create :item_do_empenho_caderno, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id, quantidade: 10, valor_unitario: 1, total: 10
				expect(item_do_empenho.item_do_pedido).to eq(empenho.projeto.pedido.itens_do_pedido.first)
			end
		end
	end

	describe '#item_do_lote' do
		context 'se empenho possui licitação' do
			it 'retorna item do lote correspondente ao item do empenho' do
				empenho = FactoryBot.create :empenho, :derivado_de_licitacao
				item_do_empenho = FactoryBot.create :item_do_empenho_caderno, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id, quantidade: 10, valor_unitario: 1, total: 10
				expect(item_do_empenho.item_do_lote).to eq(empenho.projeto.itens_do_lote.first)
			end
		end
		context 'se o empenho não possui licitação' do
			it 'retorna nil' do
				empenho = FactoryBot.create :empenho
				item_do_empenho = FactoryBot.create :item_do_empenho_caderno, empenho_id: empenho.id, quantidade: 10, valor_unitario: 1, total: 10
				expect(item_do_empenho.item_do_lote).to be_nil
			end
		end
	end

	describe '#item_do_contrato' do
		context 'se o empenho possui contrato' do
			it 'retorna item do contrato correspondente ao item do empenho' do
				projeto = FactoryBot.create(:licitacao_projeto, :dispensa )
				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, projeto_id: projeto.id)
				_lote_do_contrato = FactoryBot.create(:lote_do_contrato, contrato_id: contrato.id, lote_id: projeto.lotes.first.id)
				empenho = FactoryBot.create(:empenho , contrato_id: contrato.id , projeto_id: projeto.id, vincula_processo_contrato: true)
				item_do_empenho = FactoryBot.create :item_do_empenho_caderno, item_id: empenho.contrato.itens_dos_lotes.first.item.id, empenho_id: empenho.id, quantidade: 10, valor_unitario: 1, total: 10
				empenho.reload
				expect(item_do_empenho.item_do_contrato.item_do_lote.item).to eq(empenho.itens_do_empenho.first.item)
			end
		end
		context 'se o empenho não possui contrato' do
			it 'retorna nil' do
				empenho = FactoryBot.create :empenho, :por_contrato
				item_do_empenho = FactoryBot.create :item_do_empenho_caderno, empenho_id: empenho.id, quantidade: 10, valor_unitario: 1, total: 10
				expect(item_do_empenho.item_do_contrato).to be_nil
			end
		end
	end

	describe '#quantidade_disponivel_para_empenho' do
		context 'quando o empenho vem de contrato' do
			it 'retorna o saldo do contrato' do
				projeto = FactoryBot.create(:licitacao_projeto, :dispensa )
				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, projeto_id: projeto.id)
				_lote_do_contrato = FactoryBot.create(:lote_do_contrato, contrato_id: contrato.id, lote_id: projeto.lotes.first.id)
				empenho = FactoryBot.create(:empenho , contrato_id: contrato.id , projeto_id: projeto.id, vincula_processo_contrato: true)
				item_do_empenho = FactoryBot.create :item_do_empenho_caderno, item_id: empenho.contrato.itens_dos_lotes.first.item.id, empenho_id: empenho.id, quantidade: 10, valor_unitario: 1, total: 10
				expect(item_do_empenho.quantidade_disponivel_para_empenho).to eq(10)
			end
		end
		context 'quando o empenho vem de projeto' do
			it 'retorna o saldo do projeto' do
				empenho = FactoryBot.create :empenho, :derivado_de_licitacao
				item_do_empenho = FactoryBot.create :item_do_empenho_caderno, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id
				expect(item_do_empenho.quantidade_disponivel_para_empenho).to eq(10)
			end
		end
		context 'quando o empenho não vem de projeto' do
			it 'retorna 0' do
				empenho = FactoryBot.create :empenho
				item_do_empenho = FactoryBot.create :item_do_empenho_caderno, empenho_id: empenho.id
				expect(item_do_empenho.quantidade_disponivel_para_empenho).to be_nil
			end
		end
		context 'quando o empenho tem um aditivo' do
			it "retorna quantidade do item do aditivo" 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)
			empenho = FactoryBot.create(:empenho, contrato_id: contrato.id,
			vincula_processo_contrato: true,
			projeto_id: contrato.projeto_id,
			aditivo_id: aditivo.id)
			item_do_empenho = FactoryBot.create(:item_do_empenho_caderno, empenho_id: empenho.id,
			item_id: item_do_aditivo.item_do_lote.item_do_pedido.item_id,
			quantidade: 1, total: 9.99)
			expect(item_do_empenho.quantidade_disponivel_para_empenho).to eq 4
			end
		end
		context 'quando o empenho tem um aditivo de prazo sem itens' do
			it "retorna quantidade do item do aditivo" do
			contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato)
			aditivo = FactoryBot.create(:licitacao_aditivo, contrato_id: contrato.id)
			empenho = FactoryBot.create(:empenho, contrato_id: contrato.id,
			vincula_processo_contrato: true, descrimina_itens_processo_ou_contrato: true,
			projeto_id: contrato.projeto_id,
			aditivo_id: aditivo.id)

			item_do_contrato_para_o_empenho = contrato.itens_do_contrato.last
			item_do_empenho = Contabilidade::ItemDoEmpenho.create(empenho_id: empenho.id, item_id: item_do_contrato_para_o_empenho.item_do_lote.item_do_pedido.item.id, quantidade:1)

			expect(item_do_empenho.quantidade_disponivel_para_empenho).to eq 10
			end
		end
	end

	describe "#quantidade_disponivel" do
		it "nada utilizado" do
			item_do_empenho_caderno = FactoryBot.build( :item_do_empenho_caderno, quantidade: 1, valor_unitario: 9.99, total: 9.99)

			expect(item_do_empenho_caderno.quantidade_disponivel).to eq item_do_empenho_caderno.quantidade
		end

		it "utilizado parte dos itens" do
			empenho = FactoryBot.create :empenho, :derivado_de_licitacao
			item_do_empenho = FactoryBot.create :item_do_empenho_caderno, quantidade: 2, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id, valor_unitario: 100 , total:200
			anulacao = FactoryBot.create(:anulacao_do_empenho_total, empenho_id: empenho.id, valor: 9.99, tipo_de_anulacao: :parcial, status:3)
			anulacao_do_item = FactoryBot.create(:anulacao_do_item_do_empenho, item_do_empenho_id: item_do_empenho.id, anulacao_do_empenho_id: anulacao.id, total:100, quantidade:1)

			expect(item_do_empenho.quantidade_disponivel).to eq(item_do_empenho.quantidade - anulacao_do_item.quantidade)
		end

		it "utilizado todos os itens" do
			empenho = FactoryBot.create :empenho, :derivado_de_licitacao
			item_do_empenho = FactoryBot.create :item_do_empenho_caderno, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id
			anulacao = FactoryBot.create(:anulacao_do_empenho_total, empenho_id: empenho.id, valor: 9.99, tipo_de_anulacao: :total, status:3)
			anulacao_do_item = FactoryBot.create(:anulacao_do_item_do_empenho, item_do_empenho_id: item_do_empenho.id, anulacao_do_empenho_id: anulacao.id, total:99.99, quantidade:10)

			expect(item_do_empenho.quantidade_disponivel).to eq(0)
		end
	end

	describe '#total_anulado' do
		it 'retorna o valor correspondente aos itens anulados do empenho' do
			empenho = FactoryBot.create :empenho, :derivado_de_licitacao
			item_do_empenho = FactoryBot.create :item_do_empenho_caderno, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id
			anulacao = FactoryBot.create(:anulacao_do_empenho_total, empenho_id: empenho.id, valor: 9.99, tipo_de_anulacao: :total, status:3)
			anulacao_do_item = FactoryBot.create(:anulacao_do_item_do_empenho, item_do_empenho_id: item_do_empenho.id, anulacao_do_empenho_id: anulacao.id, total:9.99, quantidade:1)
			expect(item_do_empenho.quantidade_anulada).to eq(anulacao_do_item.quantidade)
		end
	end

	describe '#total_disponivel' do
		it 'retorna o valor correspondente aos itens disponível para liquidação' do
			empenho = FactoryBot.create :empenho, :derivado_de_licitacao
			item_do_empenho = FactoryBot.create :item_do_empenho_caderno, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id

			expect(item_do_empenho.total_disponivel.to_f).to eq(99.9)
		end
	end

	describe '#valida_quantidade_do_item' do
		context 'um empenho com contrato' do
			it 'retorna nil' do
				projeto = FactoryBot.create(:licitacao_projeto, :dispensa )
				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, projeto_id: projeto.id)
				_lote_do_contrato = FactoryBot.create(:lote_do_contrato, contrato_id: contrato.id, lote_id: projeto.lotes.first.id)
				empenho = FactoryBot.create(:empenho , contrato_id: contrato.id , projeto_id: projeto.id, vincula_processo_contrato: true)
				item_do_empenho = FactoryBot.build :item_do_empenho_caderno, item_id: empenho.contrato.itens_dos_lotes.first.item.id, empenho_id: empenho.id, quantidade: 10, valor_unitario: 1, total: 10
				item_do_empenho.validate
				expect(item_do_empenho.errors[:quantidade]).to be_empty
			end
		end

		context 'um empenho com licitação' do
			it 'com apenas um empenho pra aquela licitação' do
				empenho = FactoryBot.create :empenho, :derivado_de_licitacao
				item_do_empenho = FactoryBot.build_stubbed :item_do_empenho_caderno, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id
				item_do_empenho.validate
				expect(item_do_empenho.errors[:quantidade]).to be_empty
			end

			it 'retorna error' do
				# projeto = Licitacao::Projeto.find_by(FactoryBot.attributes_for(:licitacao_projeto)) || FactoryBot.create(:licitacao_projeto, :por_item)
				empenho = FactoryBot.create(:empenho_22090001, :derivado_de_licitacao, descrimina_itens_processo_ou_contrato: true) #:projeto_id: projeto.id
				item_do_empenho = FactoryBot.build_stubbed :item_do_empenho_caderno, item_id: empenho.projeto.pedido.itens_do_pedido.first.item_id, empenho_id: empenho.id
				item_do_empenho.quantidade = 999
				item_do_empenho.valid?
				if empenho.aditivo.present?
					origem_empenho = "aditivo"
				elsif empenho.contrato.present?
					origem_empenho ="contrato"
				else
					origem_empenho = "projeto"
				end
				expect(item_do_empenho.errors[:quantidade]).to include("não pode ser maior que a quantidade do item no #{origem_empenho}")
			end
		end
		context 'um empenho sem contrato ou licitação' do
			it 'retorna nil' do
				projeto = FactoryBot.create(:licitacao_projeto, :dispensa )
				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, projeto_id: projeto.id)
				_lote_do_contrato = FactoryBot.create(:lote_do_contrato, contrato_id: contrato.id, lote_id: projeto.lotes.first.id)
				empenho = FactoryBot.create :empenho, descrimina_itens_processo_ou_contrato: false
				item_do_empenho = FactoryBot.build_stubbed :item_do_empenho_caderno, empenho_id: empenho.id , valor_unitario: 20
				item_do_empenho.quantidade = 999
				item_do_empenho.validate
				expect(item_do_empenho.errors[:quantidade]).to be_empty
			end
		end
	end

	describe "#limite_do_total_digitado_pelo_calculo" do
		it "valor dentro do limite" do
			item_do_empenho_caderno = FactoryBot.build( :item_do_empenho_caderno, quantidade: 1, valor_unitario: 9.99, total: 10.09)
			item_do_empenho_caderno.validate

			expect(item_do_empenho_caderno.errors[:total]).not_to include("não pode ser mais que 10 centavos do valor calculado da quantidade x preço unitário")
		end

		it "valor acima do limite" do
			item_do_empenho_caderno = FactoryBot.build( :item_do_empenho_caderno, quantidade: 1, valor_unitario: 9.99, total: 10.1)
			item_do_empenho_caderno.validate

			expect(item_do_empenho_caderno.errors[:total]).to include("não pode ser mais que 10 centavos do valor calculado da quantidade x preço unitário")
		end

		it "valor abaixo do limite" do
			item_do_empenho_caderno = FactoryBot.build( :item_do_empenho_caderno, quantidade: 1, valor_unitario: 9.99, total: 9.88)
			item_do_empenho_caderno.validate

			expect(item_do_empenho_caderno.errors[:total]).to include("não pode ser menos que 10 centavos do valor calculado da quantidade x preço unitário")
		end
	end

end
