class VerificarPrescricaoON extends BaseBusiness {

	@SuppressWarnings({"PMD.ExcessiveMethodLength", "PMD.NPathComplexity"})
	public Object criarPrescricao(
			final AghAtendimentos atendimento, Date dataReferencia, String nomeMicrocomputador)
			throws BaseException {
		
		RapServidores servidorLogado = getServidorLogadoFacade().obterServidorLogado();

		
		if (atendimento == null) {
			throw new IllegalArgumentException("Atendimento não informado.");
		}
		
		// Serializa criação de prescrições sobre o mesmo atendimento
		getAghuFacade().refreshAndLock(atendimento);
		
		AghUnidadesFuncionais unidadeFuncional = atendimento.getUnidadeFuncional();
		getAghuFacade().refreshUnidadesFuncionais(unidadeFuncional);

		// utiliza a mesma data durante toda a transação
		Date dataAtual = getDataAtual();
		
		RedirectVO redirectVO = validarPrescricaoMedica(atendimento);
		if(redirectVO != null) {
			return redirectVO;
		}
		
		verificarCriarPrescricao(atendimento, dataAtual);
		
		// Calcula data de início e data de fim

		if (dataReferencia == null) {
			dataReferencia = obterDataReferenciaProximaPrescricao(atendimento,
					dataAtual);
		}

		Date horaValidadePME = unidadeFuncional.getHrioValidadePme();

		Date dthrFim = DateUtil.comporDiaHora(DateUtil.adicionaDias(
				dataReferencia, +1), horaValidadePME);

		Date dthrInicio = (Date) ObjectUtils.max(DateUtil.adicionaDias(dthrFim,
				-1), dataAtual);
		
		List<MpmPrescricaoMedica> prescricoes;
		prescricoes = getMpmPrescricaoMedicaDAO().prescricoesAtendimentoDataFim(
				atendimento, dataAtual
		);
		
		MpmPrescricaoMedica ultimaPrescricaoDia = obterUltimaPrescricaoDoDia(
				prescricoes, dataReferencia
		);
		
		if (ultimaPrescricaoDia != null && ultimaPrescricaoDia.getDthrFim().compareTo(dthrInicio) < 0) {
			// Isto ocorre quando há alteração na hora de validade da prescição (geralmente por troca de unidade funcional)
			// Neste caso, deve-se criar uma prescrição para preencher o horário entre o fim da prescrição anterior e o que 
			// seria o início da nova prescrição.
			dthrFim = dthrInicio;
			dthrInicio = ultimaPrescricaoDia.getDthrFim();
		}
		
		// ORADB MPMK_PME_RN.RN_PMEP_VER_DTHR_FIM
		if (dthrFim.compareTo(dataAtual) < 0) {
			throw new ApplicationBusinessException(ExceptionCode.PRESCRICAO_NO_PASSADO);
		}

		validarAdiantamento(unidadeFuncional, dataAtual, dthrInicio);

		// Validar se já existe prescrição neste período

		for (MpmPrescricaoMedica prescricao : prescricoes) {
			if (prescricao.getDthrFim().compareTo(dthrFim) < 0
					&& prescricao.getDthrFim().compareTo(dthrInicio) > 0) {
				dthrInicio = prescricao.getDthrFim();
			}
			if (prescricao.getDthrInicio().compareTo(dthrFim) < 0
					&& prescricao.getDthrInicio().compareTo(dthrInicio) > 0) {
				dthrFim = prescricao.getDthrInicio();
			}
			if (prescricao.getDthrInicio().compareTo(dthrInicio) >= 0
					&& prescricao.getDthrFim().compareTo(dthrFim) <= 0) {
				throw new ApplicationBusinessException(
						ExceptionCode.PRESCRICOES_SOBREPOSTAS);
			}
		}
		if (dthrInicio.compareTo(dthrFim) >= 0) {
			throw new ApplicationBusinessException(
					ExceptionCode.PRESCRICOES_SOBREPOSTAS);
		}
		
		// Verificar Prescrição Consecutiva
		if (aghuFacade.possuiCaracteristicaPorUnidadeEConstante(unidadeFuncional.getSeq(), ConstanteAghCaractUnidFuncionais.PME_CONSECUTIVA) && ultimaPrescricaoDia == null
				&& dthrInicio.compareTo(dataAtual) > 0) {
			throw new ApplicationBusinessException(ExceptionCode.PRESCRICAO_CONSECUTIVA_NAO_ENCONTRADA);
		}
		
		validaDataFimAtendimento(atendimento, dthrFim, dthrInicio);
			
		// Tudo ok. Cria nova prescrição.

		MpmPrescricaoMedica novaPrescricao = new MpmPrescricaoMedica();
		novaPrescricao.setId(new MpmPrescricaoMedicaId(atendimento.getSeq(),
				getMpmPrescricaoMedicaDAO().obterValorSequencialId()));

		novaPrescricao.setCriadoEm(dataAtual);
		novaPrescricao.setDthrMovimento(dataAtual); // mpmk_pme_rn.rn_pmep_ver_dthr_ini
		novaPrescricao.setSituacao(DominioSituacaoPrescricao.U);
		novaPrescricao.setServidor(servidorLogado);
		novaPrescricao.setServidorAtualizada(servidorLogado);
		novaPrescricao.setDthrInicio(dthrInicio);
		novaPrescricao.setDthrFim(dthrFim);
		novaPrescricao.setDtReferencia(dataReferencia);
		novaPrescricao.setAtendimento(atendimento);

		getMpmPrescricaoMedicaDAO().persistir(novaPrescricao);
		getMpmPrescricaoMedicaDAO().flush();

		// Copiar itens da prescrição anterior
		copiarPrescricao(
				novaPrescricao, 
				possuiPrescricaoFutura(dataReferencia, prescricoes), nomeMicrocomputador
		);
		
		//getAghuFacade().flush();

		gerarLogPrescricaoEmUso(novaPrescricao, "Inclusão");	
				
		getPrescricaoMedicaRN().atualizarFaturamento( novaPrescricao, null, DominioOperacaoBanco.INS, nomeMicrocomputador, new Date());

		return novaPrescricao;

	}

}