require 'rails_helper'

RSpec.describe Base::Pessoa, type: :model do
	[:tipo_de_pessoa, :estado_civil, :cidade, :estado].each do |campo|
		it{ is_expected.to belong_to campo }
	end

	it{ is_expected.to have_many(:cnaes).class_name('Base::CnaeDaPessoa') }
	it{ is_expected.to have_many(:pessoas_contas_bancarias).dependent(:destroy).inverse_of(:pessoa) }
	it{ is_expected.to have_many(:agentes_publicos_municipais).class_name('Base::AgentePublicoMunicipal') }
	it{ is_expected.to have_many(:diarias).through(:agentes_publicos_municipais).class_name('Contabilidade::Diaria') }
	it{ is_expected.to have_many(:empenhos).class_name('Contabilidade::Empenho') }
	it{ is_expected.to have_many(:liquidacoes).through(:empenhos).class_name('Contabilidade::Liquidacao') }
	it{ is_expected.to have_many(:pagamentos).through(:liquidacoes).class_name('Contabilidade::Pagamento') }
	it{ is_expected.to have_many(:retencoes).through(:pagamentos).class_name('Contabilidade::Retencao') }
	it{ is_expected.to have_many(:pessoas_dos_projetos).class_name('Licitacao::PessoaDoProjeto') }
	it{ is_expected.to have_many(:projetos).through(:pessoas_dos_projetos).class_name('Licitacao::Projeto') }

	it { is_expected.to accept_nested_attributes_for :cnaes }
	it { is_expected.to accept_nested_attributes_for :pessoas_contas_bancarias }

	[:tipo_de_pessoa_id, :nome, :data_do_cadastro, :cidade_id].each do |campo|
		it{ is_expected.to validate_presence_of campo }
	end

	it { is_expected.to validate_numericality_of(:dependentes).allow_nil }

	it { is_expected.to validate_length_of(:nome).is_at_most(80) }
	it { is_expected.to validate_length_of(:cpf).is_at_most(11) }
	it { is_expected.to validate_length_of(:cnpj).is_at_most(14) }
	it { is_expected.to validate_length_of(:identidade).is_at_most(25) }
	it { is_expected.to validate_length_of(:inscricao_estadual).is_at_most(25) }
	it { is_expected.to validate_length_of(:orgao_expedidor).is_at_most(10) }
	it { is_expected.to validate_length_of(:inscricao_municipal).is_at_most(15) }
	it { is_expected.to validate_length_of(:cep).is_equal_to(8) }
	it { is_expected.to validate_length_of(:logradouro).is_at_most(120) }
	it { is_expected.to validate_length_of(:numero).is_at_most(8) }
	it { is_expected.to validate_length_of(:complemento).is_at_most(80) }
	it { is_expected.to validate_length_of(:bairro).is_at_most(60) }
	it { is_expected.to validate_length_of(:telefone).is_at_most(15) }
	it { is_expected.to validate_length_of(:nit).is_at_most(11) }
	it { is_expected.to validate_length_of(:profissao).is_at_most(60) }
	it { is_expected.to validate_length_of(:naturalidade).is_at_most(60) }
	it { is_expected.to validate_length_of(:email).is_at_most(120) }

	it { is_expected.to allow_value('01/01/2016').for(:data_de_nascimento) }
	it { is_expected.to allow_value('').for(:data_de_nascimento) }
	it { is_expected.to_not allow_value('00/').for(:data_de_nascimento) }

	it { is_expected.to allow_value('01/01/2016').for(:data_da_emissao) }
	it { is_expected.to allow_value('').for(:data_da_emissao) }
	it { is_expected.to_not allow_value('00/').for(:data_da_emissao) }

	it { is_expected.to allow_value('01/01/2016').for(:data_do_cadastro) }
	it { is_expected.to_not allow_value('').for(:data_do_cadastro) }
	it { is_expected.to_not allow_value('00/').for(:data_do_cadastro) }

	context "pessoa é do tipo pessoa física" do
		before { allow(subject).to receive(:pessoa_fisica?).and_return(true) }
		it{ is_expected.to validate_presence_of :cpf }
		it{ is_expected.to validate_absence_of :porte }
	end

	context "pessoa é do tipo pessoa jurídica" do
		before { allow(subject).to receive(:pessoa_juridica?).and_return(true) }
		it{ is_expected.to validate_presence_of :cnpj }
		it{ is_expected.to validate_presence_of :porte }
	end

	context "pessoa é fornecedor" do
		before { allow(subject).to receive(:fornecedor?).and_return(true) }
		it{ is_expected.to validate_presence_of :cep }
	end

	context "pessoa é do tipo pessoa juridica porte osc" do
		before { allow(subject).to receive(:osc?).and_return(true) }
		it{ is_expected.to validate_presence_of :email }
	end

	describe '#uniq_nested_attributes :cnae' do
		let(:cnae)  { cnae = FactoryBot.create(:base_cnae, descricao: 'treinamento') }
		let(:pessoa) { FactoryBot.create(:pessoa_fisica, fornecedor: true) }

		context 'verifica unicidade de cnae por fornecedor' do
			it 'retorna erro' do
				atributos_pessoa =  {
					cnaes_attributes: {
							'0': {
								pessoa_id: pessoa.id,
								cnae_id: cnae.id,
								principal:false
							},
							'1': {
								pessoa_id: pessoa.id,
								cnae_id: cnae.id,
								principal:true
							}
					}
				}
				pessoa.update(atributos_pessoa)
				expect(pessoa.errors[:cnaes]).to include 'cnae deve ser único dentro de um fornecedor'
			end
		end
	end

	describe '#verifica_cnae_principal' do
		context 'quando são marcados 2 cnaes como principais' do
			it 'retorna erro' do
				cnae = FactoryBot.create(:base_cnae)
				pessoa = FactoryBot.create(:pessoa_fisica, fornecedor: true)

				atributos_pessoa =  {
					cnaes_attributes: {
							'0': {
								pessoa_id: pessoa.id,
								cnae_id: cnae.id,
								principal: true
							},
							'1': {
								pessoa_id: pessoa.id,
								cnae_id: cnae.id,
								principal: true
							}
					}
				}

				pessoa.update(atributos_pessoa)
				expect(pessoa.errors[:cnaes]).to include "Apenas um CNAE pode ser o principal da empresa"
			end
		end
		context 'quando apenas um cnae é marcado como principal' do
			it 'salva' do
				cnae = FactoryBot.create(:base_cnae)
				pessoa = FactoryBot.create(:pessoa_fisica, fornecedor: true)

				atributos_pessoa =  {
					cnaes_attributes: {
							'0': {
								pessoa_id: pessoa.id,
								cnae_id: cnae.id,
								principal:true
							},
							'1': {
								pessoa_id: pessoa.id,
								cnae_id: cnae.id,
								principal:false
							}
					}
				}

				pessoa.update(atributos_pessoa)
				expect(pessoa.errors[:cnaes]).to_not include "Apenas um CNAE pode ser o principal da empresa"
			end
		end
	end

	describe ':verifica_se_tem_ao_menos_uma_cnae_principal' do
		context 'verifica se tem ao menos uma cnae principal' do
			it 'retorna erro' do
				cnae = FactoryBot.create(:base_cnae)
				pessoa = FactoryBot.create(:pessoa_fisica, fornecedor: true)

				atributos_pessoa =  {
					cnaes_attributes: {
							'0': {
								pessoa_id: pessoa.id,
								cnae_id: cnae.id,
								principal:false
							},
					}
				}

				pessoa.update(atributos_pessoa)
				expect(pessoa.errors[:cnaes]).to include 'Deve ser selecionado um CNAE principal'
			end

			it 'retorna erro' do
				cnae = FactoryBot.create(:base_cnae)
				pessoa = FactoryBot.create(:pessoa_fisica, fornecedor: true)

				atributos_pessoa =  {
					cnaes_attributes: {
							'0': {
								pessoa_id: pessoa.id,
								cnae_id: cnae.id,
								principal:true
							},
					}
				}

				pessoa.update(atributos_pessoa)
				expect(pessoa.errors[:cnaes]).to_not include 'Deve ser selecionado um CNAE principal'
			end
		end
	end

	describe "#verifica_se_fornecedor_esta_em_uso" do
		it "se tiver pedidos" do
			pessoa = FactoryBot.create(:pessoa_fisica, fornecedor: true)
			FactoryBot.create(:pessoa_do_pedido, pessoa_id: pessoa.id)
			pessoa.update(fornecedor: false)
			expect(pessoa.errors[:fornecedor]).to include  "Não é possivel remover a função de fornecedor dessa pessoa, cadastro utilizado em processos licitatórios."
		end

		it "se não tiver pedidos" do
			pessoa = FactoryBot.create(:pessoa_fisica, fornecedor: true)
			pessoa.update(fornecedor: false)
			expect(pessoa.errors[:fornecedor]).to_not include  "Não é possivel remover a função de fornecedor dessa pessoa, cadastro utilizado em processos licitatórios."
		end

		it "se tiver projetos" do
			pessoa = FactoryBot.create(:pessoa_fisica, fornecedor: true)
			FactoryBot.create(:licitacao_pessoa_do_projeto, pessoa_id: pessoa.id)
			pessoa.update(fornecedor: false)
			expect(pessoa.errors[:fornecedor]).to include  "Não é possivel remover a função de fornecedor dessa pessoa, cadastro utilizado em processos licitatórios."
		end

		it "se não tiver projetos" do
			pessoa = FactoryBot.create(:pessoa_fisica, fornecedor: true)
			pessoa.update(fornecedor: false)
			expect(pessoa.errors[:fornecedor]).to_not include  "Não é possivel remover a função de fornecedor dessa pessoa, cadastro utilizado em processos licitatórios."
		end
	end

	describe "#pessoa_fisica?" do
		it "é verdadeiro" do
			pessoa = Base::Pessoa.new
			pessoa.tipo_de_pessoa = FactoryBot.create( :tipo_pessoa_fisica )

			expect(pessoa.pessoa_fisica?).to eq true
		end

		it "é falso" do
			pessoa = Base::Pessoa.new
			pessoa.tipo_de_pessoa_id = 2

			expect(pessoa.pessoa_fisica?).to eq false
		end

		it "é falso quando tipo_de_pessoa_id é nulo" do
			pessoa = Base::Pessoa.new

			expect(pessoa.pessoa_fisica?).to eq false
		end
	end

	describe "#pessoa_juridica?" do
		it "é verdadeiro" do
			pessoa = Base::Pessoa.new
			pessoa.tipo_de_pessoa = FactoryBot.create( :tipo_pessoa_juridica )
			expect(pessoa.pessoa_juridica?).to eq true
		end

		it "é falso" do
			pessoa = Base::Pessoa.new
			pessoa.tipo_de_pessoa = FactoryBot.create( :tipo_pessoa_fisica )

			expect(pessoa.pessoa_juridica?).to eq false
		end

		it "é falso quando tipo_de_pessoa_id é nulo" do
			pessoa = Base::Pessoa.new

			expect(pessoa.pessoa_juridica?).to eq false
		end
	end

	context "cpf ou cnpj sem formatacao" do
		it "retorne o cpf" do
			pessoa = Base::Pessoa.new
			pessoa.tipo_de_pessoa = FactoryBot.create( :tipo_pessoa_fisica )
			pessoa.cpf = "55154913604"

			expect(pessoa.cpf_ou_cnpj_sem_pontos).to eq "55154913604"
		end

		it "retorne o cnpj" do
			pessoa = Base::Pessoa.new
			pessoa.tipo_de_pessoa = FactoryBot.create( :tipo_pessoa_fisica )
			pessoa.cnpj = "48886510000134"

			expect(pessoa.cpf_ou_cnpj_sem_pontos).to eq "48886510000134"
		end
	end

	context "formatacao de cpf e cpnf" do
		it "que o cpf tenha o formato 000.000.000-00" do
			pessoa = Base::Pessoa.new
			pessoa.cpf = "55154913604"

			expect(pessoa.cpf.try(:as_cpf)).to eq "551.549.136-04"
		end

		it "que o cnpj tenha o formato 00.000.000/0000-00" do
			pessoa = Base::Pessoa.new
			pessoa.cnpj = "48886510000134"

			expect(pessoa.cnpj.try(:as_cnpj)).to eq "48.886.510/0001-34"
		end

		it "retorne o cpf formatado" do
			pessoa = Base::Pessoa.new
			pessoa.tipo_de_pessoa = FactoryBot.create( :tipo_pessoa_fisica )
			pessoa.cpf = "55154913604"

			expect(pessoa.cpf_ou_cnpj).to eq "551.549.136-04"
		end

		it "retorne o cnpj formatado" do
			pessoa = Base::Pessoa.new
			pessoa.tipo_de_pessoa = FactoryBot.create( :tipo_pessoa_juridica )
			pessoa.cnpj = "48886510000134"

			expect(pessoa.cpf_ou_cnpj).to eq "48.886.510/0001-34"
		end

		it "retorna o cpf e o nome" do
			pessoa = Base::Pessoa.new
			pessoa.nome = "FULANO"
			pessoa.tipo_de_pessoa = FactoryBot.create( :tipo_pessoa_fisica )
			pessoa.cpf = "55154913604"

			expect(pessoa.cpf_ou_cnpj_e_nome).to eq "551.549.136-04 - FULANO"
		end
	end

	describe "#tem_contas_bancarias?" do
		context "se tiver conta(s) bancaria(s)" do
			it "retorna true" do
				pessoa_conta_bancaria = FactoryBot.create(:pessoa_conta_bancaria)
				expect(pessoa_conta_bancaria.pessoa.tem_contas_bancarias?).to eq true
			end
		end

		context "se não tiver conta bancaria" do
			it "retorna false" do
				pessoa = FactoryBot.create(:pessoa_fisica)
				expect(pessoa.tem_contas_bancarias?).to eq false
			end
		end
	end

end
