require 'rails_helper'

RSpec.describe UsuariosController, type: :controller do
	sign_in_admin

	# Isso deve retornar o mínimo de atributos obrigatórios para criar um
	# Usuario válido.
	let(:atributos_validos) {
		FactoryBot.attributes_for(:usuario_comum)
	}

	let(:atributos_invalidos) {
		{ email: '' }
	}

	let(:atributos_invalidos_password) {
		{ password: '' }
	}

	describe "GET #index" do
		it "retorna todos os usuários" do
			usuario = controller.current_usuario
			get :index
			expect( assigns[:usuarios] ).to eq( [usuario] )
		end
	end

	describe "GET #new" do
		it "atribui um(a) novo(a) usuario à @usuario" do
			get :new
			expect(assigns(:usuario)).to be_a_new(Usuario)
		end
	end

	describe "GET #edit" do
		it "atribui o(a) usuario requisitado à @usuario" do
			usuario = Usuario.create! atributos_validos
			get :edit, params: {id: usuario.to_param}
			expect(assigns(:usuario)).to eq(usuario)
		end
	end

	describe "GET #edit" do
		it "atribui o(a) usuario requisitado à @usuario" do
			usuario = Usuario.create! atributos_validos
			get :edit, params: {id: usuario.to_param}
			expect(assigns(:usuario)).to eq(usuario)
		end
	end

	describe "POST #create" do
		context "com parâmetros válidos" do
			it "cria um(a) novo(a) Usuario" do
				expect {
					post :create, params: {usuario: atributos_validos}
				}.to change(Usuario, :count).by(1)
			end

			it "atribui o(a) usuario recém criado(a) à @usuario" do
				post :create, params: {usuario: atributos_validos}
				expect(assigns(:usuario)).to be_a(Usuario)
				expect(assigns(:usuario)).to be_persisted
			end

			it "redireciona para a lista de usuários" do
				post :create, params: {:usuario => atributos_validos}
				expect(response).to redirect_to( usuarios_url )
			end
		end

		context "com parâmetros inválidos" do
			it "atribui um(a) usuario recém criado(a), mas não salvo(a), à @usuario" do
				post :create, params: {usuario: atributos_invalidos}
				expect(assigns(:usuario)).to be_a_new(Usuario)
			end

			it "re-renderiza o template 'new'" do
				post :create, params: {usuario: atributos_invalidos}
				expect(response).to render_template("new")
			end
		end

		context "se não for admin" do
			sign_in_usuario_comum

			before do
				allow( controller ).to receive(:verifica_autorizacao).and_return(true)
			end
			it "não consegue criar um usuário com o perfil administrador" do
				atributos = atributos_validos
				atributos["perfil_id"] = Perfil.administrador.id

				post :create, params: { usuario: atributos_validos }

				expect(assigns(:usuario).perfil_id ).to be_nil
			end
		end
	end

	describe "PUT #update" do
		context "com parâmetros válidos" do
			let(:novos_atributos) {
				{nome_completo: 'Nome Novo'}
			}

			it "atualiza o(a) usuario requisitado(a)" do
				usuario = Usuario.create! atributos_validos
				post :update, params: {id: usuario.to_param, usuario: novos_atributos}
				usuario.reload
				expect( usuario.nome_completo ).to eq 'Nome Novo'
			end

			it "atribui o(a) usuario requisitado(a) à @usuario" do
				usuario = Usuario.create! atributos_validos
				post :update, params: {id: usuario.to_param, usuario: atributos_validos}
				expect(assigns(:usuario)).to eq(usuario)
			end

			it "redireciona para a lista de usuário" do
				usuario = Usuario.create! atributos_validos
				post :update, params: {id: usuario.to_param, usuario: atributos_validos}
				expect(response).to redirect_to(usuarios_url)
			end
		end

		context "com parâmetros inválidos" do
			it "atribui o(a) usuario à @usuario" do
				usuario = Usuario.create! atributos_validos
				post :update, params: {id: usuario.to_param, usuario: atributos_invalidos}
				expect(assigns(:usuario)).to eq(usuario)
			end

			it "re-renderiza o template 'edit'" do
				usuario = Usuario.create! atributos_validos
				post :update, params: {id: usuario.to_param, usuario: atributos_invalidos}
				expect(response).to render_template("edit")
			end
		end

		context "se não for admin" do
			sign_in_usuario_comum

			before do
				allow( controller ).to receive(:verifica_autorizacao).and_return(true)
			end
			it "não consegue atualizar um usuário para ter o perfil administrador" do
				post :update, params: {
					id: controller.current_usuario.to_param,
					usuario: { "perfil_id" => Perfil.administrador.id }
				}

				expect(assigns(:usuario).perfil_id ).to be_nil
			end
		end
	end

	describe 'update_password' do
		context "com parâmetros válidos" do
			let(:novos_atributos) {
				{
					password: "novo_pass",
					password_confirmation: "novo_pass"
				}
			}

			it "atualiza a senha do usuário requisitado(a)" do
				usuario = Usuario.create! atributos_validos
				put :update_password, { id: usuario.to_param, usuario: novos_atributos }
				usuario.reload
				expect(usuario.valid_password?('novo_pass')).to be_truthy
			end

			it "atribui o(a) usuario requisitado(a) à @usuario" do
				usuario = Usuario.create! atributos_validos
				put :update_password, {id: usuario.to_param, usuario: atributos_validos}
				expect(assigns(:usuario)).to eq(usuario)
			end

			it "redireciona para a lista de usuário" do
				usuario = Usuario.create! atributos_validos
				put :update_password, {id: usuario.to_param, usuario: atributos_validos}
				expect(response).to redirect_to(usuarios_url)
			end
		end

		context "com parâmetros inválidos" do
			it "atribui o(a) usuario à @usuario" do
				usuario = Usuario.create! atributos_validos
				put :update_password, {id: usuario.to_param, usuario: atributos_invalidos_password}
				expect(assigns(:usuario)).to eq(usuario)
			end

			it "re-renderiza o template 'edit_password'" do
				usuario = Usuario.create! atributos_validos
				put :update_password, {id: usuario.to_param, usuario: atributos_invalidos_password}
				expect(response).to render_template("edit_password")
			end
		end
	end

	describe "DELETE #destroy" do
		it "destrói o(a) usuario requisitado(a)" do
			usuario = Usuario.create! atributos_validos
			expect {
				delete :destroy, params: {:id => usuario.to_param}
			}.to change(Usuario, :count).by(-1)
		end

		it "redireciona para a lista de usuarios" do
			usuario = Usuario.create! atributos_validos
			delete :destroy, params: {:id => usuario.to_param}
			expect(response).to redirect_to(usuarios_url)
		end
	end

	describe "#GET edit_password_via_email" do

		it "envia email de recuperação, pelo parametro depois de clicar no link" do
			usuario = Usuario.find_by(FactoryBot.attributes_for(:admin).except(:password)) || FactoryBot.create(:admin)
			get :edit_password_via_email, { :email => usuario.email }
			expect(flash[:success]).to eq 'Email enviado com sucesso!'
		end

		it "caso o email não exista" do
			usuario = Usuario.find_by(FactoryBot.attributes_for(:admin).except(:password)) || FactoryBot.create(:admin)
			usuario.email = 'email@gmail.com'
			get :edit_password_via_email, { :email => usuario.email }
			expect(flash[:alert]).to eq 'Email não existe'
		end

	end

	describe '#valida_senha' do
		it 'retorna boleano' do
			FactoryBot.create(:usuario_teste_recuperar_email)
			usuario = Usuario.find_by_email("caiointersol@gmail.com")
			senha = usuario.valid_password?('teste123')
			expect(senha).to be true
		end
	end
end
