package ejb.visit;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import TO.VisitTO;
import ejb.common.CommonFacadeLocal;
import jpa.PatientJPA;
import jpa.VisitJPA;

/**
 * EJB Session Bean Class para la Practica 2, Ejercicio 1 (ISCSD) Implementa los métodos de la capa de negocio que implementan la logica de negocio y la interacción con la capa de
 * persistencia.
 * 
 * @author mark
 *
 */
@Stateless
public class VisitFacadeBean implements VisitFacadeRemote {
	// Persistence Unit Context
	@PersistenceContext(unitName = "MyHealth")
	EntityManager entman;

	@EJB
	CommonFacadeLocal commonServices;

	public Long getScheduledVisitsCount(int familyDoctorId, LocalDate date) {
		TypedQuery<Long> query = entman.createQuery("SELECT count(1) from VisitJPA v where v.date=:date and v.familyDoctor.id=:docId", Long.class);
		query.setParameter("date", date);
		query.setParameter("docId", familyDoctorId);

		return query.getSingleResult();
	}

	public List<VisitTO> listAllScheduledVisitsPaged(int familyDoctorId, LocalDate date, int pageNumber, int pageSize) {
		TypedQuery<VisitJPA> query = entman.createQuery("SELECT v from VisitJPA v where v.date=:date and v.familyDoctor.id=:docId order by v.date, v.time", VisitJPA.class);
		query.setParameter("date", date);
		query.setParameter("docId", familyDoctorId);

		if (pageSize > 0) {
			query.setFirstResult(pageNumber * pageSize);
			query.setMaxResults(pageSize);
		}

		List<VisitJPA> allJPA = query.getResultList();
		List<VisitTO> listTO = new ArrayList<VisitTO>();

		for (VisitJPA item : allJPA) {
			listTO.add(commonServices.getPOJOforVisitJPA(item, 1));
		}

		return listTO;
	}

	public Long getVisitsCount(Integer patientId, LocalDate date) {
		String strQuery = "SELECT count(1) from VisitJPA v %s";
		String strFilter = "";
		if (patientId != null)
			strFilter = " and v.patient.id=:patientId ";
		if (date != null)
			strFilter += " and v.date=:date ";

		if (strFilter.length() > 0) {
			strFilter = "WHERE 1=1 " + strFilter;
		}
		strQuery = String.format(strQuery, strFilter);

		TypedQuery<Long> query = entman.createQuery(strQuery, Long.class);

		if (patientId != null)
			query.setParameter("patientId", patientId);
		if (date != null)
			query.setParameter("date", date);

		return query.getSingleResult();
	}

	public List<VisitTO> listVisitsPaged(Integer patientId, LocalDate date, int pageNumber, int pageSize) {
		String strQuery = "SELECT v from VisitJPA v %s order by v.patient, v.date";
		String strFilter = "";
		if (patientId != null)
			strFilter = " and v.patient.id=:patientId ";
		if (date != null)
			strFilter += " and v.date=:date ";

		if (strFilter.length() > 0) {
			strFilter = "WHERE 1=1 " + strFilter;
		}
		strQuery = String.format(strQuery, strFilter);

		TypedQuery<VisitJPA> query = entman.createQuery(strQuery, VisitJPA.class);

		if (patientId != null)
			query.setParameter("patientId", patientId);
		if (date != null)
			query.setParameter("date", date);

		if (pageSize > 0) {
			query.setFirstResult(pageNumber * pageSize);
			query.setMaxResults(pageSize);
		}

		List<VisitJPA> allJPA = query.getResultList();
		List<VisitTO> listTO = new ArrayList<VisitTO>();

		for (VisitJPA item : allJPA) {
			listTO.add(commonServices.getPOJOforVisitJPA(item, 1));
		}

		return listTO;
	}

	public VisitTO getVisit(int id) throws Exception {
		VisitJPA vi = entman.find(VisitJPA.class, id);
		if (vi == null) {
			throw new Exception("No se encuentra la visita con identificador: " + String.valueOf(id));
		}

		return this.commonServices.getPOJOforVisitJPA(vi, 1);
	}

	public void addResultToVisit(int id, String result) {
		VisitJPA vi = entman.find(VisitJPA.class, id);

		vi.setResult(result);
		entman.persist(vi);
	}

	public void removeVisit(int id) {
		VisitJPA vi = entman.find(VisitJPA.class, id);
		entman.remove(vi);
	}

	public void updateVisit(int id, LocalDate date, LocalTime time) {
		VisitJPA vi = entman.find(VisitJPA.class, id);
		vi.setDate(date);
		vi.setTime(time);
		entman.persist(vi);
	}

	public VisitTO addVisit(int patientId, LocalDate date, LocalTime time, String observations) {

		PatientJPA pat = entman.find(PatientJPA.class, patientId);

		VisitJPA vi = new VisitJPA(date, time, observations, "", pat, pat.getFamilyDoctor());
		entman.persist(vi);

		return this.commonServices.getPOJOforVisitJPA(vi, 1);
	}
}
