public ResultResponse<EnvioOcorrenciasResult> Post([FromBody]ReporteOcorrenciasMatricula ocorrencias)
        {
            ResultResponse<EnvioOcorrenciasResult> resposta = new ResultResponse<EnvioOcorrenciasResult>();

            //List<ValorSistema> paramSistema = valoresSistemaRepository.All.Where(v => v.tipologia == "ESTADO_EVENTO_STAGGING"
            //                                                                    || v.tipologia == "OPERACAO_EVENTO"
            //                                                                    || v.tipologia == "PARAM_PASTA_FICHEIROS").ToList();
            //List<ValorSistema> estadosEvento = paramSistema.Where(v => v.tipologia == "ESTADO_EVENTO_STAGGING").ToList();
            //List<ValorSistema> operacoesEvento = paramSistema.Where(v => v.tipologia == "OPERACAO_EVENTO").ToList();
            //ValorSistema pastaUpload = paramSistema.Where(v => v.tipologia == "PARAM_PASTA_FICHEIROS").Single();

            List<ValorSistema> estadosEvento = valoresSistemaRepository.GetPorTipologia("ESTADO_EVENTO_STAGGING");
            List<ValorSistema> operacoesEvento = valoresSistemaRepository.GetPorTipologia("OPERACAO_EVENTO");
            ValorSistema pastaUpload = valoresSistemaRepository.GetPorTipologia("PARAM_PASTA_FICHEIROS").Single();

            
            if (ocorrencias == null || ocorrencias.Ocorrencia == null)
            {
                resposta.Success = false;
                resposta.ErrorMessage = "Erro na recepção de ocorrências. Mensagem mal formada.";
            }

            UserProfile user = null;

            if (WebSecurity.IsAuthenticated)
            {
                user = usersRepository.GetUserByIDIncludeEntidade(WebSecurity.CurrentUserId);
            }
            else
            {
                string username = string.Empty;

                IEnumerable<string> headerVals;
                if (Request.Headers.TryGetValues("Authorization", out headerVals))
                {
                    string authHeader = headerVals.FirstOrDefault();
                    char[] delims = { ' ' };
                    string[] authHeaderTokens = authHeader.Split(new char[] { ' ' });
                    if (authHeaderTokens[0].Contains("Basic"))
                    {
                        string decodedStr = BasicAuthorizeAttribute.DecodeFrom64(authHeaderTokens[1]);
                        string[] unpw = decodedStr.Split(new char[] { ':' });
                        username = unpw[0];
                    }
                    else
                    {
                        if (authHeaderTokens.Length > 1)
                            username = BasicAuthorizeAttribute.DecodeFrom64(authHeaderTokens[1]);
                    }
                }

                user = usersRepository.GetUserByUsernameIncludeEntidade(username);
            }

            if (user == null)
            {
                resposta.Success = false;
                resposta.ErrorMessage += "Erro de autenticação.";
            }

            var root = System.Configuration.ConfigurationManager.AppSettings["FilesUploadDestination"];
            //string root = System.Web.HttpContext.Current.Server.MapPath(destination);
            var provider = new MultipartFormDataStreamProvider(root);

            if (resposta.Success == false)
            {
                return resposta;
            }

            DateTime dataRecepcao = DateTime.Now;

            ReporteOcorrenciasFNMPAS reporteOcorrenciasFNMPAS = new ReporteOcorrenciasFNMPAS(ocorrencias);
            reporteOcorrenciasFNMPAS.ordenaOcorrencias();

            int nrOcorrencias = 0;
            for (int i = 0; i < reporteOcorrenciasFNMPAS.OcorrenciaOrdenada.Count(); i++)
            {
                ReporteOcorrenciasMatriculaOcorrenciaOrdenada ocorrencia = reporteOcorrenciasFNMPAS.OcorrenciaOrdenada[i];

                //evento Duplicado e esmagado com os novos dados. (C M - stagging/producao) (A - producao/stagging) 
                //Não foi ainda inserido na Base de dados nem houve delete logico do anterior. 
                //Fazer deletes logicos, e inserções após verificações.
                //Anulações podem necessitar logica adicional caso a validação falhe. (duplicar registo em stagging)
                EventoStagging evento = new EventoStagging();

                int codigoOperacaoId = 0;
                switch (ocorrencia.CodigoOperacao)
                {
                    case ReporteOcorrenciasMatriculaOcorrenciaCodigoOperacao.C: codigoOperacaoId = operacoesEvento.Where(o => o.valor == "C").Single().valorSistemaId; break;
                    case ReporteOcorrenciasMatriculaOcorrenciaCodigoOperacao.M: codigoOperacaoId = operacoesEvento.Where(o => o.valor == "M").Single().valorSistemaId; break;
                    case ReporteOcorrenciasMatriculaOcorrenciaCodigoOperacao.A: codigoOperacaoId = operacoesEvento.Where(o => o.valor == "A").Single().valorSistemaId; break;
                    default: codigoOperacaoId = operacoesEvento.Where(o => o.valor == "C").Single().valorSistemaId; break;
                }

                Ficheiro ficheiroVirtual = new Ficheiro { dataAlteracao = dataRecepcao, dataUpload = dataRecepcao, entidadeId = user.entidadeId };

                evento.esmagaDados(ocorrencia, ficheiroVirtual, codigoOperacaoId);
                evento.utilizadorReporte = user.UserName;

                evento.estadoEventoId = estadosEvento.Where(e => e.valor == "PENDENTE").Single().valorSistemaId;

                eventosStaggingRepository.InsertOrUpdate(evento);
                nrOcorrencias++;
            }

                eventosStaggingRepository.Save();
                resposta.Success = true;
                resposta.Result = new EnvioOcorrenciasResult { dataRecepcao = dataRecepcao, nrOcorrencias = nrOcorrencias, seguradora = user.entidade.nome };
            
            return resposta;
        }
        public static void processaFicheiro(Ficheiro ficheiro){

            ValorSistemaRepository valoresSistemaRepository = new ValorSistemaRepository();

            //List<ValorSistema> valSistema = valoresSistemaRepository.All.Where(v => v.tipologia == "ESTADO_EVENTO_STAGGING" || v.tipologia == "OPERACAO_EVENTO").ToList();

            //List<ValorSistema> estadosEvento = valSistema.Where(v => v.tipologia == "ESTADO_EVENTO_STAGGING").ToList();
            //List<ValorSistema> operacoesEvento = valSistema.Where(v => v.tipologia == "OPERACAO_EVENTO").ToList();

            List<ValorSistema> estadosEvento = valoresSistemaRepository.GetPorTipologia("ESTADO_EVENTO_STAGGING");
            List<ValorSistema> operacoesEvento = valoresSistemaRepository.GetPorTipologia("OPERACAO_EVENTO");
            List<ValorSistema> tiposErro = valoresSistemaRepository.GetPorTipologia("TIPO_ERRO");
            List<ValorSistema> estadosFicheiro = valoresSistemaRepository.GetPorTipologia("ESTADO_FICHEIRO");

            ReporteOcorrenciasMatricula reporte;

            XmlSerializer serializer = new XmlSerializer(typeof(ReporteOcorrenciasMatricula));
            using (FileStream fileStream = new FileStream(ficheiro.localizacao, FileMode.Open))
            {
                reporte = (ReporteOcorrenciasMatricula)serializer.Deserialize(fileStream);
            }

            if (reporte.Cabecalho.CodigoEstatistico != ficheiro.entidade.codigoEntidade)
            {
                ErroFicheiro erroFicheiro = new ErroFicheiro(){ dataValidacao = DateTime.Now, 
                                                                tipologiaId = tiposErro.Single(e => e.valor == "GENERICO").valorSistemaId,
                                                                descricao = "Ficheiro reportado pela entidade com código '" + ficheiro.entidade.codigoEntidade + "' e com registos relativos à entidade '" + reporte.Cabecalho.CodigoEstatistico + "'.",
                                                                ficheiroId = ficheiro.ficheiroId };

                ErroFicheiroException ex = new ErroFicheiroException();
                ex.errosFicheiro.Add(erroFicheiro);

                throw ex;
            }

            ReporteOcorrenciasFNMPAS reporteOcorrenciasFNMPAS = new ReporteOcorrenciasFNMPAS(reporte);
            reporteOcorrenciasFNMPAS.ordenaOcorrencias();
           

            for (int i = 0; i < reporteOcorrenciasFNMPAS.OcorrenciaOrdenada.Count(); i++)
            {
                ReporteOcorrenciasMatriculaOcorrenciaOrdenada ocorrencia = reporteOcorrenciasFNMPAS.OcorrenciaOrdenada[i];

                //evento Duplicado e esmagado com os novos dados. (C M - stagging/producao) (A - producao/stagging) 
                //Não foi ainda inserido na Base de dados nem houve delete logico do anterior. 
                //Fazer deletes logicos, e inserções após verificações.
                //Anulações podem necessitar logica adicional caso a validação falhe. (duplicar registo em stagging)
                EventoStagging evento = new EventoStagging();
                
                int codigoOperacaoId = 0;
                switch (ocorrencia.CodigoOperacao)
                {
                    case ReporteOcorrenciasMatriculaOcorrenciaCodigoOperacao.C: codigoOperacaoId = operacoesEvento.Where(o=> o.valor =="C").Single().valorSistemaId; break;
                    case ReporteOcorrenciasMatriculaOcorrenciaCodigoOperacao.M: codigoOperacaoId = operacoesEvento.Where(o=> o.valor =="M").Single().valorSistemaId; break;
                    case ReporteOcorrenciasMatriculaOcorrenciaCodigoOperacao.A: codigoOperacaoId = operacoesEvento.Where(o=> o.valor =="A").Single().valorSistemaId; break;
                    default: codigoOperacaoId = operacoesEvento.Where(o => o.valor == "C").Single().valorSistemaId; break;
                }
                evento.esmagaDados(ocorrencia, ficheiro, codigoOperacaoId);

                evento.estadoEventoId = estadosEvento.Where(e => e.valor == "PENDENTE").Single().valorSistemaId;

                ficheiro.eventosStagging.Add(evento);
            }

            //EventoStaggingRepository eventosStaggingRepository = new EventoStaggingRepository();
            //eventosStaggingRepository.InsertOrUpdate(evento);
            //eventosStaggingRepository.Save();
        }
        public static EventoStagging criarEventoStagging(EventoStagging eventoPendente, Mutex mutex = null)
        {
            ValorSistemaRepository valoresSistemaRepository = new ValorSistemaRepository();
            List<ValorSistema> tiposErro = valoresSistemaRepository.GetPorTipologia("TIPO_ERRO", mutex);

            EventoStagging novoEvento = null;

            if (eventoPendente.codigoOperacao == null)
            {
                throw new ErroEventoStaggingException { errosEventoStagging = new List<ErroEventoStagging> { new ErroEventoStagging { campo = "CodigoOperacao", descricao = "Código de Operação Inválido", tipologiaId = tiposErro.Where(e => e.valor == "GENERICO").Single().valorSistemaId } } };
            }

            try
            {              
                novoEvento = EventoStaggingFactory.duplicarEventoStagging(eventoPendente.matricula, (int)eventoPendente.entidadeId, eventoPendente.dataInicioCobertura, eventoPendente.horaInicioCobertura, eventoPendente.codigoOperacao, mutex);

                //Caso não exista registo em stagging duplica-se o Registo em Producao               
                //novoEvento = EventoStaggingFactory.duplicarEventoProducao(eventoPendente.matricula, (int)eventoPendente.entidadeId, eventoPendente.dataInicioCobertura, eventoPendente.horaInicioCobertura);
                
                //Caso este também não exista, trata-se de uma nova ocorrência.
                //Poderiamos concluir que se não é uma criação é um erro, mas validemos isto juntamente com as validações de negócio.
                if (novoEvento == null)
                {
                    novoEvento = new EventoStagging();

                    if (eventoPendente.ficheiroID != null)
                    {
                        novoEvento.dataReporte = eventoPendente.ficheiro.dataAlteracao;
                        novoEvento.dataUltimaAlteracaoErro = eventoPendente.ficheiro.dataAlteracao;
                    }
                }
            }
            catch (ErroEventoStaggingException erros)
            {
                novoEvento = new EventoStagging();
                if (eventoPendente.ficheiroID != null)
                {
                    novoEvento.dataReporte = eventoPendente.ficheiro.dataAlteracao;
                    novoEvento.dataUltimaAlteracaoErro = eventoPendente.ficheiro.dataAlteracao;
                }
                
                foreach (ErroEventoStagging erro in erros.errosEventoStagging)
                {
                    erro.eventoStagging = novoEvento;
                    novoEvento.errosEventoStagging.Add(erro);
                }
            }

            novoEvento.esmagaDados(eventoPendente);

            return novoEvento;
        }