require 'rails_helper'

RSpec.describe Licitacao::OrdemDeCompra, type: :model do
	it { is_expected.to belong_to(:orcamento).class_name('Orcamento') }
	it { is_expected.to belong_to(:empenho).class_name('Contabilidade::Empenho') }

	it { is_expected.to delegate_method(:unidade_orcamentaria).to(:empenho) }

	it { is_expected.to have_many(:itens_da_ordem_de_compra) }
	it { is_expected.to have_many(:ocorrencias_da_ordem_de_compra).class_name('Licitacao::OcorrenciaDaOrdemDeCompra')}

	[:data_da_solicitacao, :empenho_id].each do |atributo|
		it { is_expected.to validate_presence_of atributo }
	end

	let(:projeto) {
		FactoryBot.create(:licitacao_projeto)
	}

	let(:item_do_pedido) {
		FactoryBot.create(:item_do_pedido, pedido_id: projeto.pedido.id)
	}

	let(:item_da_unidade_orcamentaria) {
		FactoryBot.create(:item_da_unidade_orcamentaria, quantidade: 10, item_do_pedido_id: item_do_pedido.id)
	}

	let(:item_do_lote) {
		item_da_unidade_orcamentaria
		FactoryBot.create(:licitacao_item_do_lote, item_do_pedido_id: item_do_pedido.id)
	}

	let(:ordem_de_compra_por_processo) {
		item_do_lote
		pessoa_do_projeto = item_do_lote.lote.projeto.pessoas_do_projeto.first
		@ordem_de_compra = FactoryBot.create(:licitacao_ordem_de_compra, contratado_id: pessoa_do_projeto.id, unidade_orcamentaria_id: item_da_unidade_orcamentaria.unidade_orcamentaria_por_pedido.unidade_orcamentaria.id)
		@ordem_de_compra
	}

	let(:ordem_de_compra_por_contrato) {
		pessoa_do_projeto = item_do_lote.lote.projeto.pessoas_do_projeto.first
		@contrato = FactoryBot.create(:licitacao_contrato, :com_lotes_do_contrato, numero: '112233', contratado_id: pessoa_do_projeto.id)
		@item_do_contrato = FactoryBot.create(:licitacao_item_do_contrato, quantidade: 15, contrato_id: @contrato.id, item_do_lote_id: item_do_lote.id)
		@ordem_de_compra = FactoryBot.create(:licitacao_ordem_de_compra)
		@ordem_de_compra
	}

	describe ':motivo_do_cancelamento' do
		context 'com ordem de compra cancelada' do
			subject {
				FactoryBot.build :licitacao_ordem_de_compra, status: :cancelado
			}

			it{ is_expected.to validate_presence_of :motivo_do_cancelamento }
		end
	end

	describe '#data_da_ordem_deve_ser_maior_ou_igual_a_data_do_empenho' do
		context 'quando a data da ordem de compra é anterior à data do empenho' do
			it 'retorna erro' do
				empenho = FactoryBot.create(:empenho_22090001, data_de_solicitacao: '30/11/2016'.to_date)
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, data_da_solicitacao: "28/11/2016".to_date, empenho: empenho)
				ordem_de_compra.save
				expect( ordem_de_compra.errors[:data_da_solicitacao] ).to include "não pode ser anterior à data do empenho: #{empenho.data_de_solicitacao}"
			end
		end
		context 'quando a data da ordem de compra é igual ou posterior à data do empenho' do
			it 'não retorna erro' do
				empenho = FactoryBot.create(:empenho_22090001, data_de_solicitacao: '30/11/2016'.to_date)
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, data_da_solicitacao: "01/12/2016".to_date, empenho: empenho)
				ordem_de_compra.validate

				expect( ordem_de_compra.errors[:data_da_solicitacao] ).to_not include "não pode ser anterior à data do empenho: #{empenho.data_de_solicitacao}"
			end
		end
		context 'quando a data da ordem de compra é igual à data do empenho' do
			it 'não retorna erro' do
				empenho = FactoryBot.create(:empenho_22090001, data_de_solicitacao: '30/11/2016'.to_date)
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, data_da_solicitacao: "30/11/2016".to_date, empenho: empenho)
				ordem_de_compra.validate

				expect( ordem_de_compra.errors[:data_da_solicitacao] ).to_not include "não pode ser anterior à data do empenho: #{empenho.data_de_solicitacao}"
			end
		end
	end

	describe '#valor_total' do
	end

	describe '#valida_delecao' do
		context 'quando ordem de compra não tem itens' do
			it 'permite deleção' do
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, data_da_solicitacao: "30/11/2017".to_date)
				ordem_de_compra.save(validate: false)
				expect { ordem_de_compra.destroy }.to change(Licitacao::OrdemDeCompra, :count).by(-1)
			end
		end
		context 'quando ordem de compra tem itens' do
			it 'não permite deleção' do
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, data_da_solicitacao: "30/11/2017".to_date)
				ordem_de_compra.save(validate: false)
				item_da_ordem = ordem_de_compra.itens_da_ordem_de_compra.new(quantidade: 1)
				item_da_ordem.save(validate: false)
				expect { ordem_de_compra.valida_delecao }.to raise_error('Não é possivel deletar ordens de fornecimento com itens ou canceladas')
			end
		end
		context 'quando ordem de compra está cancelada' do
			it 'não permite deleção' do
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, :cancelada)
				ordem_de_compra.save(validate: false)
				expect { ordem_de_compra.destroy }.to raise_error('Não é possivel deletar ordens de fornecimento com itens ou canceladas')
			end
		end
	end

	context 'empenho_esta_confirmado?' do
		it 'não permite salvar' do
			empenho = FactoryBot.create(:empenho_22090001, status: 'solicitado')
			ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, :cancelada, empenho_id: empenho.id)
			ordem_de_compra.save
			expect( ordem_de_compra.errors[:numero] ).to_not include "Empenho não está confirmado."
		end
	end


	context 'atribui_numero' do
		it 'primeira ordem do dia' do
			ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, data_da_solicitacao: "30/11/2017".to_date)
			ordem_de_compra.validate

			expect(ordem_de_compra.numero).to eq "30110001"
		end

		it 'segunda ordem do dia' do
			primeira_ordem = FactoryBot.build(:licitacao_ordem_de_compra, data_da_solicitacao: "30/11/2017".to_date)
			primeira_ordem.validate
			primeira_ordem.save(validate: false)
			ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, data_da_solicitacao: "30/11/2017".to_date)
			ordem_de_compra.validate

			expect(ordem_de_compra.numero).to eq "30110002"
		end
	end

	context 'quantidade restante da ordem apos recebimento' do
		it 'Quando o recebimento é parcial' do
			ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra)
			ordem_de_compra.save(validate: false)
			item = FactoryBot.create(:caderno)
			item_da_ordem = ordem_de_compra.itens_da_ordem_de_compra.build(quantidade: 10, item_id: item.id)
			item_da_ordem.save(validate: false)
			unidade_orcamentaria = Loa::UnidadeOrcamentaria.last
			agente_publico = FactoryBot.create(:agente_publico)
			almoxarifado = FactoryBot.build(:gestao_de_estoque_almoxarifado)
			almoxarifado.unidades_orcamentarias_do_almoxarifado.build(unidade_orcamentaria_id: unidade_orcamentaria.id)
			almoxarifado.responsaveis_dos_almoxarifados.build(agente_publico_municipal_id: agente_publico.id, data_de_entrada: "2021-10-01", data_de_saida: "2021-30-01")
			almoxarifado.save
			almoxarifado.reload
			recebimento_de_material = FactoryBot.create(:gestao_de_estoque_recebimento_de_material, ordem_de_compra_id: ordem_de_compra.id, almoxarifado_id: almoxarifado.id, data_de_emissao: '2016-15-11')
			item_do_recebimento = FactoryBot.create(:gestao_de_estoque_itens_do_recebimento_de_material, recebimento_de_material_id: recebimento_de_material.id, item_id: item_da_ordem.item_id, quantidade: 5)
			recebimento_de_material.update_attribute(:status, "recebido")
			expect(ordem_de_compra.quantidade_a_receber).to eq 5
		end

		it 'Quando o recebimento é total' do
			ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra)
			ordem_de_compra.save(validate: false)
			item = FactoryBot.create(:caderno)
			item_da_ordem = ordem_de_compra.itens_da_ordem_de_compra.build(quantidade: 10, item_id: item.id)
			item_da_ordem.save(validate: false)
			unidade_orcamentaria = Loa::UnidadeOrcamentaria.last
			agente_publico = FactoryBot.create(:agente_publico)
			almoxarifado = FactoryBot.build(:gestao_de_estoque_almoxarifado)
			almoxarifado.unidades_orcamentarias_do_almoxarifado.build(unidade_orcamentaria_id: unidade_orcamentaria.id)
			almoxarifado.responsaveis_dos_almoxarifados.build(agente_publico_municipal_id: agente_publico.id, data_de_entrada: "2021-10-01", data_de_saida: "2021-30-01")
			almoxarifado.save
			almoxarifado.reload
			recebimento_de_material = FactoryBot.create(:gestao_de_estoque_recebimento_de_material, ordem_de_compra_id: ordem_de_compra.id, almoxarifado_id: almoxarifado.id, data_de_emissao: '2016-15-11')
			item_do_recebimento = FactoryBot.create(:gestao_de_estoque_itens_do_recebimento_de_material, recebimento_de_material_id: recebimento_de_material.id, item_id: item_da_ordem.item_id, quantidade: 10)
			recebimento_de_material.update_attribute(:status, "recebido")
			expect(ordem_de_compra.quantidade_a_receber).to eq 0
		end
	end

	context "Válida se o empenho tem itens" do
		it "Quando tem itens" do
			item_empenho = FactoryBot.create(:item_do_empenho)
			ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, empenho_id: item_empenho.empenho.id)
			ordem_de_compra.validate
			expect(ordem_de_compra.errors[:base]).to_not include "Empenho selecionado não tem itens"
		end
		it "Quando não tem itens" do
			empenho = FactoryBot.create(:empenho_22090001, status: 'solicitado')
			ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, empenho_id: empenho.id)
			ordem_de_compra.validate
			expect(ordem_de_compra.errors[:base]).to include "Empenho selecionado não tem itens"
		end
	end

	describe "#define_tipo_de_ordem_de_compra" do
		context "Quando é ordem de fornecimento" do
			it "define tipo como ordem de fornecimento" do
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra)
				ordem_de_compra.save(validate: false)
				allow(ordem_de_compra).to receive(:eh_ordem_de_fornecimento?).and_return(true)

				ordem_de_compra.define_tipo_de_ordem_de_compra
				expect(ordem_de_compra.reload.tipo_de_ordem_de_compra).to eq "ordem_de_fornecimento"
			end
		end
		context "Quando é ordem de serviço" do
			it "define tipo como ordem de serviço" do
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra, empenho_id: nil)
				ordem_de_compra.save(validate: false)

				ordem_de_compra.define_tipo_de_ordem_de_compra
				expect(ordem_de_compra.reload.tipo_de_ordem_de_compra).to eq "ordem_de_servico"
			end
		end
	end

	describe "#valida_se_pelo_menos_um_esta_preenchido?" do
		context "Quando é válido" do
			it "Quando não tem item" do
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra)
				ordem_de_compra.validate
				expect(ordem_de_compra.errors[:base]).to_not include("É necessário preencher pelo menos um item")
			end
			it "Quando tem pelo menos um item com valor maior que zero" do
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra)
				ordem_de_compra.itens_da_ordem_de_compra.build(total: 0)
				ordem_de_compra.itens_da_ordem_de_compra.build(total: 10)

				ordem_de_compra.validate
				expect(ordem_de_compra.errors[:base]).to_not include("É necessário preencher pelo menos um item")
			end
		end
		context "Quando é inválido" do
			it "Quando nenhum item tem valor maior que zero" do
				ordem_de_compra = FactoryBot.build(:licitacao_ordem_de_compra)
				ordem_de_compra.itens_da_ordem_de_compra.build(total: 0)
				ordem_de_compra.itens_da_ordem_de_compra.build(total: 0)

				ordem_de_compra.validate
				expect(ordem_de_compra.errors[:base]).to include("É necessário preencher pelo menos um item")
			end
		end
	end

	describe "#lancar_ocorrencia" do
		it 'Cria ocorrencia para a ordem de compra' do
			ordem_de_compra = FactoryBot.create(:licitacao_ordem_de_compra)
			ordem_de_compra.status = "fechado"
			ordem_de_compra.save
			expect(ordem_de_compra.ocorrencias_da_ordem_de_compra.count).to eql(1)
		end
	end
end
