package com.jasamedika.medifirst2000.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.naming.CommunicationException;
import javax.persistence.EntityManager;

import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jasamedika.medifirst2000.vo.AntrianPasienDiPeriksaVO;
import com.jasamedika.medifirst2000.vo.AsalRujukanVO;
import com.jasamedika.medifirst2000.vo.DetailRencanaOperasiVO;
import com.jasamedika.medifirst2000.vo.JenisOperasiVO;
import com.jasamedika.medifirst2000.vo.JenisPetugasPelaksanaVO;
import com.jasamedika.medifirst2000.vo.KamarVO;
import com.jasamedika.medifirst2000.vo.LoginUserVO;
import com.jasamedika.medifirst2000.vo.PasienDaftarVO;
import com.jasamedika.medifirst2000.vo.PasienVO;
import com.jasamedika.medifirst2000.vo.PegawaiVO;
import com.jasamedika.medifirst2000.vo.RencanaOperasiCustomVO;
import com.jasamedika.medifirst2000.entities.AntrianPasienDiPeriksa;
import com.jasamedika.medifirst2000.entities.AsalRujukan;
import com.jasamedika.medifirst2000.entities.DetailRencanaOperasi;
import com.jasamedika.medifirst2000.entities.JenisOperasi;
import com.jasamedika.medifirst2000.entities.JenisPetugasPelaksana;
import com.jasamedika.medifirst2000.entities.Kamar;
import com.jasamedika.medifirst2000.entities.LoginUser;
import com.jasamedika.medifirst2000.entities.Pasien;
import com.jasamedika.medifirst2000.entities.PasienDaftar;
import com.jasamedika.medifirst2000.entities.Pegawai;
import com.jasamedika.medifirst2000.exception.ServiceVOException;
import com.jasamedika.medifirst2000.service.AntrianPasienDiPeriksaService;
import com.jasamedika.medifirst2000.service.RencanaOperasiService;
import com.jasamedika.medifirst2000.service.StrukOrderService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.JsonUtil;
import com.jasamedika.medifirst2000.entities.RencanaOperasi;
import com.jasamedika.medifirst2000.entities.Ruangan;
import com.jasamedika.medifirst2000.entities.StrukOrder;
import com.jasamedika.medifirst2000.entities.responterhadapoperasi;
import com.jasamedika.medifirst2000.enums.StatusAntrianEnum;
import com.jasamedika.medifirst2000.vo.RencanaOperasiVO;
import com.jasamedika.medifirst2000.vo.RuanganVO;
import com.jasamedika.medifirst2000.vo.StrukOrderVO;
import com.jasamedika.medifirst2000.vo.rujukanVO;
//import com.jasamedika.medifirst2000.converter.AsalRujukanConverter;
import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.converter.KelasConverter;
import com.jasamedika.medifirst2000.dao.AntrianPasienDiPeriksaDao;
import com.jasamedika.medifirst2000.dao.DetailRencanaOperasiDao;
import com.jasamedika.medifirst2000.dao.RencanaOperasiDao;
import com.jasamedika.medifirst2000.dao.StrukOrderDao;
import com.jasamedika.medifirst2000.dto.AntrianPasien;

/**
 * Implement class for RencanaOperasiService
 * 
 * @author Generator
 * @param <T>
 */
@Service("rencanaOperasiService")
public class RencanaOperasiServiceImpl extends BaseVoServiceImpl implements RencanaOperasiService {
	@Autowired
	private BaseConverterImpl<RencanaOperasiVO, RencanaOperasi> rencanaOperasiConverter;
	
	@Autowired
	private BaseConverterImpl<AsalRujukanVO, AsalRujukan> asalRujukanConverter;
		
	@Autowired
	private DetailRencanaOperasiDao detailRencanaOperasiDao;
	
	@Autowired
	private AntrianPasienDiPeriksaDao antrianPasienDiPeriksaDao;
	
	@Autowired
	private AntrianPasienDiPeriksaService antrianPasienDiperiksaService;
	
	@Autowired
	private StrukOrderService strukOrderService;
	
	@Autowired
	private StrukOrderDao strukOrderDao;
	
	@Autowired
	private RencanaOperasiDao rencanaOperasiDao;
	
	@Autowired
	private AntrianPasienDiPeriksaService antrianPasienDiPeriksaService;
	
	@Autowired
	private BaseConverterImpl<DetailRencanaOperasiVO, DetailRencanaOperasi> detailRencanaOperasiConverter;
	
	@Autowired
	private BaseConverterImpl<AntrianPasienDiPeriksaVO, AntrianPasienDiPeriksa> antrianPasienDiPeriksaConverter;
	
	@Autowired
	private BaseConverterImpl<PegawaiVO, Pegawai> pegawaiConverter;
	
	@Autowired
	private BaseConverterImpl<PasienDaftarVO, PasienDaftar> pasienDaftarConverter;
	
	@Autowired
	private BaseConverterImpl<PasienVO, Pasien> pasienConverter;
	
	@Autowired
	private BaseConverterImpl<KamarVO, Kamar> kamarConverter;
	
	@Autowired
	private BaseConverterImpl<StrukOrderVO, StrukOrder> strukOrderConverter;
	
	@Autowired
	private BaseConverterImpl<JenisOperasiVO, JenisOperasi> jenisOperasiConverter;
	
	@Autowired
	private BaseConverterImpl<RuanganVO, Ruangan> ruanganConverter;

	@Autowired
	private BaseConverterImpl<JenisPetugasPelaksanaVO, JenisPetugasPelaksana> jenisPetugasPelaksanaConverter;

	@Override
	public Map<String, Object> saveRencanaOperasi(RencanaOperasiVO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		RencanaOperasi model = new RencanaOperasi();
		model = rencanaOperasiConverter.transferVOToModel(vo, model);
		model.getDetailPelaksana().clear();
		if (CommonUtil.isNotNullOrEmpty(vo.getNoCm())) {
			model.setNoCm(
					antrianPasienDiPeriksaConverter.transferVOToModel(vo.getNoCm(), new AntrianPasienDiPeriksa()));
		}
		RencanaOperasi resultDomain = rencanaOperasiDao.save(model);
		for (DetailRencanaOperasiVO item : vo.getDetailPelaksana()) {
			DetailRencanaOperasi modelItem = new DetailRencanaOperasi();
			modelItem = detailRencanaOperasiConverter.transferVOToModel(item, modelItem);
			modelItem.setRencanaOperasi(resultDomain);
			/*if (CommonUtil.isNotNullOrEmpty(item.getPegawai())) {
				modelItem.setPegawai(pegawaiConverter.transferVOToModel(item.getPegawai(), new Pegawai()));
			}
			if (CommonUtil.isNotNullOrEmpty(item.getJenisPelaksana())) {
				modelItem.setJenisPelaksana(jenisPetugasPelaksanaConverter.transferVOToModel(item.getJenisPelaksana(),
						new JenisPetugasPelaksana()));
			}*/

			DetailRencanaOperasi resultDomainItem = detailRencanaOperasiDao.save(modelItem);
			if (CommonUtil.isNotNullOrEmpty(resultDomain)) {
				result.put("noRec", resultDomain.getNoRec());
			}
		}

		if (CommonUtil.isNotNullOrEmpty(resultDomain)) {
			result.put("noRec", resultDomain.getNoRec());
		}

		return result;
	}

	@Override
	public Map<String, Object> findByName(String nama) {
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("items", JsonUtil.ToMaps(rencanaOperasiDao.findAll()));
		return result;
	}
	
	@Override
	public Map<String, Object> saveRencanaOperasiNew(RencanaOperasiCustomVO vo) {
		
		Map<String, Object> result = new HashMap<String, Object>();
		Map<String, Object> data = new HashMap<String, Object>();
		if(CommonUtil.isNotNullOrEmpty(vo))
		{
			RencanaOperasiVO temp = vo.getRencanaOperasi();
			RencanaOperasi model = rencanaOperasiDao.findRencanaOperasiByNorec(vo.getStrukOrder().getNoRec());
			
			if(CommonUtil.isNotNullOrEmpty(model) && CommonUtil.isNullOrEmpty(model.getTglOperasi()))
			{
				model.setTglRencana(vo.getRencanaOperasi().getTglRencana());
				/*if (CommonUtil.isNotNullOrEmpty(vo.getRencanaOperasi().getKamar())) {
					model.setKamar(kamarConverter.transferVOToModel(vo.getRencanaOperasi().getKamar(), new Kamar()));
				}*/
				/*if (CommonUtil.isNotNullOrEmpty(vo.getRencanaOperasi().getJenisOperasi())) {
					model.setJenisOperasi(jenisOperasiConverter.transferVOToModel(vo.getRencanaOperasi().getJenisOperasi(), new JenisOperasi()));
				}*/
				Set<DetailRencanaOperasi> listDetailRencanaOperasi = new HashSet<DetailRencanaOperasi>();
				
				for (DetailRencanaOperasiVO item : vo.getRencanaOperasi().getDetailPelaksana()) {
					
					for(PegawaiVO pegawai : item.getPegawaiList())
					{
						DetailRencanaOperasi modelItem = new DetailRencanaOperasi();
						modelItem = detailRencanaOperasiConverter.transferVOToModel(item,  modelItem);
						modelItem.setRencanaOperasi(model);
						if (CommonUtil.isNotNullOrEmpty(pegawai)) {
							modelItem.setPegawai(pegawaiConverter.transferVOToModel(pegawai, new Pegawai()));
							
						}
						if (CommonUtil.isNotNullOrEmpty(item.getJenisPelaksana())) {
							modelItem.setJenisPelaksana(jenisPetugasPelaksanaConverter.transferVOToModel(item.getJenisPelaksana(),
									new JenisPetugasPelaksana()));
						}
						if(CommonUtil.isNotNullOrEmpty(item.getRuangan()))
						{
							modelItem.setRuangan(ruanganConverter.transferVOToModel(item.getRuangan(), new Ruangan()));
						}
						model.getDetailPelaksana().clear();
						listDetailRencanaOperasi.add(modelItem);
					}
				}
				model.setDetailPelaksana(listDetailRencanaOperasi);
				if(CommonUtil.isNotNullOrEmpty(model))
				{
					RencanaOperasi resultDomain = rencanaOperasiDao.save(model);
					if (CommonUtil.isNotNullOrEmpty(resultDomain)) {
						result.put("noRec", resultDomain.getNoRec());
					}
				}
			}
			
		}
			
		return result;
	}

	
	@Override
	public Map<String, Object> savePermintaanOperasi(RencanaOperasiCustomVO vox) {
		Map<String, Object> result = new HashMap<String, Object>();
		RencanaOperasi model = new RencanaOperasi();
		StrukOrder strukOrder = new StrukOrder();
		RencanaOperasiVO vo = vox.getRencanaOperasi();
		StrukOrderVO strukOrderVO = vox.getStrukOrder();
		if(CommonUtil.isNotNullOrEmpty(vox))
		{
			
			if(CommonUtil.isNotNullOrEmpty(strukOrderVO))
			{
				strukOrder = strukOrderConverter.transferVOToModel(strukOrderVO, new StrukOrder());
				strukOrder.setIsDelivered((byte)1);
				String noOrder = strukOrderService.formatNoUrut("Struk Order", "STO");
				String noOrderIntern = strukOrderService.formatNoUrut("Struk Order Operasi", "OK");
				strukOrder.setNoOrder(noOrder);
				strukOrder.setNoOrderIntern(noOrderIntern);
				strukOrder.setTotalBeaMaterai(0.0);
				strukOrder.setTotalBiayaKirim(0.0);
				strukOrder.setTotalBiayaTambahan(0.0);
				strukOrder.setTotalDiscount(0.0);
				strukOrder.setTotalHargaSatuan(0.0);
				strukOrder.setTotalHarusDibayar(0.0);
				strukOrder.setTotalPph(0.0);
				strukOrder.setTotalPpn(0.0);
				if(CommonUtil.isNotNullOrEmpty(strukOrderVO.getNoCm()))
				{
					strukOrder.setNoCm(pasienConverter.transferVOToModel(strukOrderVO.getNoCm(), new Pasien()));
				}
				if(CommonUtil.isNotNullOrEmpty(strukOrderVO.getNoRegistrasi()))
				{
					strukOrder.setNoRegistrasi(pasienDaftarConverter.transferVOToModel(strukOrderVO.getNoRegistrasi(), new PasienDaftar()));
				}
				if (CommonUtil.isNotNullOrEmpty(strukOrderVO.getPegawaiOrder())) {
					strukOrder.setPegawaiOrder(pegawaiConverter.transferVOToModel(strukOrderVO.getPegawaiOrder(), new Pegawai()));
				}
				if (CommonUtil.isNotNullOrEmpty(strukOrderVO.getRuangan())) {
					strukOrder.setRuangan(ruanganConverter.transferVOToModel(strukOrderVO.getRuangan(), new Ruangan()));
				}
				if (CommonUtil.isNotNullOrEmpty(strukOrderVO.getRuanganTujuan())) {
					strukOrder.setRuanganTujuan(ruanganConverter.transferVOToModel(strukOrderVO.getRuangan(), new Ruangan()));
				}				
			}
			if(CommonUtil.isNotNullOrEmpty(vo)){
				Set<RencanaOperasi> rencanaOperasiSet = new HashSet<>();
				if(CommonUtil.isNotNullOrEmpty(vo.getStrukOrder().getRencanaOperasi())){
					
					model = rencanaOperasiConverter.transferVOToModel(vo, model);	
					if (CommonUtil.isNotNullOrEmpty(strukOrder)) {
						model.setStrukOrder(strukOrder);
					}
					if(CommonUtil.isNotNullOrEmpty(model)) {
						rencanaOperasiSet.add(model);
					}
				}
				if(CommonUtil.isNotNullOrEmpty(rencanaOperasiSet)) {
					strukOrder.setRencanaOperasi(rencanaOperasiSet);
				}
			}			

			if(CommonUtil.isNotNullOrEmpty(strukOrder))
			{
				StrukOrder resultDomain = strukOrderDao.save(strukOrder);
				if (CommonUtil.isNotNullOrEmpty(resultDomain)) {
					result.put("noRec", resultDomain.getNoRec());
				}
			}			
		}

		return result;
	}
	
	@Override
	public Map<String, Object> saveOperasi(RencanaOperasiVO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		AntrianPasienDiPeriksa antrianPasienDiPeriksa = new AntrianPasienDiPeriksa();
		
		if(CommonUtil.isNotNullOrEmpty(vo.getStrukOrder())) {
			RencanaOperasi rencanaOperasi = rencanaOperasiDao.findRencanaOperasiByNorec(vo.getStrukOrder().getNoRec());
			
			StrukOrder strukOrder = strukOrderDao.findByNoRec(vo.getStrukOrder().getNoRec());
			
			Map<String, Object> antrian = antrianPasienDiPeriksaDao.findAntrianByNoRec(vo.getNoCm().getNoRec());
			
			//noRec: 2c90e38f5f34cc89015f34da5eea0004
			AntrianPasienDiPeriksa antrianPasienSebelumnya =  rencanaOperasiDao.getAntrianSebelumnyaByNoRec((String) antrian.get("noRecPasienDaftar"));
				
			if(CommonUtil.isNotNullOrEmpty(vo.getTglOperasi())) {
				rencanaOperasi.setTglOperasi(vo.getTglOperasi());
			}
			
			RencanaOperasi resultdata = rencanaOperasiDao.save(rencanaOperasi);
			
			if(CommonUtil.isNotNullOrEmpty(vo.getNoCm().getNoRec())) {
				antrianPasienDiPeriksa.setNoRec((String)antrian.get("noRec"));
				antrianPasienDiPeriksa.setNoAntrian(antrianPasienDiPeriksaService.getFormatNumberByMonthYearRuangan(
						vo.getTglOperasi(), strukOrder.getRuanganTujuan().getId()));
				antrianPasienDiPeriksa.setTglRegistrasi((Date)antrian.get("tglRegistrasi"));
				
				if(CommonUtil.isNotNullOrEmpty(antrian.get("statusPasien"))) {
					antrianPasienDiPeriksa.setStatusPasien((byte)antrian.get("statusPasien"));
				}
				if(CommonUtil.isNotNullOrEmpty(antrian.get("statusAntrian"))){
					antrianPasienDiPeriksa.setStatusAntrian((String)antrian.get("statusAntrian"));
				}
				
				antrianPasienDiPeriksa.setAsalRujukan(asalRujukanConverter.transferVOToModel(vo.getAsalRujukan(), new AsalRujukan()));
				antrianPasienDiPeriksa.setPasienDaftar(strukOrder.getNoRegistrasi());
				antrianPasienDiPeriksa.setKelas(antrianPasienSebelumnya.getKelas());
				antrianPasienDiPeriksa.setPegawai(pegawaiConverter.transferVOToModel(vo.getStrukOrder().getPegawaiOrder(), strukOrder.getPegawaiOrder()));
				antrianPasienDiPeriksa.setRuangan(ruanganConverter.transferVOToModel(vo.getRuangan(), new Ruangan()));
				antrianPasienDiPeriksa.setStrukOrder(strukOrder);
				
				AntrianPasienDiPeriksa resultAntrian = antrianPasienDiPeriksaDao.save(antrianPasienDiPeriksa);
				
				if(CommonUtil.isNotNullOrEmpty(resultAntrian)) {
					result.put("noRec", resultAntrian.getNoRec());
				}
			
			}

		}
					
		return result;

	}
	
	
	@Override
	public List<Map<String, Object>> getRencanaOperasi(String noRec) {
		List<Map<String, Object>> result = rencanaOperasiDao.findRencanaOperasi(noRec);
		return result;
	}

	@Override
	public Map<String, Object> savePembatalanOperasi(RencanaOperasiVO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		RencanaOperasi rencanaOperasi = rencanaOperasiDao.findByNorec(vo.getNoRec());//get Rencana operasi where tglOperasi is null
		if(CommonUtil.isNotNullOrEmpty(rencanaOperasi))
		{
			rencanaOperasi.setStatusBatal(vo.getStatusBatal());
			rencanaOperasi.setKeterangan(vo.getKeterangan());
			rencanaOperasi.setPegawaiYangMembatalkan(pegawaiConverter.transferVOToModel(vo.getPegawaiYangMembatalkan(), new Pegawai()));
			RencanaOperasi model = rencanaOperasiDao.save(rencanaOperasi);
			if(CommonUtil.isNotNullOrEmpty(model))
			{
				result.put("noRec", model.getNoRec());				
			}
		}
		
		return result;
	}

	@Override
	public List<Map<String, Object>> getPermintaanOperasi() {
		List<Map<String, Object>> result = rencanaOperasiDao.findPermintaanOperasi();
		return result;
	}

	@Override
	public List<Map<String, Object>> getRencanaOperasi() {
		List<Map<String, Object>> result = rencanaOperasiDao.findRencanaOperasi();
		return result;
	}

	@Override
	public List<Map<String, Object>> getPermintaanOperasi(String startDate, String endDate, String noCm) {
		List<Map<String, Object>> result = rencanaOperasiDao.findPermintaanOperasiByNocmAndDate(startDate, endDate, noCm);
		return result;
	}

	@Override
	public List<Map<String, Object>> getRencanaOperasi(String startDate, String endDate, String noCm) {
		List<Map<String, Object>> result = rencanaOperasiDao.findRencanaOperasiByNocmAndDate(startDate, endDate, noCm);
		return result;
	}

	@Override
	public Map<String, Object> getRencanaOperasiByNorec(String noRec) {
		Map<String, Object> result = rencanaOperasiDao.findRencanaOperasiByNoRec(noRec);
		return result;
	}

	@Override
	public Map<String, Object> getPermintaanOperasiByNorec(String noRec) {
		Map<String, Object> result = rencanaOperasiDao.findPermintaanOperasiByNoRec(noRec);		
		return result;
	}

	
}