require 'rails_helper'

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

	# it_behaves_like "gera eventos contábeis", "Recolher", Contabilidade::TalaoDeReceita, :contabilidade_talao_de_receita_sem_convenio

	it{ is_expected.to belong_to( :orcamento ).required(true) }
	it{ is_expected.to belong_to( :natureza_da_receita ).class_name('Base::NaturezaDaReceita')}
	it{ is_expected.to belong_to( :pessoa ).class_name('Base::Pessoa').required(true) }
	it{ is_expected.to belong_to( :conta_bancaria_por_unidade_orcamentaria ).class_name('Base::ContaBancariaPorUnidadeOrcamentaria') }
	it{ is_expected.to have_many( :anulacoes_dos_taloes_de_receita ) }

	[:data_do_talao, :valor, :tipo_do_talao, :historico, :pessoa_id, :conta_bancaria_por_unidade_orcamentaria_id,
		:documento_de_credito, :tipo_de_documento].each do |atributo|
		it{ is_expected.to validate_presence_of atributo }
	end

	it{ is_expected.to validate_uniqueness_of( :numero_do_talao ).scoped_to( :orcamento_id ).case_insensitive}

	it { is_expected.to validate_length_of(:documento_de_credito).is_at_most(20)}

	it { is_expected.to_not allow_value('').for(:data_do_talao) }
	it { is_expected.to_not allow_value('00/').for(:data_do_talao) }

	#it { is_expected.to_not allow_value('').for(:data_do_credito) }
	#it { is_expected.to_not allow_value('00/').for(:data_do_credito) }

	describe '#atribui_codigo_disponivel' do
		it "atribui ao talão de receita o próximo código disponível" do
			talao_de_receita_1 = FactoryBot.create( :contabilidade_talao_de_receita_sem_convenio )
			talao_de_receita_1.numero_do_talao = talao_de_receita_1.atribui_codigo_disponivel
			talao_de_receita_1.save

			talao_de_receita_2 = FactoryBot.create( :contabilidade_talao_de_receita_sem_convenio )
			talao_de_receita_2.numero_do_talao = talao_de_receita_2.atribui_codigo_disponivel
			talao_de_receita_2.save
			expect(talao_de_receita_2.numero_do_talao).to eq "13090002"
		end
	end

	describe '#lancar_na_conta_bancaria' do
		it "lançou um movimento da conta bancária apos criar um talão de receita" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))
			movimentacao_da_conta_bancaria = Contabilidade::MovimentacaoDaContaBancaria.where(conta_bancaria_por_unidade_orcamentaria: talao_de_receita.conta_bancaria_por_unidade_orcamentaria).last
			expect(movimentacao_da_conta_bancaria.valor.to_f).to eq talao_de_receita.valor.to_f
		end
	end

	describe '#lancar_movimento_orcamentario' do
		context 'valor do talão é diferente de zero' do
			it 'cria um lançamento da receita após criar um talão da receita' do
				orcamento_da_receita = Loa::OrcamentoDaReceita.find_or_create_by!( FactoryBot.attributes_for(:orcamento_da_receita_saude) )
				talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, valor: 100, natureza_da_receita: orcamento_da_receita.unidade_orcamentaria_por_natureza_da_receita.natureza_da_receita))
				lancamento_do_orcamento_da_receita = Contabilidade::LancamentoDoOrcamentoDaReceita.last
				expect(lancamento_do_orcamento_da_receita.modulo).to eq talao_de_receita
			end
		end
	end

	describe '#apagar_movimento_orcamentario' do
		it 'ao apagar talão de receita, apaga movimento orçamentário' do
			orcamento_da_receita = Loa::OrcamentoDaReceita.find_or_create_by!( FactoryBot.attributes_for(:orcamento_da_receita_saude) )
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, natureza_da_receita: orcamento_da_receita.unidade_orcamentaria_por_natureza_da_receita.natureza_da_receita))
			lancamento_do_orcamento_da_receita = Contabilidade::LancamentoDoOrcamentoDaReceita.where(orcamento_da_receita: orcamento_da_receita).last
			expect(lancamento_do_orcamento_da_receita.modulo).to eq talao_de_receita
		end
	end

	describe "#saldo" do
		it "valor do saldo igual a 9.99 quando nao existe anulacao" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))

			expect(talao_de_receita.saldo.to_f).to eq 9.99
		end

		it "valor do saldo igual a 5.00 quando foi anulado 4.99" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))
			talao_de_receita.valor_anulado = 4.99
			expect(talao_de_receita.saldo.to_f).to eq 5.00
		end
	end

	describe "#saldo em porcentagem" do
		it "valor do saldo igual a 9.99 quando nao existe anulacao" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))

			expect(talao_de_receita.saldo_em_porcentagem.to_f).to eq 100
		end

		it "valor do saldo igual a 5.00 quando foi anulado 5.00" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, valor: 10))
			talao_de_receita.valor_anulado = 5
			expect(talao_de_receita.saldo_em_porcentagem.to_f).to eq 50
		end
	end

	describe "#porcentagem anulada" do
		it "quando nao existe anulacao" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))

			expect(talao_de_receita.porcentagem_anulada.to_f).to eq 0
		end

		it "quando foi anulado 5.00" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, valor: 10))
			talao_de_receita.valor_anulado = 5
			expect(talao_de_receita.porcentagem_anulada.to_f).to eq 50
		end

		it "quando foi anulado 10" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, valor: 10))
			talao_de_receita.valor_anulado = 10
			expect(talao_de_receita.porcentagem_anulada.to_f).to eq 100
		end
	end

	describe "#anulado?" do
		it "anulado é verdadeiro se nao existe saldo" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))
			talao_de_receita.valor_anulado = talao_de_receita.valor
			expect(talao_de_receita.anulado?).to eq true
		end

		it "anulado é falso se existe saldo" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))
			talao_de_receita.valor = 100.00
			talao_de_receita.valor_anulado = 10.00
			expect(talao_de_receita.anulado?).to eq false
		end
	end

	describe "#parcialmente_anulado?" do
		it "está parcialmente anulado se existe lançamento de anulação e ainda tem saldo" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))
			talao_de_receita.valor = 100.00
			talao_de_receita.valor_anulado = 10.00
			expect(talao_de_receita.parcialmente_anulado?).to eq true
		end

		it "não está parcialmente anulado pois não existe lançamento de anulação" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))
			talao_de_receita.valor = 100.00
			talao_de_receita.valor_anulado = 0.00
			expect(talao_de_receita.parcialmente_anulado?).to eq false
		end

		it "não está parcialmente anulado pois está totalmente anulado" do
			talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio))
			talao_de_receita.valor = 100.00
			talao_de_receita.valor_anulado = 100.00
			expect(talao_de_receita.parcialmente_anulado?).to eq false
		end
	end

	describe 'validação de mesmo exercício do orçamento para data_do_talao' do
		context 'quando data de talão de um exercício diferente do orçamento' do
			it "retorna erro" do
				talao_de_receita = Contabilidade::TalaoDeReceita.create(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, data_do_talao: "2015-01-01"))
				expect( talao_de_receita.errors[:data_do_talao] ).to include "deve ser do mesmo exercício do orçamento"
			end
		end
		context 'quando data de talão de um exercício igual a do orçamento' do
			it "salva o talão de receita" do
				talao_de_receita = Contabilidade::TalaoDeReceita.create(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, data_do_talao: "2016-01-01"))
				talao_de_receita.validate
				expect( talao_de_receita.errors[:data_do_talao] ).to_not include "deve ser do mesmo exercício do orçamento"
			end
		end
	end

	#describe 'validação de mesmo exercício do orçamento para data_do_credito' do
	#	context 'quando data de crédito de um exercício diferente do orçamento' do
	#		it "retorna erro" do
	#			talao_de_receita = Contabilidade::TalaoDeReceita.create(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, data_do_credito: "2015-01-01"))
	#			expect( talao_de_receita.errors[:data_do_credito] ).to include "deve ser do mesmo exercício do orçamento"
	#		end
	#	end
	#	context 'quando data de crédito de um exercício igual a do orçamento' do
	#		it "salva o talão de receita" do
	#			talao_de_receita = Contabilidade::TalaoDeReceita.create(FactoryBot.attributes_for(:contabilidade_talao_de_receita_sem_convenio, data_do_credito: "2016-01-01"))
	#			expect( talao_de_receita ).to be_persisted
	#		end
	#	end
	#end

	describe 'valida saldo do orcamento da receita' do
		it "quando lanca movimento orcamentario" do
			#talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita))
			#expect( talao_de_receita.natureza_da_receita.orcamentos_da_receita.first.valor_arrecadado.to_f ).to eq talao_de_receita.valor.to_f
			pending("Implementar")
			fail
		end

		it "quando apaga movimento orcamentario" do
			#talao_de_receita = Contabilidade::TalaoDeReceita.create!(FactoryBot.attributes_for(:contabilidade_talao_de_receita))
			#talao_de_receita.destroy
			#expect( Loa::OrcamentoDaReceita.last.valor_arrecadado.to_f ).to eq 0.to_f
			pending("Implementar")
			fail
		end
	end

	describe '#data_nao_pode_estar_no_futuro' do
		it 'valida que a data do talão não pode ser maior que o dia atual de lançamento' do
			talao_de_receita = Contabilidade::TalaoDeReceita.new( FactoryBot.attributes_for( :contabilidade_talao_de_receita_sem_convenio, data_do_talao: Date.tomorrow ) )
			talao_de_receita.save

			expect(talao_de_receita.errors[:data_do_talao]).to include( 'data de lançamento não pode ser maior que hoje' )
		end
	end

	context "Data do talão superior a data da abertura de conta" do
		before(:each) do
			@talao_de_receita = FactoryBot.create(:contabilidade_talao_de_receita_sem_convenio)
			@talao_de_receita.reload
		end
		it "Quando data do talão é superior ou igual a data de aberura da conta" do
			@talao_de_receita.conta_bancaria_por_unidade_orcamentaria.conta_bancaria.update_attribute(:data_de_abertura, @talao_de_receita.data_do_talao)
			@talao_de_receita.validate
			expect(@talao_de_receita.errors[:data_do_talao]).to_not include "Deve ser Superior a Data de Abertura da Conta"
		end
		it "Quando data do talão é inferior a data de abertura da conta" do
			@talao_de_receita.conta_bancaria_por_unidade_orcamentaria.conta_bancaria.update_attribute(:data_de_abertura, @talao_de_receita.data_do_talao + 1.day)
			@talao_de_receita.validate
			expect(@talao_de_receita.errors[:data_do_talao]).to include "Deve ser Superior a Data de Abertura da Conta"
		end
	end

	describe "Quando o talão é de redução" do
		before(:each) do
			@natureza_receita_deducao = Base::NaturezaDaReceita.find_or_create_by!( FactoryBot.attributes_for(:nova_natureza_receita_deducao) )
		end

		context "e não possui anulações" do
			it 'retorna o valor total do talão abaixo de zero' do
				talao_de_receita = FactoryBot.create(:contabilidade_talao_de_receita_sem_convenio, natureza_da_receita: @natureza_receita_deducao, valor: 1000)
				expect(talao_de_receita.saldo).to eq -1000
			end
		end

		context "e não possui uma anulação parcial" do
			it 'retorna o valor total do talão abaixo de zero' do
				talao_de_receita = FactoryBot.create(:contabilidade_talao_de_receita_sem_convenio, natureza_da_receita: @natureza_receita_deducao, valor: 1000)
				anulacao_do_talao_de_receita = Contabilidade::AnulacaoDoTalaoDeReceita.create(talao_de_receita: talao_de_receita, valor: 100.00, historico: "...", data_da_anulacao: Date.today, tipo_de_anulacao: :parcial)
				expect(talao_de_receita.reload.saldo).to eq -900
			end
		end

		context "e não possui uma anulação total" do
			it 'retorna o valor total do talão abaixo de zero' do
				talao_de_receita = FactoryBot.create(:contabilidade_talao_de_receita_sem_convenio, natureza_da_receita: @natureza_receita_deducao, valor: 1000)
				anulacao_do_talao_de_receita = Contabilidade::AnulacaoDoTalaoDeReceita.create(talao_de_receita: talao_de_receita, valor: 1000.00, historico: "...", data_da_anulacao: Date.today, tipo_de_anulacao: :total)
				expect(talao_de_receita.reload.saldo).to eq 0
			end
		end
	end

end
