require 'rails_helper'

RSpec.describe Ppa::Proposta, type: :model do

	it{ is_expected.to belong_to :micro_regiao }
	it{ is_expected.to belong_to :sub_area_tematica }
	it{ is_expected.to belong_to :cidadao }
	it{ is_expected.to belong_to :ppa }
	it{ is_expected.to belong_to :proposta_combinada }

	it{ is_expected.to have_one  :iniciativa }
	it{ is_expected.to have_many :votos_da_proposta }
	it{ is_expected.to have_many :propostas_combinadas }

	it{ is_expected.to validate_presence_of(:area_tematica_id).on(:create) }
	it{ is_expected.to validate_presence_of(:descricao)}
	it{ is_expected.to validate_presence_of(:micro_regiao_id) }

	describe 'validate_presence_of :sub_area_tematica_id' do
		context 'quando sistema está utilizando somente área temática' do
			subject {
				ppa = FactoryBot.create :ppa_fortaleza_2014, ativar_somente_area_tematica: true
				FactoryBot.build(:ppa_proposta, ppa_id: ppa.id)
			}
			it { is_expected.not_to validate_presence_of :sub_area_tematica_id }
		end

		context 'quando sistema também utiliza subárea temática' do
			subject {
				ppa = FactoryBot.create :ppa_fortaleza_2014, ativar_somente_area_tematica: false
				FactoryBot.build(:ppa_proposta, ppa_id: ppa.id)
			}
			it { is_expected.to validate_presence_of :sub_area_tematica_id }
		end
	end

	describe 'validate_presence_of :regiao_id, on: :create' do
		context 'quando sistema está utilizando somente região' do
			subject {
				ppa = FactoryBot.create :ppa_fortaleza_2014, ativar_somente_micro_regiao: true
				FactoryBot.build(:ppa_proposta, ppa_id: ppa.id)
			}
			it { is_expected.not_to validate_presence_of :regiao_id }
		end

		context 'quando sistema também utiliza subregião' do
			subject {
				ppa = FactoryBot.create :ppa_fortaleza_2014, ativar_somente_micro_regiao: false
				FactoryBot.build(:ppa_proposta, ppa_id: ppa.id)
			}
			it { is_expected.to validate_presence_of :regiao_id }
		end
	end

	describe '#validate_presence_of proposta_com_combinacoes_id' do
		context 'quando o status é combinada' do
			subject(:proposta_combinada) {
				FactoryBot.build(:ppa_proposta, status: 'combinada')
			}

			it { is_expected.to validate_presence_of :proposta_combinada_id }
		end

		context 'quando o status não é combinada' do
			subject(:proposta_nao_combinada) {
				FactoryBot.build(:ppa_proposta)
			}

			it { is_expected.to validate_absence_of :proposta_combinada_id }
		end
	end

	describe '#termos_de_uso' do
		it "quando o usuário não concordou com os termos" do
			ppa = FactoryBot.create(:ppa_fortaleza_2014, habilitar_termos_de_uso: true)
			cidadao = FactoryBot.create(:cidadao, aceitou_os_termos_de_uso: false)
			proposta = FactoryBot.build(:ppa_proposta, cidadao_id: cidadao.id, ppa_id: ppa.id, interna: false)
			proposta.validate
			expect(proposta.errors[:cidadao_id]).to include "Você não pode enviar propostas sem aceitar os termos de uso"
		end

		it "quando o usuário não concordou com os termos, mas é uma edição interna" do
			ppa = FactoryBot.create(:ppa_fortaleza_2014, habilitar_termos_de_uso: true)
			cidadao = FactoryBot.create(:cidadao, aceitou_os_termos_de_uso: false)
			proposta = FactoryBot.build(:ppa_proposta, cidadao_id: cidadao.id, ppa_id: ppa.id, interna:true)
			proposta.save
			expect(proposta).to be_persisted
		end
	end

	describe 'combinação de proposta' do
		context 'existe' do
			subject { FactoryBot.build(:ppa_proposta, status: 5) }
			it { is_expected.to validate_presence_of :proposta_combinada_id }
		end
		context 'não existe' do
			subject { FactoryBot.build(:ppa_proposta, status: 2) }
			it { is_expected.to validate_absence_of :proposta_combinada_id }
		end
	end

	describe 'validates_length_of :descricao' do
		context 'quando é um problema' do
			subject { FactoryBot.build(:ppa_proposta, status: 2, is_problema: true) }
			it { is_expected.to validate_length_of :descricao }
		end
	end

	describe 'validates_length_of :problema' do
		context 'quando é um problema' do
			subject { FactoryBot.build(:ppa_proposta, status: 2, is_problema: true) }
			it { is_expected.to validate_length_of :problema }
		end
	end

	describe 'validates_length_of :cidadao_id' do
		context 'quando é criado externamente' do
			subject { FactoryBot.build(:ppa_proposta, status: 2, interna: false) }
			it { is_expected.to validate_length_of :cidadao_id }
		end
	end

	describe '#maximo_de_caracteres_da_descricao' do
		context "caso proposta externa" do
			subject(:proposta) {
				ppa = FactoryBot.create :ppa_fortaleza_2014, quantidade_de_caracteres_das_propostas: 15
				FactoryBot.build(:ppa_proposta, ppa_id: ppa.id,interna: false)
			}

			it 'retorna mensagem de erro' do
				proposta.descricao = 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...'
				proposta.save
				expect(proposta.errors[:descricao]).to include "é muito longo (máximo: #{proposta.ppa.quantidade_de_caracteres_das_propostas.to_i} caracteres)"
			end
		end
	end

	describe '#copia_proposta_para_proposta_revisada' do
		context 'na criação de uma proposta' do
			it 'copia a proposta para a proposta revisada' do
				proposta = FactoryBot.create(:ppa_proposta, descricao: 'Esta descrição é um exemplo de teste que possui muitos caracteres')
				expect(proposta.proposta_revisada).to eq proposta.descricao
			end
		end
	end

	describe "escopo" do
		context "votaveis" do
			it "deve incluir propostas em votação, aprovadas ou rejeitadas" do
				proposta_em_analise = FactoryBot.create(:ppa_proposta, status: 0)
				proposta_rejeitada = FactoryBot.create(:ppa_proposta, status: 1)
				proposta_em_votacao = FactoryBot.create(:ppa_proposta, status: 2)
				proposta_aprovada = FactoryBot.create(:ppa_proposta, status: 3)
				proposta_reprovada = FactoryBot.create(:ppa_proposta, status: 4)

				expect( Ppa::Proposta.votaveis ).not_to include(proposta_em_analise)
				expect( Ppa::Proposta.votaveis ).not_to include(proposta_rejeitada)
				expect( Ppa::Proposta.votaveis ).to include(proposta_em_votacao)
				expect( Ppa::Proposta.votaveis ).to include(proposta_aprovada)
				expect( Ppa::Proposta.votaveis ).to include(proposta_reprovada)
			end
		end
	end

	describe '#quantidade_limite_de_propostas_por_cidadao' do
		context 'quando excede o limite de propostas' do
			it 'retorna mensagem de erro' do
				ppa = FactoryBot.create :ppa_fortaleza_2014, quantidade_limite_de_propostas: 2
				FactoryBot.create(:ppa_proposta, status: 3, ppa_id: ppa.id)
				FactoryBot.create(:ppa_proposta, status: 0, ppa_id: ppa.id)

				proposta = FactoryBot.build(:ppa_proposta, status: 2, ppa_id: ppa.id)
				proposta.save

				expect(proposta.errors[:cidadao_id]).to include 'Você já excedeu o limite de envio de propostas. (2 por munícipe)'
			end
		end

		context 'quando excede o limite de propostas sendo proposta interna' do
			it 'ignora o limite e salva a proposta' do
				ppa = FactoryBot.create :ppa_fortaleza_2014, quantidade_limite_de_propostas: 2
				FactoryBot.create(:ppa_proposta, status: 3, ppa_id: ppa.id, cidadao_id:2)
				FactoryBot.create(:ppa_proposta, status: 0, ppa_id: ppa.id,cidadao_id:2)

				proposta = FactoryBot.build(:ppa_proposta, status: 2, ppa_id: ppa.id, cidadao_id:2, interna:true)
				proposta.save

				expect(proposta).to be_persisted
			end
		end
	end

	describe '#imutabilidade_pos_preencher_descricao' do
		context 'quando proposta é realizada alteração da proposta de um cidadão' do
			it 'retorna mensagem de erro' do
				proposta = FactoryBot.create(:ppa_proposta)
				proposta.update(descricao: 'Esta descrição é um exemplo de teste que possui muitos caracteres')
				expect(proposta.errors[:descricao]).to include "não é possível alterar a proposta original de um cidadão"
			end
		end
	end

	describe "#descricao_revisada" do
		context "caso campo proposta_revisada esteja preenchido" do
			it 'retornar valor da proposta revisada' do
				mensagem = 'Esta descrição é um exemplo de proposta revisada que possui muitos caracteres'
				proposta = FactoryBot.create(:ppa_proposta, descricao: 'Esta descrição é um exemplo de teste que possui muitos caracteres')
				proposta.update(proposta_revisada: mensagem )
				proposta.reload
				expect(proposta.descricao_revisada).to eq mensagem
			end
		end

		context "caso campo proposta_revisada não esteja preenchido" do
			it 'retornar valor da proposta revisada' do
				proposta = FactoryBot.create(:ppa_proposta)
				expect(proposta.descricao_revisada).to eq proposta.descricao
			end
		end
	end

	describe ".quantidade_problema_por_regiao" do
		context "mostra os nomes e quantidade de votos para cada regiao por problema" do
			it 'retorna nome e quantidade' do
				proposta = FactoryBot.create :ppa_proposta, problema: 'Lorem ipsum dolor sit amet, consectetur', is_problema: true
				resultado_proposta_por_regiao = Ppa::Proposta.quantidade_problema_por_regiao proposta.ppa_id
				resultado = { nome: proposta.micro_regiao.regiao.nome, quantidade: 1 }
				expect(resultado_proposta_por_regiao).to include resultado
			end
		end
	end

	describe ".quantidade_proposta_por_regiao" do
		context "mostra os nomes e quantidade de votos para cada regiao por proposta " do
			it 'retorna nome e quantidade' do
				proposta = FactoryBot.create :ppa_proposta, is_problema: false
				resultado_proposta_por_regiao = Ppa::Proposta.quantidade_proposta_por_regiao proposta.ppa_id
				resultado = { nome: proposta.micro_regiao.regiao.nome, quantidade: 1 }
				expect(resultado_proposta_por_regiao).to include resultado
			end
		end
	end

	describe ".quantidade_problema_por_micro_regiao" do
		context "mostra os nomes e quantidade de votos para cada micro_regiao por problema" do
			it 'retorna nome e quantidade' do
				proposta = FactoryBot.create :ppa_proposta, problema: 'Lorem ipsum dolor sit amet, consectetur', is_problema: true
				resultado_proposta_por_microrregiao = Ppa::Proposta.quantidade_problema_por_micro_regiao proposta.ppa_id
				resultado = { nome: proposta.micro_regiao.nome, quantidade: 1 }
				expect(resultado_proposta_por_microrregiao).to include resultado
			end
		end
	end

	describe ".quantidade_proposta_por_micro_regiao" do
		context "mostra os nomes e quantidade de votos para cada micro_regiao por propostas" do
			it 'retorna nome e quantidade' do
				proposta = FactoryBot.create :ppa_proposta, is_problema: false
				resultado_proposta_por_microrregiao = Ppa::Proposta.quantidade_proposta_por_micro_regiao proposta.ppa_id
				resultado = { nome: proposta.micro_regiao.nome, quantidade: 1 }
				expect(resultado_proposta_por_microrregiao).to include resultado
			end
		end
	end

	describe '#total_de_votos' do
		it "returna o total de votos, tanto internos quanto externos" do
			proposta = FactoryBot.create(:ppa_proposta, votos_internos: 10)
			4.times do
				cidadao = FactoryBot.build(:cidadao, aceitou_os_termos_de_uso: true)
				cidadao.save(validate: false)
				Ppa::VotoDaProposta.create(proposta_id: proposta.id, cidadao_id: cidadao.id)
			end
			proposta.reload
			expect(proposta.total_de_votos).to eq 14
		end
	end

	describe '#foi_votada_por?' do
		before(:each) do
			@proposta = FactoryBot.create(:ppa_proposta, votos_internos: 10)
		end
		context 'se o cidadão votou' do
			it 'retorna true' do
				cidadao = FactoryBot.build(:cidadao, aceitou_os_termos_de_uso: true)
				cidadao.save(validate: false)
				Ppa::VotoDaProposta.create(proposta_id: @proposta.id, cidadao_id: cidadao.id)
				expect(@proposta.foi_votada_por?(cidadao)).to be_truthy
			end
		end
		context 'se o cidadão não votou' do
			it 'retorna false' do

			end
		end
	end

	describe ".quantidade_proposta_por_area_tematica" do
		context "mostra os nomes e quantadade de votos por area tematica por propostas" do
			it 'retorna nome e quantidade' do
				proposta = FactoryBot.create :ppa_proposta, is_problema: false
				resultado_proposta_por_area_tematica = Ppa::Proposta.quantidade_proposta_por_area_tematica proposta.ppa_id
				resultado = { nome: proposta.area_tematica.nome, quantidade: 1 }
				expect(resultado_proposta_por_area_tematica).to include resultado
			end
		end
	end

	describe ".quantidade_problema_por_area_tematica" do
		context "mostra os nomes e quantidade de votos por area tematica quando problema existir em propostas" do
			it 'retorna nome e quantidade' do
				proposta = FactoryBot.create :ppa_proposta, problema: 'Lorem ipsum dolor sit amet, consectetur' ,is_problema: true
				resultado_proposta_por_area_tematica_com_problema = Ppa::Proposta.quantidade_problema_por_area_tematica proposta.ppa_id
				resultado = { nome: proposta.area_tematica.nome, quantidade: 1 }
				expect(resultado_proposta_por_area_tematica_com_problema).to include resultado
			end
		end
	end
end
