public List <VagaViewModel> BuscarVagasPorFiltro(string text, long usuarioCandidatoAlunoId)
        {
            // Remove Acentos e caracteres especiais
            text = FormatStringUtil.ClearString(text);

            // Divide o texto digitado pelo usuário em "TAG's", quando encontrar um espaço em branco " "
            string[] tags = text.Split(" ");

            // Busca status de vaga "ativa"
            var statusVagaAtivaDb = _ctx.StatusVagas.FirstOrDefault(x => x.Descricao == StatusVagaDefaultValuesAcess.GetValue(StatusVagaDefaultValues.VagaAtiva));

            // Busca todas as Vagas que estejam ativas
            var vagas = _mapper.Map <List <VagaViewModel> >(_ctx.Vagas.Where(x => x.StatusVagaId == statusVagaAtivaDb.Id).ToList());

            // Busca todas as inscrições do candidato
            var inscricoesCandidato = _ctx.Inscricoes.Where(x => x.UsuarioCandidatoAlunoId == usuarioCandidatoAlunoId && x.Ativo).ToList();

            // Preenche municípios e demais dados, para fazer busca por estado
            vagas.ForEach(x =>
            {
                x.Municipio            = _mapper.Map <MunicipioViewModel>(_ctx.Municipios.FirstOrDefault(y => y.Id == x.Municipio.Id));
                x.Municipio.UfSigla    = _mapper.Map <UfSiglaViewModel>(_ctx.UfSiglas.FirstOrDefault(y => y.Id == x.Municipio.UfSigla.Id));
                x.AreaVagaRecomendadas = _mapper.Map <List <AreaVagaRecomendadaViewModel> >(_ctx.AreaVagaRecomendadas.Where(y => y.VagaId == x.Id));

                // Completa campo "áreas" da lista de areaVagaRecomendadas
                x.AreaVagaRecomendadas.ForEach(y =>
                {
                    y.Area = _mapper.Map <AreaViewModel>(_ctx.Areas.FirstOrDefault(a => a.Id == y.Area.Id));
                });

                x.StatusVaga      = _mapper.Map <StatusVagaViewModel>(_ctx.StatusVagas.FirstOrDefault(y => y.Id == x.StatusVaga.Id));
                x.TipoExperiencia = _mapper.Map <TipoExperienciaViewModel>(_ctx.TipoExperiencias.FirstOrDefault(y => y.Id == x.TipoExperiencia.Id));

                // Busca usuarioEmpresa
                var usuarioEmpresa = _ctx.UsuarioEmpresas.FirstOrDefault(y => y.Id == x.UsuarioEmpresaId);

                // Busca empresa por empresaId e retorna apenas o nome da empresa
                x.NomeEmpresa = _ctx.Empresas.FirstOrDefault(y => y.Id == usuarioEmpresa.EmpresaId).Nome;

                // Propriedade a mais sobre o Status da Vaga para FACILITAR no frontend (Vaga ativa == true | Vaga encerrada == false)
                x.VagaAtiva = x.StatusVaga.Id == statusVagaAtivaDb.Id ? true : false;
            });

            // Procura em ufs alguma referencia de estado ou sigla na tag
            var ufs = _mapper.Map <List <UfSiglaViewModel> >(_ctx.UfSiglas.Where(x => tags.Any(tag =>
                                                                                               FormatStringUtil
                                                                                               .ClearString(x.UFEstado)
                                                                                               .Contains(tag) ||
                                                                                               FormatStringUtil
                                                                                               .ClearString(x.UFSigla) == tag)));

            // Procura em municipios alguma referencia de cidade na tag
            var municipios = _mapper.Map <List <MunicipioViewModel> >(_ctx.Municipios.Where(x => tags.Any(tag =>
                                                                                                          FormatStringUtil
                                                                                                          .ClearString(x.Descricao)
                                                                                                          .Contains(tag))));

            //HashSet<VagaViewModel> vgs = new HashSet<VagaViewModel>(vagas);

            //var vagaTagDescricaoVaga = vagas.Where(x => tags.Any(tag =>
            //    FormatStringUtil
            //        .ClearString(x.DescricaoVaga)
            //            .Contains(tag))).ToList();

            //var vagaTagCargo = vagas.Where(x => tags.Any(tag =>
            //    FormatStringUtil
            //        .ClearString(x.Cargo)
            //            .Contains(tag))).ToList();

            //var vagaTagNomeVaga = vagas.Where(x => tags.Any(tag =>
            //    FormatStringUtil
            //        .ClearString(x.NomeVaga)
            //            .Contains(tag))).ToList();

            //vagas = vgs.Intersect(vagaTagNomeVaga).Intersect(vagaTagCargo).Intersect(vagaTagDescricaoVaga).ToList();

            //&&
            //   (ufs.Any(y => y.Id == x.Municipio.UfSigla.Id) ||
            //   municipios.Any(y => y.Id == x.Municipio.Id))

            // Busca referencia das tags no cargo, descrição, nome da vaga, cidade e uf's
            vagas = vagas.Where(x => tags.Any(tag =>
                                              FormatStringUtil
                                              .ClearString(x.DescricaoVaga)
                                              .Contains(tag) ||
                                              FormatStringUtil
                                              .ClearString(x.Cargo)
                                              .Contains(tag) ||
                                              FormatStringUtil
                                              .ClearString(x.NomeVaga)
                                              .Contains(tag))).ToList();

            // Caso a lista de municipios não esteja vazia
            if (ufs.Any() || municipios.Any())
            {
                // Itera entre todas as vagas
                foreach (var vg in vagas.ToList())
                {
                    // Remove a vaga caso não seja da cidade específicada
                    if (!(ufs.Any(x => x.Id == vg.Municipio.UfSigla.Id) || municipios.Any(x => x.Id == vg.Municipio.Id)))
                    {
                        vagas.Remove(vg);
                    }
                }
            }

            // Falta fazer o conjunto entre todas as "tag's" que o usuário digitou || remover tags que não estejam presentes na vaga (?)

            // Verifica se o usuário tem alguma inscrição em vagas
            if (inscricoesCandidato.Any())
            {
                // Retira da lista todas as vagas em que o candidato já esta cadastrado.
                inscricoesCandidato.ForEach(x =>
                {
                    vagas.RemoveAll(y => y.Id == x.VagaId);
                });
            }

            // Retorna as vagas baseado no filtro, buscando por Estado, nome, cargo, e descrição da vaga
            return(vagas);
        }
        public async Task <IActionResult> CriarUsuarioEmpresa(CriarUsuarioEmpresaInput input)
        {
            if (!ValidatorUtil.CnpjIsValid(input.Cnpj))
            {
                return(StatusCode(400, "CNPJ Inválido."));
            }

            var usuarioDb = _usuarioRepository.GetUsuarioByEmail(input.Email);

            // Verifica se já existe um usuário com mesmo email cadastrado no sistema
            if (usuarioDb != null)
            {
                return(StatusCode(400, $"Já existe um usuário com email [{input.Email}] no sistema."));
            }

            // Verifica se existe um aluno cadastrado com mesmo email
            var alunoDb = _alunoRepository.BuscarPorEmail(input.Email);

            if (alunoDb != null)
            {
                return(StatusCode(400, $"Já existe um aluno cadastrado com email [{input.Email}] no sistema."));
            }

            var empresaDb = _empresaRepository.GetByCNPJ(input.Cnpj);

            if (empresaDb == null)
            {
                #region Verifica se já existe uma empresa com o mesmo CNPJ cadastrada no sistema
                var responseReceita = await apiRequestService.ReceitaWS(input.Cnpj);

                if (responseReceita == null)
                {
                    return(StatusCode(400, "Ocorreu um erro na busca do CNPJ da Empresa, tente novamente mais tarde."));
                }

                if (responseReceita.Status.Equals("ERROR") || responseReceita.Status.Equals("CNPJ inválido") || !responseReceita.Status.Equals("OK"))
                {
                    return(StatusCode(400, $"{responseReceita.Message}"));
                }

                #region Cadastra/Busca endereços e vincula-os

                TipoEmpresa tipoEmpresa = null;

                if (responseReceita.TipoEmpresa.ToUpper() == TipoEmpresaDefaultValuesAccess.GetValue(TipoEmpresaDefaultValues.FILIAL))
                {
                    tipoEmpresa = _tipoEmpresaRepository.GetByDescricao(TipoEmpresaDefaultValuesAccess.GetValue(TipoEmpresaDefaultValues.FILIAL));
                }

                if (responseReceita.TipoEmpresa.ToUpper() == TipoEmpresaDefaultValuesAccess.GetValue(TipoEmpresaDefaultValues.MATRIZ))
                {
                    tipoEmpresa = _tipoEmpresaRepository.GetByDescricao(TipoEmpresaDefaultValuesAccess.GetValue(TipoEmpresaDefaultValues.MATRIZ));
                }

                if (tipoEmpresa == null)
                {
                    return(StatusCode(400, "Houve um erro ao adquirir o tipo da empresa."));
                }

                var responseViaCep = await apiRequestService.ViaCEP(FormatStringUtil.CaracterClear(responseReceita.CEP));

                if (responseViaCep == null)
                {
                    return(StatusCode(400, "Ocorreu um erro na busca do endereço da Empresa, tente novamente mais tarde."));
                }

                var UfSiglaDb = _enderecoRepository.GetUfSiglaBySigla(responseViaCep.UfSigla);

                if (UfSiglaDb == null)
                {
                    return(StatusCode(400, "Não existe UF's necessárias cadastradas no banco de dados, não é possível prosseguir com o cadastro da empresa."));
                }

                var municipioDb = _enderecoRepository.GetMunicipioByDescricao(responseViaCep.Localidade);

                // Cria um novo município caso não encontre já criado no banco de dados.
                if (municipioDb == null)
                {
                    try
                    {
                        municipioDb = new Municipio(responseViaCep.Localidade, UfSiglaDb.Id);

                        municipioDb = _enderecoRepository.CreateMunicipio(municipioDb);
                    }
                    catch (Exception)
                    {
                        return(StatusCode(500, "Houve um erro interno ao criar um novo município no banco de dados para a Empresa."));
                    }
                }

                // Verifica quais campos que não estão vazios para criar o endereço
                string logradouroPreenchido = string.IsNullOrEmpty(responseViaCep.Logradouro) == false ? responseViaCep.Logradouro : responseReceita.Logradouro;
                string bairroPreenchido     = string.IsNullOrEmpty(responseViaCep.Bairro) == false ? responseViaCep.Bairro : responseReceita.Bairro;

                // Cria novo endereço para a Empresa
                Endereco endereco = null;
                try
                {
                    endereco = new Endereco(responseViaCep.Cep, bairroPreenchido, logradouroPreenchido, responseReceita.Numero, municipioDb.Id);
                }
                catch (Exception)
                {
                    return(StatusCode(500, "Houve um erro interno criar um endereço para a Empresa."));
                }

                var enderecoDb = _enderecoRepository.Create(endereco);

                #endregion

                // Verifica se fantasia esta nula e substitui por nome, caso contrário, mantem fantasia
                string nomeEmpresa = string.IsNullOrEmpty(responseReceita.Fantasia) ? responseReceita.Nome : responseReceita.Fantasia;

                // Cria Empresa
                empresaDb = null;
                try
                {
                    empresaDb = new Empresa(input.Cnpj, nomeEmpresa, enderecoDb.Id, tipoEmpresa.Id);
                }
                catch (Exception)
                {
                    return(StatusCode(500, "Houve um erro interno ao criar uma Empresa."));
                }

                // Cria Empresa no BD
                empresaDb = _empresaRepository.Create(empresaDb);

                #region Registra todos os TiposCnaes (Atividade Principal e Atividade Secundária)

                // Default Values Atividade principal e secundária
                var AtividadePrincipalDb  = _tipoAtividadeCnaeRepository.GetByDescricao(TipoAtividadeCnaeDefaultValuesAccess.GetValue(TipoAtividadeCnaeDefaultValues.AtividadePrincipal));
                var AtividadeSecundariaDb = _tipoAtividadeCnaeRepository.GetByDescricao(TipoAtividadeCnaeDefaultValuesAccess.GetValue(TipoAtividadeCnaeDefaultValues.AtividadeSecundaria));

                // Atividade Principal
                TipoCnae tipoCnaeDb = null;

                if (responseReceita.AtividadePrincipal.Any())
                {
                    foreach (var ap in responseReceita.AtividadePrincipal)
                    {
                        tipoCnaeDb = _empresaRepository.GetTipoCnaeByCodigo(ap.Code);

                        if (tipoCnaeDb == null)
                        {
                            try
                            {
                                tipoCnaeDb = new TipoCnae(ap.Text, ap.Code);

                                tipoCnaeDb = _empresaRepository.CreateTipoCnae(tipoCnaeDb);
                            }
                            catch (Exception)
                            {
                                return(StatusCode(500, "Houve um erro interno ao criar a Atividade Principal da Empresa, tente novamente mais tarde."));
                            }
                        }

                        AtividadeCnae atividadeCnae = null;
                        try
                        {
                            atividadeCnae = new AtividadeCnae(tipoCnaeDb.Id, AtividadePrincipalDb.Id, empresaDb.Id);

                            _empresaRepository.CreateAtividadeCnae(atividadeCnae);
                        }
                        catch (Exception)
                        {
                            return(StatusCode(500, "Houve um erro interno ao vincular o CNAE à Empresa, tente novamente mais tarde."));
                        }
                    }
                }

                // Atividades Secundárias
                if (responseReceita.AtividadeSecundaria.Any())
                {
                    foreach (var ats in responseReceita.AtividadeSecundaria)
                    {
                        tipoCnaeDb = _empresaRepository.GetTipoCnaeByCodigo(ats.Code);

                        if (tipoCnaeDb == null)
                        {
                            try
                            {
                                tipoCnaeDb = new TipoCnae(ats.Text, ats.Code);

                                tipoCnaeDb = _empresaRepository.CreateTipoCnae(tipoCnaeDb);
                            }
                            catch (Exception)
                            {
                                return(StatusCode(500, "Houve um erro interno ao criar alguma Atividade Secundária da Empresa, tente novamente mais tarde."));
                            }
                        }

                        AtividadeCnae atividadeCnae = null;
                        try
                        {
                            atividadeCnae = new AtividadeCnae(tipoCnaeDb.Id, AtividadeSecundariaDb.Id, empresaDb.Id);

                            _empresaRepository.CreateAtividadeCnae(atividadeCnae);
                        }
                        catch (Exception)
                        {
                            return(StatusCode(500, "Houve um erro interno ao vincular o CNAE à Empresa, tente novamente mais tarde."));
                        }
                    }
                }

                #endregion

                // Registra todos da lista de QSA
                if (responseReceita.QSA.Any())
                {
                    foreach (var qsa in responseReceita.QSA)
                    {
                        QSA qsaDb = null;
                        try
                        {
                            qsaDb = new QSA(qsa.Nome, qsa.Qual, empresaDb.Id);

                            _empresaRepository.CreateQSA(qsaDb);
                        }
                        catch (Exception)
                        {
                            return(StatusCode(500, "Houve um erro interno ao criar o QSA da Empresa."));
                        }
                    }
                }
                #endregion
            }
            else
            {
                #region Caso empresa já exista
                var usuarioEmpresaDb = _usuarioEmpresaRepository.GetByEmpresaId(empresaDb.Id);

                // Verifica se já existe um usuário vinculado à empresa
                if (usuarioEmpresaDb != null)
                {
                    return(StatusCode(400, $"A Empresa de CNPJ [{input.Cnpj}] já está vinculada à um usuário."));
                }
                #endregion
            }

            var tipoEmpresaDb   = _tipoUsuarioRepository.GetByDescricao(TipoUsuarioDefaultValuesAccess.GetValue(TipoUsuarioDefaultValues.Empresa));
            var statusUsuarioDb = _statusUsuarioRepository.GetByDescricao(StatusUsuarioDefaultValuesAcess.GetValue(StatusUsuarioDefaultValues.ContaAtiva));

            // Criação do usuário
            usuarioDb = null;
            try
            {
                // Gera Hash da senha
                var senhaHash = new PasswordHasher <Usuario>().HashPassword(usuarioDb, input.Senha);

                usuarioDb = new Usuario(input.Nome, input.Email, senhaHash, tipoEmpresaDb.Id);
            }
            catch (Exception)
            {
                return(StatusCode(500, "Houve um erro interno ao criar o Usuário."));
            }

            usuarioDb = _usuarioRepository.Create(usuarioDb);

            // Cria o 1° histórico do usuário
            HistoricoStatusUsuario historicoUsuario = null;
            try
            {
                historicoUsuario = new HistoricoStatusUsuario(statusUsuarioDb.Id, usuarioDb.Id);
            }
            catch (Exception)
            {
                return(StatusCode(500, "Houve um erro interno ao criar o histórico do usuário."));
            }

            _historicoStatusUsuarioRepository.Create(historicoUsuario);

            // Criação do UsuarioEmpresa, vincula o usuário à empresa criada
            UsuarioEmpresa usuarioEmpresa = null;
            try
            {
                usuarioEmpresa = new UsuarioEmpresa(empresaDb.Id, usuarioDb.Id);
            }
            catch (Exception)
            {
                return(StatusCode(500, "Houve um erro interno ao criar o UsuarioEmpresa (vincular o usuário à empresa)."));
            }

            _usuarioEmpresaRepository.Create(usuarioEmpresa);

            await _usuarioRepository.UnitOfWork.SaveDbChanges();

            return(StatusCode(200, $"Usuário {usuarioDb.Email} com perfil de Empresa com CNPJ {empresaDb.CNPJ} criado com sucesso!"));
        }