package com.jasamedika.medifirst2000.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jasamedika.medifirst2000.constants.Master;
import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.dao.IkiDanRemunerasiDao;
import com.jasamedika.medifirst2000.dao.IndeksKinerjaDokterDao;
import com.jasamedika.medifirst2000.dao.IndikatorKinerjaDetailDao;
import com.jasamedika.medifirst2000.dao.JabatanDao;
import com.jasamedika.medifirst2000.dao.LogbookKinerjaDokterDao;
import com.jasamedika.medifirst2000.dao.MapPegawaiJabatanToUnitKerjaDao;
import com.jasamedika.medifirst2000.dao.MapPegawaiLaboratRadiologiDao;
import com.jasamedika.medifirst2000.dao.MonitoringAbsenDao;
import com.jasamedika.medifirst2000.dao.PegawaiDao;
import com.jasamedika.medifirst2000.dao.RunningNumberDao;
import com.jasamedika.medifirst2000.dao.SettingPirSdmDao;
import com.jasamedika.medifirst2000.dao.ShiftKerjaDao;
import com.jasamedika.medifirst2000.dao.SkoringTindakanMedisDao;
import com.jasamedika.medifirst2000.dao.StrukHistoriDao;
import com.jasamedika.medifirst2000.dao.StrukPelayananDao;
import com.jasamedika.medifirst2000.dao.SubUnitKerjaDao;
import com.jasamedika.medifirst2000.dao.TargetLayananDao;
import com.jasamedika.medifirst2000.entities.EvaluasiJabatan;
import com.jasamedika.medifirst2000.entities.IkiDanRemunerasi;
import com.jasamedika.medifirst2000.entities.IndeksKinerjaDokter;
import com.jasamedika.medifirst2000.entities.IndikatorKinerjaDetail;
import com.jasamedika.medifirst2000.entities.Jabatan;
import com.jasamedika.medifirst2000.entities.KelompokTransaksi;
import com.jasamedika.medifirst2000.entities.LogbookKinerjaDokter;
import com.jasamedika.medifirst2000.entities.Pegawai;
import com.jasamedika.medifirst2000.entities.PegawaiHistoriRekap;
import com.jasamedika.medifirst2000.entities.Ruangan;
import com.jasamedika.medifirst2000.entities.RunningNumber;
import com.jasamedika.medifirst2000.entities.SettingPirSdm;
import com.jasamedika.medifirst2000.entities.StrukHistori;
import com.jasamedika.medifirst2000.entities.StrukPelayanan;
import com.jasamedika.medifirst2000.entities.SubUnitKerjaPegawai;
import com.jasamedika.medifirst2000.entities.SuratKeputusan;
import com.jasamedika.medifirst2000.entities.TargetLayanan;
import com.jasamedika.medifirst2000.entities.UnitKerjaPegawai;
import com.jasamedika.medifirst2000.service.IkiDanRemunerasiService;
import com.jasamedika.medifirst2000.service.LogbookKinerjaService;
import com.jasamedika.medifirst2000.service.TargetSkorDokterService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.CurrencyUtil;
import com.jasamedika.medifirst2000.util.DateUtil;
import com.jasamedika.medifirst2000.util.StringUtil;
import com.jasamedika.medifirst2000.vo.EvaluasiJabatanVO;
import com.jasamedika.medifirst2000.vo.IkiDanRemunerasiVO;
import com.jasamedika.medifirst2000.vo.IndikatorKinerjaDetailVO;
import com.jasamedika.medifirst2000.vo.JabatanVO;
import com.jasamedika.medifirst2000.vo.KelompokTransaksiVO;
import com.jasamedika.medifirst2000.vo.PegawaiVO;
import com.jasamedika.medifirst2000.vo.RuanganVO;
import com.jasamedika.medifirst2000.vo.SettingPirSdmVO;
import com.jasamedika.medifirst2000.vo.SkorDokterVO;
import com.jasamedika.medifirst2000.vo.StrukHistoriVO;
import com.jasamedika.medifirst2000.vo.SubUnitKerjaPegawaiVO;
import com.jasamedika.medifirst2000.vo.SuratKeputusanVO;
import com.jasamedika.medifirst2000.vo.TargetSkorDokterVO;
import com.jasamedika.medifirst2000.vo.UnitKerjaPegawaiVO;
import com.jasamedika.medifirst2000.vo.custom.TargetLayananJamKerjaDetailVO;
import com.jasamedika.medifirst2000.vo.custom.TargetLayananJamKerjaVO;
import com.jasamedika.medifirst2000.vo.custom.TargetLayananLuarJamKerjaDetailVO;
import com.jasamedika.medifirst2000.vo.custom.TargetLayananLuarJamKerjaVO;

@Service("IkiDanRemunerasiService")
public class IkiDanRemunerasiServiceImpl extends BaseVoServiceImpl implements IkiDanRemunerasiService {

	@Autowired
	private LogbookKinerjaService logbookKinerjaService;

	@Autowired
	private TargetSkorDokterService targetSkorDokterService;

	@Autowired
	private BaseConverterImpl<StrukHistoriVO, StrukHistori> strukHistoriConverter;

	@Autowired
	private BaseConverterImpl<IkiDanRemunerasiVO, IkiDanRemunerasi> ikiDanRemunerasiConverter;

	@Autowired
	private BaseConverterImpl<UnitKerjaPegawaiVO, UnitKerjaPegawai> unitKerjaPegawaiConverter;

	@Autowired
	private BaseConverterImpl<RuanganVO, Ruangan> ruanganConverter;

	@Autowired
	private BaseConverterImpl<KelompokTransaksiVO, KelompokTransaksi> kelompokTransaksiConverter;

	@Autowired
	private BaseConverterImpl<EvaluasiJabatanVO, EvaluasiJabatan> evaluasiJabatanConverter;

	@Autowired
	private BaseConverterImpl<SuratKeputusanVO, SuratKeputusan> suratKeputusanConverter;

	@Autowired
	private BaseConverterImpl<SettingPirSdmVO, SettingPirSdm> settingPirSdmConverter;

	@Autowired
	private BaseConverterImpl<PegawaiVO, Pegawai> pegawaiConverter;

	@Autowired
	private IkiDanRemunerasiDao ikiDanRemunerasiDao;

	@Autowired
	private StrukPelayananDao strukPelayananDao;

	@Autowired
	private MonitoringAbsenDao monitoringAbsenDao;

	@Autowired
	private SettingPirSdmDao settingPirSdmDao;

	@Autowired
	private RunningNumberDao runningNumberDao;

	@Autowired
	private StrukHistoriDao strukHistoriDao;

	@Autowired
	private TargetLayananDao targetLayananDao;

	@Autowired
	private SkoringTindakanMedisDao skoringTindakanMedisDao;

	@Autowired
	private IndikatorKinerjaDetailDao indikatorKinerjaDetailDao;

	@Autowired
	private SubUnitKerjaDao subunitKerjaDao;

	@Autowired
	private MapPegawaiJabatanToUnitKerjaDao mapPegawaiJabatanToUnitKerjaDao;

	@Autowired
	private LogbookKinerjaDokterDao logbookKinerjaDokterDao;

	@Autowired
	private ShiftKerjaDao shiftKerjaDao;

	@Autowired
	private PegawaiDao pegawaiDao;

	@Autowired
	private JabatanDao jabatanDao;

	@Autowired
	private MapPegawaiLaboratRadiologiDao mapPegawaiLaboratRadiologiDao;

	@Autowired
	private IndeksKinerjaDokterDao indeksKinerjaDokterDao;

	@Override
	public Map<String, Object> loadData() {
		Map<String, Object> result = new HashMap<>();
		List<Map<String, Object>> listData = ikiDanRemunerasiDao.getPegawaiRemunerasi();
		if (CommonUtil.isNotNullOrEmpty(listData)) {
			result.put("liatData", listData);
		}
		return result;
	}

	@Override
	public Map<String, Object> getKalkulasiDataRemunerasi(Integer id, String date) {
		String[] splitData = date.split("-");
		Integer paramTahun = Integer.parseInt(splitData[0]);

		Date start = DateUtil.startMonth(date.substring(0, 7));
		Date end = DateUtil.endMonth(date.substring(0, 7));

		Map<String, Object> ikiRemunerasi = new HashMap<>();

		Map<String, Object> evaluasiJabatan = ikiDanRemunerasiDao.getEvaluasiJabatan(id);
		if (CommonUtil.isNotNullOrEmpty(evaluasiJabatan.get("nilaiJabatan"))) {
			Double indeksKehadiran = ikiDanRemunerasiDao.getIndeksKehadiran(date.substring(0, 7), id);
			if (CommonUtil.isNotNullOrEmpty(indeksKehadiran)) {
				ikiRemunerasi.put("nilaiIndeksKehadiran", indeksKehadiran);
			} else {
				ikiRemunerasi.put("nilaiIndeksKehadiran", 0.0);
			}
			ikiRemunerasi.putAll(evaluasiJabatan);
			Double gajiBersih = 0.00;
			if (CommonUtil.isNotNullOrEmpty(ikiRemunerasi.get("nipPns"))) {
				List<Map<String, Object>> komponenGaji = ikiDanRemunerasiDao.getTotalGaji(id);
				if (CommonUtil.isNotNullOrEmpty(komponenGaji)) {
					for (Map<String, Object> data : komponenGaji) {
						if (((Integer) data.get("id") == 63 || (Integer) data.get("id") == 64
								|| (Integer) data.get("id") == 65 || (Integer) data.get("id") == 66
								|| (Integer) data.get("id") == 67 || (Integer) data.get("id") == 68
								|| (Integer) data.get("id") == 69 || (Integer) data.get("id") == 70)) {
							if ((byte) data.get("isByMonth") == 1) {
								gajiBersih = gajiBersih - (Double) data.get("hargaSatuan");
							} else if ((byte) data.get("isByWeek") == 1) {
								gajiBersih = (Double) data.get("hargaSatuan") * 4;
							} else if ((byte) data.get("isByDay") == 1) {
								gajiBersih = (Double) data.get("hargaSatuan")
										* (Integer) ikiRemunerasi.get("nilaiIndeksKehadiran");
							}
						} else {
							if ((byte) data.get("isByMonth") == 1) {
								gajiBersih = gajiBersih + (Double) data.get("hargaSatuan");
							} else if ((byte) data.get("isByWeek") == 1) {
								gajiBersih = (Double) data.get("hargaSatuan") * 4;
							} else if ((byte) data.get("isByDay") == 1) {
								gajiBersih = (Double) data.get("hargaSatuan")
										* (Double) ikiRemunerasi.get("nilaiIndeksKehadiran");
							}
						}
					}
					ikiRemunerasi.put("gaji", gajiBersih);
				}
				Double ikur = 0.0;
				Double pirr = 0.0;
				List<Map<String, Object>> pirs = settingPirSdmDao.getPIR(paramTahun.toString());
				if (CommonUtil.isNotNullOrEmpty(pirs)) {
					Map<String, Object> pir = pirs.get(0);
					pirr = (Double) pir.get("pir");
				}
				if (CommonUtil.isNotNullOrEmpty(ikiRemunerasi.get("idUnitKerja"))) {
					Map<String, Object> iku = settingPirSdmDao
							.getIKUUnitKerja((Integer) ikiRemunerasi.get("idUnitKerja"), start, end);
					if (CommonUtil.isNotNullOrEmpty(iku)) {
						ikur = (Double) iku.get("iku");
					}
				}
				ikiRemunerasi.put("pir", pirr);
				ikiRemunerasi.put("iku", ikur);
				Map<String, Object> indexKinerjaIndividu = ikiDanRemunerasiDao.getTotalIndexKinerjaIndividu(id,
						date.substring(0, 7));
				if (CommonUtil.isNotNullOrEmpty(indexKinerjaIndividu)) {
					ikiRemunerasi.put("iki", indexKinerjaIndividu.get("iki"));
				} else {
					ikiRemunerasi.put("iki", 0.00);
				}
				if (CommonUtil.isNotNullOrEmpty(ikiRemunerasi)) {
					Double P1 = ((Double) ikiRemunerasi.get("pir") * 15) / 100;
					ikiRemunerasi.put("P1", P1);
					// --------------------------------------------
					Double P2 = ((Double) ikiRemunerasi.get("pir") * 85) / 100;
					ikiRemunerasi.put("P2", P2);
					// --------------------------------------------
					Double P1_Rp = (Double) ikiRemunerasi.get("nilaiJabatan");
					P1_Rp = P1_Rp * P1;
					P1_Rp = P1_Rp * (Double) ikiRemunerasi.get("nilaiIndeksKehadiran");
					ikiRemunerasi.put("P1_Rp", CurrencyUtil.getPriceInINA(P1_Rp));
					// --------------------------------------------
					Double P2_Rp = (Double) ikiRemunerasi.get("nilaiJabatan") * P2 * (Double) ikiRemunerasi.get("iki")
							* (Double) ikiRemunerasi.get("iku");
					ikiRemunerasi.put("P2_Rp", CurrencyUtil.getPriceInINA(P2_Rp));
					// --------------------------------------------
					Double REMUNERASI = P1_Rp + P2_Rp;
					ikiRemunerasi.put("sum", CurrencyUtil.getPriceInINA(REMUNERASI));
					if (CommonUtil.isNotNullOrEmpty(ikiRemunerasi.get("kelompokJabatanId"))) {
						Map<String, Object> rangeKmk = ikiDanRemunerasiDao
								.getRangeKmk((Integer) ikiRemunerasi.get("nilaiKelompokJabatan"));
						if (CommonUtil.isNotNullOrEmpty(rangeKmk)) {
							Double TOTAL_REMUNERASI = 0.00;
							if (REMUNERASI > (Integer) rangeKmk.get("maximal")) {
								TOTAL_REMUNERASI = (Double) rangeKmk.get("maximal");
							} else if (REMUNERASI <= (Integer) rangeKmk.get("maximal")) {
								TOTAL_REMUNERASI = REMUNERASI;
							}
							ikiRemunerasi.put("remunerasi", CurrencyUtil.getPriceInINA(TOTAL_REMUNERASI));
							if (CommonUtil.isNotNullOrEmpty(ikiRemunerasi.get("idGolongan"))) {
								int idGolongan = (Integer) ikiRemunerasi.get("idGolongan");
								Double pajak = ikiDanRemunerasiDao.findPersentasiPajak(idGolongan);
								if (CommonUtil.isNullOrEmpty(pajak)) {
									pajak = 0.0;
								}
								pajak = (pajak * TOTAL_REMUNERASI) / 100;
								ikiRemunerasi.put("pajak", CurrencyUtil.getPriceInINA(pajak));
								ikiRemunerasi.put("remunerasiYgDiterima",
										CurrencyUtil.getPriceInINA(TOTAL_REMUNERASI - pajak));
							} else {
								ikiRemunerasi.put("pajak", 0.0);
								ikiRemunerasi.put("remunerasiYgDiterima", CurrencyUtil.getPriceInINA(TOTAL_REMUNERASI));
							}

						}
					} else {
						ikiRemunerasi.put("remunerasi", 0);
					}
				}
			}
		}

		return ikiRemunerasi;
	}

	@Override
	public Map<String, Object> saveIkiRemunerasi(StrukHistoriVO vo) {
		Map<String, Object> result = new HashMap<>();
		Set<IkiDanRemunerasi> listIkiDanRemunerasi = new HashSet<IkiDanRemunerasi>();
		Set<PegawaiHistoriRekap> listPegawaiHistoriRekap = new HashSet<PegawaiHistoriRekap>();
		if (CommonUtil.isNotNullOrEmpty(vo)) {
			StrukHistori strukHistori = strukHistoriConverter.transferVOToModel(vo, new StrukHistori());
			for (IkiDanRemunerasiVO data : vo.getIkiDanRemunerasi()) {
				String noRecStrukPelayanan = "";
				Pegawai pegawai = pegawaiConverter.transferVOToModel(data.getPegawai(), new Pegawai());
				IkiDanRemunerasi ikiDanRemunerasi = ikiDanRemunerasiConverter.transferVOToModel(data,
						new IkiDanRemunerasi());

				if (CommonUtil.isNotNullOrEmpty(data.getEvaluasiJabatan())) {
					ikiDanRemunerasi.setEvaluasiJabatan(evaluasiJabatanConverter
							.transferVOToModel(data.getEvaluasiJabatan(), new EvaluasiJabatan()));
				}
				if (CommonUtil.isNotNullOrEmpty(data.getPegawai())) {
					ikiDanRemunerasi.setPegawai(pegawai);
				}
				ikiDanRemunerasi.setStrukHistory(strukHistori);
				Date start = DateUtil.startMonth(strukHistori.getTglHistori());
				Date end = DateUtil.endMonth(strukHistori.getTglHistori());
				int id = pegawai.getId();
				Double temp = ikiDanRemunerasiDao.findRemunerasi(start, end, id);
				if (CommonUtil.isNullOrEmpty(temp)) {
					// insert into StrukPelayanan
					StrukPelayanan strukPelayanan = new StrukPelayanan();
					strukPelayanan.setKdpegawaipenerima(ikiDanRemunerasi.getPegawai());
					strukPelayanan.setNamapegawaipenerima(ikiDanRemunerasi.getPegawai().getNamaLengkap());
					strukPelayanan.setTotalharusdibayar(ikiDanRemunerasi.getRemunerasi());
					if (CommonUtil.isNotNullOrEmpty(strukPelayanan)) {
						StrukPelayanan modelStrukPelayanan = strukPelayananDao.save(strukPelayanan);
						result.put("noRec StrukPelayanan-" + modelStrukPelayanan.noRec, modelStrukPelayanan.noRec);
						noRecStrukPelayanan = modelStrukPelayanan.getNoRec();
					}
					if (CommonUtil.isNotNullOrEmpty(noRecStrukPelayanan)) {
						// insert into pegawaiHistoriRekap
						PegawaiHistoriRekap pegawaiHistoriRekap = new PegawaiHistoriRekap();
						pegawaiHistoriRekap.setTotalHargaIndex(ikiDanRemunerasi.getRemunerasi());
						pegawaiHistoriRekap.setPegawai(ikiDanRemunerasi.getPegawai());
						pegawaiHistoriRekap.setNoStrukPelayanan(strukPelayanan);
						pegawaiHistoriRekap.setStrukHistory(strukHistori);
						listPegawaiHistoriRekap.add(pegawaiHistoriRekap);
						listIkiDanRemunerasi.add(ikiDanRemunerasi);
					}
				}
			}
			strukHistori.setKelompokTransaksi(
					kelompokTransaksiConverter.transferVOToModel(vo.getKelompokTransaksi(), new KelompokTransaksi()));
			strukHistori.setRuangan(ruanganConverter.transferVOToModel(vo.getRuangan(), new Ruangan()));
			strukHistori.getPegawaiHistoriRekap().clear();
			strukHistori.setPegawaiHistoriRekap(listPegawaiHistoriRekap);
			strukHistori.getIkiDanRemunerasi().clear();
			strukHistori.setIkiDanRemunerasi(listIkiDanRemunerasi);
			if (CommonUtil.isNotNullOrEmpty(strukHistori)) {
				StrukHistori model = strukHistoriDao.save(strukHistori);
				result.put("noRecStrukHistori" + "", model.noRec);
			}
		}
		return result;
	}

	@Override
	public Map<String, Object> getKalkulasiDataRemunerasiByUnitKerja(Integer ruanganId, String date) {
		Map<String, Object> result = new HashMap<>();

		List<Map<String, Object>> listIKIDanRemunerasi = new ArrayList<Map<String, Object>>();
		List<Integer> listId = monitoringAbsenDao.findByIdPegawaiByRuangan(ruanganId);
		for (Integer idPegawai : listId) {
			Map<String, Object> data = this.getKalkulasiDataRemunerasi(idPegawai, date);
			if (CommonUtil.isNotNullOrEmpty(data)) {
				listIKIDanRemunerasi.add(data);
			}
		}
		result.put("listIKIDanRemunerasi", listIKIDanRemunerasi);
		return result;
	}

	@Override
	@Transactional(readOnly = false)
	public Map<String, Object> getKalkulasiDataRemunerasiPegawai(String date) {
		Map<String, Object> result = new HashMap<>();
		List<String> listIdKategori = ikiDanRemunerasiDao.findIdKategoriPegawai();
		List<Map<String, Object>> listIKIDanRemunerasi = new ArrayList<Map<String, Object>>();
		for (String idKategory : listIdKategori) {
			Integer idKategoryPegawai = Integer.valueOf(idKategory);
			List<Integer> listIdPegawai = ikiDanRemunerasiDao.findDetailKategoriPegawai(idKategoryPegawai);

			for (Integer idPegawai : listIdPegawai) {
				// Integer idPegawai = 1059;
				Map<String, Object> data = this.getKalkulasiDataRemunerasi(idPegawai, date);
				if (CommonUtil.isNotNullOrEmpty(data)) {
					listIKIDanRemunerasi.add(data);
				}
			}
		}
		result.put("noStrukHistori", getRunningNumber("Struk Histori"));

		result.put("listIKIDanRemunerasi", listIKIDanRemunerasi);
		return result;
	}

	@Transactional(readOnly = false)
	private String getRunningNumber(String kegunaan) {
		RunningNumber runningNumber = runningNumberDao.findByResetAndKegunaan("0", kegunaan);
		Integer number = (runningNumber.getNomerTerbaru() + (Integer) 1);
		runningNumber.setNomerTerbaru(runningNumber.getNomerTerbaru() + (Integer) 1);
		String noOrderIntern = StringUtil.formatNumber(number.toString(), 6);
		runningNumberDao.save(runningNumber);
		return noOrderIntern;
	}

	@Override
	public Map<String, Object> findPir(String tahun) {
		List<Map<String, Object>> results = settingPirSdmDao.getPIR(tahun);
		Calendar date = Calendar.getInstance();
		int year = date.get(Calendar.YEAR);
		Map<String, Object> result = new HashMap<String, Object>();
		if (CommonUtil.isNotNullOrEmpty(results)) {
			result = results.get(0);
			if (Integer.valueOf(tahun) > year) {
				result.put("status", false); // false_means_data_is_not_used_and_can_be_updated
			} else {
				result.put("status", true);
			}
		}
		return result;
	}

	@Override
	public Map<String, Object> savePirDanIku(List<SettingPirSdmVO> vos) {
		Map<String, Object> result = new HashMap<String, Object>();
		for (SettingPirSdmVO vo : vos) {
			Date start = DateUtil.startMonth(vo.getTglAwal());
			Date end = DateUtil.endMonth(vo.getTglAwal());
			SettingPirSdm settingPirSdm = settingPirSdmConverter.transferVOToModel(vo, new SettingPirSdm());
			if (CommonUtil.isNotNullOrEmpty(vo.getSuratKeputusan())) {
				settingPirSdm.setSuratKeputusan(
						suratKeputusanConverter.transferVOToModel(vo.getSuratKeputusan(), new SuratKeputusan()));
			}
			if (CommonUtil.isNotNullOrEmpty(vo.getUnitKerja())) {
				settingPirSdm.setUnitKerja(
						unitKerjaPegawaiConverter.transferVOToModel(vo.getUnitKerja(), new UnitKerjaPegawai()));
			}
			if (CommonUtil.isNotNullOrEmpty(vo.getIku())) {
				if (CommonUtil.isNotNullOrEmpty(vo.getUnitKerja())) {
					Map<String, Object> data = settingPirSdmDao.getIKUUnitKerja(vo.getUnitKerja().getId(), start, end);
					if (CommonUtil.isNotNullOrEmpty(data)) {
						settingPirSdm.setId((Integer) data.get("id"));
					}
				}
			}

			if (CommonUtil.isNotNullOrEmpty(vo.getPir())) {
				SimpleDateFormat df = new SimpleDateFormat("yyyy");
				List<Map<String, Object>> datas = settingPirSdmDao.getPIR(df.format(vo.getTglAwal()));
				if (CommonUtil.isNotNullOrEmpty(datas)) {
					Map<String, Object> data = datas.get(0);
					settingPirSdm.setId((Integer) data.get("id"));
				}
			}
			if (CommonUtil.isNotNullOrEmpty(settingPirSdm)) {
				SettingPirSdm model = settingPirSdmDao.save(settingPirSdm);
				result.put(model.getId() + "", model.getId());
			}
		}
		return result;
	}

	@Override
	public Map<String, Object> getListPegawai() {
		return null;
	}

	@Override
	public Map<String, Object> findIKU(String periode, Integer idUnitkerja) {
		Date start = DateUtil.startMonth(periode);
		Date end = DateUtil.endMonth(periode);
		Map<String, Object> result = settingPirSdmDao.getIKUUnitKerja(idUnitkerja, start, end);
		Calendar date = Calendar.getInstance();
		int month = date.get(Calendar.MONTH);
		periode = periode.substring(5, 7);
		if (CommonUtil.isNotNullOrEmpty(result)) {
			if (Integer.valueOf(periode) > month + 1) {
				result.put("status", false); // false_means_data_is_not_used_and_can_be_updated
			} else {
				result.put("status", true);
			}
		}
		return result;
	}

	@Override
	public List<Map<String, Object>> findAllIKU() {
		List<Map<String, Object>> result = settingPirSdmDao.getAllIKU();
		return result;
	}

	@Override
	public void autoSaveTargetCapaianLayananJamKerja() throws ParseException {
		List<Map<String, Object>> listIkiDokter = new ArrayList<>();
		List<SkorDokterVO> listSkorDokter = new ArrayList<>();

		LocalDate now = LocalDate.now();
		LocalDate firstDayOfYear = now.with(TemporalAdjusters.firstDayOfYear());
		LocalDate firstDate = now.minusYears(1).withMonth(1);
		LocalDate lastDate = now.minusYears(1).withMonth(12);
		if (now.getYear() == 2022) {
			firstDate = now.withYear(2019).withMonth(3);
			lastDate = now.withYear(2020).withMonth(2);
		}
		String bulanAwal = firstDate.getYear() + "-"
				+ (firstDate.getMonthValue() < 10 ? "0" + firstDate.getMonthValue() : firstDate.getMonthValue());
		String bulanAkhir = lastDate.getYear() + "-"
				+ (lastDate.getMonthValue() < 10 ? "0" + lastDate.getMonthValue() : lastDate.getMonthValue());

		List<Map<String, Object>> data = indeksKinerjaDokterDao.findAll(bulanAwal, bulanAkhir);
		if (CommonUtil.isNotNullOrEmpty(data)) {
			listSkorDokter = this.logbookKinerjaService.hitungTargetSkorLogbookDokter(bulanAwal, bulanAkhir);
		}

		for (Map<String, Object> map : data) {
			for (SkorDokterVO skorDokter : listSkorDokter) {
				if (CommonUtil.isNullOrEmpty(map.get("skor")) && skorDokter.getIdPegawai().equals(map.get("pegawaiId"))
						&& skorDokter.getBulan().equals(map.get("bulan"))) {
					map.put("skor", skorDokter.getSkor());
				}
			}
		}

		if (CommonUtil.isNotNullOrEmpty(data)) {
			data.stream()
					.filter(ikiDokter -> ikiDokter.get("iki") != null && ikiDokter.get("skor") != null
							&& !Double.valueOf(0.0).equals(ikiDokter.get("skor")))
					.collect(Collectors.groupingBy(ikiDokter -> ikiDokter.get("subunitKerjaId"),
							Collectors.groupingBy(ikiDokter -> ikiDokter.get("iki"))))
					.forEach((o1, objectListMap) -> objectListMap.forEach((o2, maps) -> {
						List<Map<String, Object>> sortedCollectMap = maps.stream()
								.sorted(Comparator.comparing(o3 -> Double.valueOf(o3.get("skor").toString())))
								.collect(Collectors.toList());

						int listMapSize = sortedCollectMap.size();
						boolean isIkiMax = Double.valueOf(3.0).equals(sortedCollectMap.get(0).get("iki"));
						double score;
						if (isIkiMax) {
							// min
							score = Double.parseDouble(sortedCollectMap.get(0).get("skor").toString());
						} else if (listMapSize % 2 == 0) {
							// med for even
							int center1 = listMapSize / 2 - 1;
							int center2 = listMapSize / 2;
							score = (Double.parseDouble(sortedCollectMap.get(center1).get("skor").toString())
									+ Double.parseDouble(sortedCollectMap.get(center2).get("skor").toString())) / 2;
						} else {
							// med for odd
							int center = listMapSize / 2;
							score = Double.parseDouble(sortedCollectMap.get(center).get("skor").toString());
						}

						sortedCollectMap.forEach(collectMap -> {
							double skorDasar = score / Double.parseDouble(collectMap.get("iki").toString());

							collectMap.put("skorDasar", skorDasar);
						});

						listIkiDokter.addAll(sortedCollectMap);
					}));
		}

		List<IndeksKinerjaDokter> models = new ArrayList<>();
		for (Map<String, Object> ikiDokter : listIkiDokter) {
			IndeksKinerjaDokter model = indeksKinerjaDokterDao.findOne(ikiDokter.get("noRec").toString());
			model.setSkor(Double.parseDouble(ikiDokter.get("skor").toString()));
			model.setSkorDasar(Double.parseDouble(ikiDokter.get("skorDasar").toString()));

			models.add(model);
		}

		indeksKinerjaDokterDao.save(models);

		List<Map<String, Object>> listTotalSkor = indeksKinerjaDokterDao.findTotalSkorByKelompokKerja(bulanAwal,
				bulanAkhir);
		for (Map<String, Object> totalSkor : listTotalSkor) {
			TargetSkorDokterVO vo = new TargetSkorDokterVO();
			vo.setKdProfile((short) 0);
			vo.setStatusEnabled(true);

			UnitKerjaPegawaiVO unitKerjVO = new UnitKerjaPegawaiVO();
			unitKerjVO.setId(Integer.parseInt(totalSkor.get("unitKerjaId").toString()));
			vo.setUnitKerjaPegawai(unitKerjVO);

			SubUnitKerjaPegawaiVO subunitKerjaVO = new SubUnitKerjaPegawaiVO();
			subunitKerjaVO.setId(Integer.parseInt(totalSkor.get("subunitKerjaId").toString()));
			vo.setSubUnitKerjaPegawai(subunitKerjaVO);

			vo.setTotalSkorDasar(Double.parseDouble(totalSkor.get("totalSkorDasar").toString()));
			vo.setTglHitung(Date.from(now.atStartOfDay(ZoneId.systemDefault()).toInstant()));
			vo.setTmt(Date.from(firstDayOfYear.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));

			/**
			 * Tidak memungkinkan untuk hitung ulang target skor kelompok kerja
			 * dengan asumsi tidak adanya fitur batal verifikasi logbook skor
			 * dokter
			 * 
			 * Sehingga tidak memanggil service update
			 */
			targetSkorDokterService.add(vo);
		}
	}

	@Override
	public void autoSaveTargetCapaianLayananJamKerja(String strPeriode) throws ParseException {
		List<Map<String, Object>> dataLayananRaw = new ArrayList<>();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		SimpleDateFormat sdfINA = new SimpleDateFormat("MMMM yyyy", new Locale("in", "ID"));

		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

		Date periode = sdf.parse(strPeriode);

		// get_few_months_earlier
		Calendar calTglAwal = Calendar.getInstance();
		calTglAwal.setTime(periode);
		calTglAwal.set(Calendar.HOUR_OF_DAY, 0);
		calTglAwal.set(Calendar.MINUTE, 0);
		calTglAwal.set(Calendar.SECOND, 0);
		calTglAwal.set(Calendar.DAY_OF_MONTH, 1);
		calTglAwal.add(Calendar.MONTH, -Integer.valueOf(GetSettingDataFixed("jmlBlnHitungTargetMedis")));

		// get_this_period
		Calendar bulan = Calendar.getInstance();
		bulan.setTime(periode);
		bulan.set(Calendar.HOUR_OF_DAY, 23);
		bulan.set(Calendar.MINUTE, 59);
		bulan.set(Calendar.SECOND, 0);
		bulan.set(Calendar.DAY_OF_MONTH, bulan.getActualMaximum(Calendar.DAY_OF_MONTH));

		LocalDateTime PSBBDate = LocalDateTime.of(2020, 9, 14, 0, 0, 0);
		LocalDateTime PSBBEnd = LocalDateTime.parse(GetSettingDataFixed("psbbperiod"), dtf);

		Date pssbAwal = Date.from(PSBBDate.atZone(ZoneId.systemDefault()).toInstant());
		Date pssbAkhir = Date.from(PSBBEnd.atZone(ZoneId.systemDefault()).toInstant());

		List<Integer> listRuangEks = splitDataSettingDatafixed("IdRuanganEksekutif");
		List<Integer> listKonsulTapiVisit = splitDataSettingDatafixed("konsulTapiVisit");

		List<Integer> listIndikatorPelayanan = Arrays.asList(Master.IndikatorKinerjaJamKerja.INDIKATOR_PELAYANAN_MEDIS);

		List<Integer> listIdNonjadwal = shiftKerjaDao.findListNonjadwal();

		List<Integer> listIdDokterKsmUmum = pegawaiDao.getDokterByKelompokKerja(Master.SubUnitKerja.KK_UMUM);

		List<Integer> listIdDokterLabPA = pegawaiDao.getDokterByKelompokKerja(Master.SubUnitKerja.KK_PATOLOGI_ANATOMI);
		List<Integer> listIdDJPLabPA = splitDataSettingDatafixed("penunjang_pa");

		List<Integer> listIdDokterLabPK = pegawaiDao.getDokterByKelompokKerja(Master.SubUnitKerja.KK_PATOLOGI_KLINIK);
		List<Integer> listIdDJPLabPK = splitDataSettingDatafixed("penunjang_pk");

		List<Integer> listIdDokterRad = pegawaiDao.getDokterByKelompokKerja(Master.SubUnitKerja.KK_RADIOLOGI);
		List<Integer> listIdDJPRad = splitDataSettingDatafixed("penunjang_radiologi");

		List<Integer> listIdDJPUtama = splitDataSettingDatafixed("medis_utama");

		List<Integer> listIdLaboranRadiolog = mapPegawaiLaboratRadiologiDao.findPegawaiLaboranRadiolog();
		List<Integer> listIdDJPAdmPK = splitDataSettingDatafixed("admin_nonpk");

		List<Map<String, Object>> dataRaw = ikiDanRemunerasiDao.getDataLayananJamKerja(calTglAwal.getTime(),
				bulan.getTime(), pssbAwal, pssbAkhir, listIdNonjadwal, Master.JenisPegawai.DOKTER,
				Arrays.asList(Master.Departemen.GRUP_RAWAT_JALAN), Arrays.asList(Master.KategoryPegawai.REMUN),
				Arrays.asList(Master.KedudukanPegawai.INACTIVE_LOGIN), Arrays.asList(Master.UnitKerja.KSM),
				Arrays.asList(Master.JenisProduk.NONTINDAKAN), Arrays.asList(Master.KelompokPasien.KELOMPOK_BPJS),
				Master.Produk.KARCIS);
		
		List<Integer> idsDokterUmumIGD = splitDataSettingDatafixed("pr_dokter_umum_igd");
		List<Integer> idsKonsultasiDokterJaga = splitDataSettingDatafixed("pr_konsultasi_dokter_jaga");
		List<Integer> idsPenunjangBukanAnestesi = splitDataSettingDatafixed("pr_penunjang_nonanestesi");

		// filter detail jenis produk
		for (Map<String, Object> map : dataRaw) {
			if (listIdDokterLabPA.contains(map.get("pegawaiId"))) {
				List<Integer> listIdTempLabPA = new ArrayList<Integer>(listIdDJPLabPA);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempLabPA);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempLabPA.addAll(listIdTempAdmPK);
					}
				}
				if (listIdTempLabPA.contains(map.get("djpId"))) {
					dataLayananRaw.add(map);
				}
			} else if (listIdDokterLabPK.contains(map.get("pegawaiId"))) {
				List<Integer> listIdTempLabPK = new ArrayList<Integer>(listIdDJPLabPK);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempLabPK);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempLabPK.addAll(listIdTempAdmPK);
					}
				}
				if (listIdTempLabPK.contains(map.get("djpId"))) {
					dataLayananRaw.add(map);
				}
			} else if (listIdDokterRad.contains(map.get("pegawaiId"))) {
				List<Integer> listIdTempRad = new ArrayList<Integer>(listIdDJPRad);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempRad);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempRad.addAll(listIdTempAdmPK);
					}
				}
				if (listIdTempRad.contains(map.get("djpId"))) {
					dataLayananRaw.add(map);
				}
			} else if (listIdDJPUtama.contains(map.get("djpId"))) {
				List<Integer> listIdTempUtama = new ArrayList<Integer>(listIdDJPUtama);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempUtama);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempUtama.addAll(listIdTempAdmPK);
					}
				}
				if (listIdTempUtama.contains(map.get("djpId"))) {
					dataLayananRaw.add(map);
				}
			} else if (!listIdDJPUtama.contains(map.get("djpId"))) {
				List<Integer> listIdTempUtama = new ArrayList<Integer>(listIdDJPUtama);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempUtama);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempUtama.addAll(listIdTempAdmPK);
					}
				}
				if (!listIdTempUtama.contains(map.get("djpId"))
						&& idsDokterUmumIGD.contains(map.get("idTindakan"))
						&& listIdDokterKsmUmum.contains(map.get("pegawaiId"))
						&& Master.Departemen.IGD.equals(map.get("idDepartemen"))) {
					dataLayananRaw.add(map);
				}
			}
		}

		// get_kategori_bulan
		List<String> listBulanPelayanan = new ArrayList<>();
		List<String> listBulanPelayananSorted = new ArrayList<>();
		for (Map<String, Object> dat : dataLayananRaw) {
			if (!listBulanPelayanan.contains(sdf.format(dat.get("tglPelayanan")))) {
				listBulanPelayanan.add(sdf.format(dat.get("tglPelayanan")));
			}
		}
		listBulanPelayananSorted = listBulanPelayanan.stream().sorted().collect(Collectors.toList());

		// get_kategori_kelompok_kerja
		List<Integer> listIdKK = new ArrayList<>();
		for (Map<String, Object> map : dataLayananRaw) {
			if (!listIdKK.contains(map.get("idKelompokKerja"))) {
				listIdKK.add(Integer.parseInt(map.get("idKelompokKerja").toString()));
			}
		}

		List<Map<String, Object>> listKelompokKerja = subunitKerjaDao.findSubDanUnitKerjaById(listIdKK);

		List<Map<String, Object>> dataLastTargetLayanan = targetLayananDao.getLastTargetLayananJamKerja(
				sdf.format(calTglAwal.getTime()), sdf.format(bulan.getTime()),
				Arrays.asList(Master.IndikatorKinerjaJamKerja.INDIKATOR_PELAYANAN_MEDIS));

		List<Map<String, Object>> filterTarget = new ArrayList<>();
		// filtering target
		for (Map<String, Object> mapData : dataLastTargetLayanan) {
			boolean isContained = false;
			for (Map<String, Object> mapFilter : filterTarget) {
				if (mapData.get("kelompokKerjaId").equals(mapFilter.get("kelompokKerjaId"))
						&& mapData.get("indikatorId").equals(mapFilter.get("indikatorId"))
						&& mapData.get("periode").equals(mapFilter.get("periode"))) {
					isContained = true;
					break;
				}
			}
			if (!isContained) {
				Map<String, Object> mapFilter = new HashMap<>();
				mapFilter.put("kelompokKerjaId", mapData.get("kelompokKerjaId"));
				mapFilter.put("indikatorId", mapData.get("indikatorId"));
				mapFilter.put("periode", mapData.get("periode"));
				filterTarget.add(mapFilter);
			}
		}

		List<Map<String, Object>> dataTargetFiltered = new ArrayList<>();
		// processing Target
		for (Map<String, Object> mapFilter : filterTarget) {
			for (Map<String, Object> mapData : dataLastTargetLayanan) {
				if (mapData.get("kelompokKerjaId").equals(mapFilter.get("kelompokKerjaId"))
						&& mapData.get("indikatorId").equals(mapFilter.get("indikatorId"))
						&& mapData.get("periode").equals(mapFilter.get("periode"))) {
					dataTargetFiltered.add(mapData);
					break;
				}
			}
		}

		List<Map<String, Object>> dataSkoringRaw = skoringTindakanMedisDao.findLatestActiveSkorByKelompokKerja();

		List<Map<String, Object>> filterSkoring = new ArrayList<>();
		// filtering skoring
		for (Map<String, Object> mapData : dataSkoringRaw) {
			boolean isContained = false;
			for (Map<String, Object> mapFilter : filterSkoring) {
				if (mapData.get("produkId").equals(mapFilter.get("produkId"))
						&& mapData.get("kelompokKerjaId").equals(mapFilter.get("kelompokKerjaId"))) {
					isContained = true;
					break;
				}
			}
			if (!isContained) {
				Map<String, Object> mapFilter = new HashMap<>();
				mapFilter.put("produkId", mapData.get("produkId"));
				mapFilter.put("kelompokKerjaId", mapData.get("kelompokKerjaId"));
				filterSkoring.add(mapFilter);
			}
		}

		List<Map<String, Object>> dataSkoringFiltered = new ArrayList<>();
		// processing skoring
		for (Map<String, Object> mapFilter : filterSkoring) {
			for (Map<String, Object> mapData : dataSkoringRaw) {
				if (mapFilter.get("produkId").equals(mapData.get("produkId"))
						&& mapFilter.get("kelompokKerjaId").equals(mapData.get("kelompokKerjaId"))) {
					dataSkoringFiltered.add(mapData);
					break;
				}
			}
		}

		List<Map<String, Object>> dataLayananScored = new ArrayList<>();
		// scoring data layanan
		for (Map<String, Object> layanan : dataLayananRaw) {
			for (Map<String, Object> skoring : dataSkoringFiltered) {
				if (layanan.get("idTindakan").equals(skoring.get("produkId"))
						&& layanan.get("idKelompokKerja").equals(skoring.get("kelompokKerjaId"))
						&& (((Date) skoring.get("tglBerlaku")).before(((Date) layanan.get("tglPelayanan")))
								|| ((Date) skoring.get("tglBerlaku")).equals(((Date) layanan.get("tglPelayanan"))))) {

					if (Double.valueOf(layanan.get("hargaDiskon").toString()) > 0.0
							&& (CommonUtil.isNullOrEmpty(layanan.get("statusDiskon"))
									|| Integer.valueOf(layanan.get("statusDiskon").toString()).equals(0))) {
						layanan.put("jumlahTindakan", 0.0);
					} else if (listRuangEks.contains(layanan.get("idRuangan"))
							&& !layanan.get("namaTindakan").toString().toLowerCase().contains(Master.KONSUL)
							&& !layanan.get("namaTindakan").toString().toLowerCase().contains(Master.VISIT)) {
						layanan.put("jumlahTindakan",
								Double.valueOf(layanan.get("jumlahTindakan").toString())
										* Double.valueOf(skoring.get("skor").toString())
										* Master.Remunerasi.PERSEN_SKOR_EKSEKUTIF);
					} else if (layanan.get("jenisPetugasId").equals(Master.JenisPetugasPelaksana.ASISTEN_SPESIALIS)) {
						layanan.put("jumlahTindakan",
								Double.valueOf(layanan.get("jumlahTindakan").toString())
										* Double.valueOf(skoring.get("skor").toString())
										* Master.Remunerasi.PERSEN_SKOR_ASISTEN_SPESIALIS);
					} else {
						layanan.put("jumlahTindakan", Double.valueOf(layanan.get("jumlahTindakan").toString())
								* Double.valueOf(skoring.get("skor").toString()));
					}

					break;
				}
			}
			dataLayananScored.add(layanan);
		}

		for (Map<String, Object> kelompokKerja : listKelompokKerja) {
			for (Integer idIndikator : listIndikatorPelayanan) {
				TargetLayananJamKerjaVO resultVo = new TargetLayananJamKerjaVO();
				List<TargetLayananJamKerjaDetailVO> listDetail = new ArrayList<>();

				double capaianTriwulanKE = 0.0;
				double capaianTriwulanKG = 0.0;
				double capaianTriwulanKR = 0.0;
				double capaianTriwulanTE = 0.0;
				double capaianTriwulanTG = 0.0;
				double capaianTriwulanTO = 0.0;
				double capaianTriwulanTR = 0.0;
				double capaianTriwulanVI = 0.0;

				int i = 0;
				for (String datePelayanan : listBulanPelayananSorted) {
					i++;
					TargetLayananJamKerjaDetailVO detail = new TargetLayananJamKerjaDetailVO();

					double capaianBulanan = 0.0;
					double targetBulanan = 0.0;
					for (Map<String, Object> data : dataLayananScored) {
						if (kelompokKerja.get("subunitKerjaId").equals(data.get("idKelompokKerja"))
								&& datePelayanan.equals(sdf.format(data.get("tglPelayanan")))) {
							if (idIndikator.equals(Master.IndikatorKinerjaJamKerja.VISITE)
									&& (listKonsulTapiVisit.contains(data.get("idTindakan")) || data.get("namaTindakan")
											.toString().toLowerCase().contains(Master.VISIT))) {
								capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
								if (i < listBulanPelayananSorted.size()) {
									capaianTriwulanVI += Double.valueOf(data.get("jumlahTindakan").toString());
									for (Map<String, Object> target : dataTargetFiltered) {
										if (kelompokKerja.get("subunitKerjaId").equals(target.get("kelompokKerjaId"))
												&& idIndikator.equals(target.get("indikatorId"))
												&& datePelayanan.equals(target.get("periode"))) {
											targetBulanan = Double.valueOf(target.get("target").toString());
											break;
										}
									}
								} else if (i == listBulanPelayananSorted.size()) {
									targetBulanan = Math
											.floor(capaianTriwulanVI / (listBulanPelayananSorted.size() - 1));
								}
							} else if (idIndikator.equals(Master.IndikatorKinerjaJamKerja.KONSUL_EKS)
									&& data.get("namaTindakan").toString().toLowerCase().contains(Master.KONSUL)
									&& listRuangEks.contains(data.get("idRuangan"))) {
								capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
								if (i < listBulanPelayananSorted.size()) {
									capaianTriwulanKE += Double.valueOf(data.get("jumlahTindakan").toString());
									for (Map<String, Object> target : dataTargetFiltered) {
										if (kelompokKerja.get("subunitKerjaId").equals(target.get("kelompokKerjaId"))
												&& idIndikator.equals(target.get("indikatorId"))
												&& datePelayanan.equals(target.get("periode"))) {
											targetBulanan = Double.valueOf(target.get("target").toString());
											break;
										}
									}
								} else if (i == listBulanPelayananSorted.size()) {
									targetBulanan = Math
											.floor(capaianTriwulanKE / (listBulanPelayananSorted.size() - 1));
								}
							} else if (idIndikator.equals(Master.IndikatorKinerjaJamKerja.KONSUL_GADAR)
									&& data.get("namaTindakan").toString().toLowerCase().contains(Master.KONSUL)
									&& data.get("idDepartemen").equals(Master.Departemen.IGD)) {
								capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
								if (i < listBulanPelayananSorted.size()) {
									capaianTriwulanKG += Double.valueOf(data.get("jumlahTindakan").toString());
									for (Map<String, Object> target : dataTargetFiltered) {
										if (kelompokKerja.get("subunitKerjaId").equals(target.get("kelompokKerjaId"))
												&& idIndikator.equals(target.get("indikatorId"))
												&& datePelayanan.equals(target.get("periode"))) {
											targetBulanan = Double.valueOf(target.get("target").toString());
											break;
										}
									}
								} else if (i == listBulanPelayananSorted.size()) {
									targetBulanan = Math
											.floor(capaianTriwulanKG / (listBulanPelayananSorted.size() - 1));
								}
							} else if (idIndikator.equals(Master.IndikatorKinerjaJamKerja.KONSUL_REG)
									&& data.get("namaTindakan").toString().toLowerCase().contains(Master.KONSUL)) {
								capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
								if (i < listBulanPelayananSorted.size()) {
									capaianTriwulanKR += Double.valueOf(data.get("jumlahTindakan").toString());
									for (Map<String, Object> target : dataTargetFiltered) {
										if (kelompokKerja.get("subunitKerjaId").equals(target.get("kelompokKerjaId"))
												&& idIndikator.equals(target.get("indikatorId"))
												&& datePelayanan.equals(target.get("periode"))) {
											targetBulanan = Double.valueOf(target.get("target").toString());
											break;
										}
									}
								} else if (i == listBulanPelayananSorted.size()) {
									targetBulanan = Math
											.floor(capaianTriwulanKR / (listBulanPelayananSorted.size() - 1));
								}
							} else if (idIndikator.equals(Master.IndikatorKinerjaJamKerja.TINDAKAN_EKS)
									&& listRuangEks.contains(data.get("idRuangan"))) {
								capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
								if (i < listBulanPelayananSorted.size()) {
									capaianTriwulanTE += Double.valueOf(data.get("jumlahTindakan").toString());
									for (Map<String, Object> target : dataTargetFiltered) {
										if (kelompokKerja.get("subunitKerjaId").equals(target.get("kelompokKerjaId"))
												&& idIndikator.equals(target.get("indikatorId"))
												&& datePelayanan.equals(target.get("periode"))) {
											targetBulanan = Double.valueOf(target.get("target").toString());
											break;
										}
									}
								} else if (i == listBulanPelayananSorted.size()) {
									targetBulanan = Math
											.floor(capaianTriwulanTE / (listBulanPelayananSorted.size() - 1));
								}
							} else if (idIndikator.equals(Master.IndikatorKinerjaJamKerja.TINDAKAN_GADAR)
									&& data.get("idDepartemen").equals(Master.Departemen.IGD)) {
								capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
								if (i < listBulanPelayananSorted.size()) {
									capaianTriwulanTG += Double.valueOf(data.get("jumlahTindakan").toString());
									for (Map<String, Object> target : dataTargetFiltered) {
										if (kelompokKerja.get("subunitKerjaId").equals(target.get("kelompokKerjaId"))
												&& idIndikator.equals(target.get("indikatorId"))
												&& datePelayanan.equals(target.get("periode"))) {
											targetBulanan = Double.valueOf(target.get("target").toString());
											break;
										}
									}
								} else if (i == listBulanPelayananSorted.size()) {
									targetBulanan = Math
											.floor(capaianTriwulanTG / (listBulanPelayananSorted.size() - 1));
								}
							} else if (idIndikator.equals(Master.IndikatorKinerjaJamKerja.TINDAKAN_OPS)
									&& data.get("idRuangan").equals(Master.Ruangan.OK)) {
								capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
								if (i < listBulanPelayananSorted.size()) {
									capaianTriwulanTO += Double.valueOf(data.get("jumlahTindakan").toString());
									for (Map<String, Object> target : dataTargetFiltered) {
										if (kelompokKerja.get("subunitKerjaId").equals(target.get("kelompokKerjaId"))
												&& idIndikator.equals(target.get("indikatorId"))
												&& datePelayanan.equals(target.get("periode"))) {
											targetBulanan = Double.valueOf(target.get("target").toString());
											break;
										}
									}
								} else if (i == listBulanPelayananSorted.size()) {
									targetBulanan = Math
											.floor(capaianTriwulanTO / (listBulanPelayananSorted.size() - 1));
								}
							} else if (idIndikator.equals(Master.IndikatorKinerjaJamKerja.TINDAKAN_REG)) {
								capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
								if (i < listBulanPelayananSorted.size()) {
									capaianTriwulanTR += Double.valueOf(data.get("jumlahTindakan").toString());
									for (Map<String, Object> target : dataTargetFiltered) {
										if (kelompokKerja.get("subunitKerjaId").equals(target.get("kelompokKerjaId"))
												&& idIndikator.equals(target.get("indikatorId"))
												&& datePelayanan.equals(target.get("periode"))) {
											targetBulanan = Double.valueOf(target.get("target").toString());
											break;
										}
									}
								} else if (i == listBulanPelayananSorted.size()) {
									targetBulanan = Math
											.floor(capaianTriwulanTR / (listBulanPelayananSorted.size() - 1));
								}
							}
						}
					}
					Date bulanPelayanan = sdf.parse(datePelayanan);

					detail.setDate(datePelayanan);
					detail.setBulan(sdfINA.format(bulanPelayanan));
					detail.setTarget(targetBulanan);
					detail.setCapaian(capaianBulanan);
					listDetail.add(detail);
				}
				if (Double.valueOf(listDetail.get(listDetail.size() - 1).getTarget()) > 0.0) {
					resultVo.setDetail(listDetail);
					SubUnitKerjaPegawaiVO kelompokKerjaVO = new SubUnitKerjaPegawaiVO();
					kelompokKerjaVO.setId(Integer.valueOf(kelompokKerja.get("subunitKerjaId").toString()));

					UnitKerjaPegawaiVO unitKerjaVO = new UnitKerjaPegawaiVO();
					unitKerjaVO.setId(Integer.valueOf(kelompokKerja.get("unitKerjaId").toString()));
					kelompokKerjaVO.setUnitKerja(unitKerjaVO);

					IndikatorKinerjaDetailVO detailIndikatorVO = new IndikatorKinerjaDetailVO();
					detailIndikatorVO.setId(idIndikator);

					resultVo.setKelompokKerja(kelompokKerjaVO);
					resultVo.setIndikator(detailIndikatorVO);

					saveTargetCapaianLayananKelompokKerja(resultVo, sdf.parse(strPeriode));
				}
			}
		}
	}

	@Override
	@Transactional(readOnly = false)
	public void saveTargetCapaianLayananKelompokKerja(TargetLayananJamKerjaVO vo, Date periodeHitung)
			throws ParseException {
		Date tglHitung = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		for (TargetLayananJamKerjaDetailVO detail : vo.getDetail()) {
			SubUnitKerjaPegawai kelompokKerja = new SubUnitKerjaPegawai();
			kelompokKerja.setId(vo.getKelompokKerja().getId());

			UnitKerjaPegawai unitKerja = new UnitKerjaPegawai();
			unitKerja.setId(vo.getKelompokKerja().getUnitKerja().getId());
			kelompokKerja.setUnitKerja(unitKerja);

			IndikatorKinerjaDetail indikator = new IndikatorKinerjaDetail();
			indikator.setId(vo.getIndikator().getId());

			TargetLayanan targetLayanan = new TargetLayanan();
			targetLayanan.setKdProfile((short) 0);
			targetLayanan.setStatusEnabled(true);
			targetLayanan.setUnitKerjaPegawai(unitKerja);
			targetLayanan.setSubUnitKerjaPegawai(kelompokKerja);
			targetLayanan.setTglHitung(tglHitung);
			targetLayanan.setPeriode(sdf.parse(detail.getDate()));
			targetLayanan.setIndikatorDetail(indikator);
			targetLayanan.setTarget(detail.getTarget());
			targetLayanan.setCapaian(detail.getCapaian());

			targetLayananDao.save(targetLayanan);
			if (sdf.format(targetLayanan.getPeriode()).equals(sdf.format(periodeHitung))) {
				List<Map<String, Object>> dataPegawai = mapPegawaiJabatanToUnitKerjaDao
						.findPegawaiJabatanByKelompokKerja(targetLayanan.getSubUnitKerjaPegawai().getId(),
								Arrays.asList(Master.KategoryPegawai.REMUN), Master.JenisPegawai.DOKTER,
								Arrays.asList(Master.KedudukanPegawai.INACTIVE_LOGIN));

				Double detailTarget = Math.floor(targetLayanan.getTarget() / dataPegawai.size());
				if (detailTarget < 1.0) {
					detailTarget = 1.0;
				}

				for (Map<String, Object> map : dataPegawai) {
					LogbookKinerjaDokter logbook = new LogbookKinerjaDokter();
					logbook.setKdProfile((short) 0);
					logbook.setStatusEnabled(true);
					logbook.setBulan(targetLayanan.getPeriode());
					logbook.setDetailTarget(detailTarget);
					logbook.setDetailCapaian(0.0);
					logbook.setIndikatorDetail(targetLayanan.getIndikatorDetail());
					Jabatan jabatan = new Jabatan();
					jabatan.setId(Integer.valueOf(map.get("jabatanId").toString()));
					logbook.setJabatan(jabatan);
					Pegawai pegawai = new Pegawai();
					pegawai.setId(Integer.valueOf(map.get("pegawaiId").toString()));
					logbook.setPegawai(pegawai);
					logbook.setTglHitung(tglHitung);

					logbookKinerjaDokterDao.save(logbook);
				}
			}
		}
	}

	@Override
	public void autoSaveTargetCapaianLayananLuarJamKerja(String strPeriode) throws ParseException {
		List<Map<String, Object>> dataLayananRaw = new ArrayList<>();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		SimpleDateFormat sdfINA = new SimpleDateFormat("MMMM yyyy", new Locale("in", "ID"));

		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

		Date periode = sdf.parse(strPeriode);

		// get_few_months_earlier
		Calendar calTglAwal = Calendar.getInstance();
		calTglAwal.setTime(periode);
		calTglAwal.set(Calendar.HOUR_OF_DAY, 0);
		calTglAwal.set(Calendar.MINUTE, 0);
		calTglAwal.set(Calendar.SECOND, 0);
		calTglAwal.set(Calendar.DAY_OF_MONTH, 1);
		calTglAwal.add(Calendar.MONTH, -Integer.valueOf(GetSettingDataFixed("jmlBlnHitungTargetMedis")));

		// get_this_period
		Calendar bulan = Calendar.getInstance();
		bulan.setTime(periode);
		bulan.set(Calendar.HOUR_OF_DAY, 23);
		bulan.set(Calendar.MINUTE, 59);
		bulan.set(Calendar.SECOND, 0);
		bulan.set(Calendar.DAY_OF_MONTH, bulan.getActualMaximum(Calendar.DAY_OF_MONTH));

		LocalDateTime PSBBDate = LocalDateTime.of(2020, 9, 14, 0, 0, 0);
		LocalDateTime PSBBEnd = LocalDateTime.parse(GetSettingDataFixed("psbbperiod"), dtf);

		Date pssbAwal = Date.from(PSBBDate.atZone(ZoneId.systemDefault()).toInstant());
		Date pssbAkhir = Date.from(PSBBEnd.atZone(ZoneId.systemDefault()).toInstant());

		List<Integer> listRuangEks = splitDataSettingDatafixed("IdRuanganEksekutif");
		List<Integer> listKonsulTapiVisit = splitDataSettingDatafixed("konsulTapiVisit");

		List<Integer> listIndikatorPelayanan = Arrays
				.asList(Master.IndikatorKinerjaLuarJamKerja.INDIKATOR_PELAYANAN_MEDIS);

		List<Integer> listIdNonjadwal = shiftKerjaDao.findListNonjadwal();

		List<Integer> listIdDokterKsmUmum = pegawaiDao.getDokterByKelompokKerja(Master.SubUnitKerja.KK_UMUM);

		List<Integer> listIdDokterLabPA = pegawaiDao.getDokterByKelompokKerja(Master.SubUnitKerja.KK_PATOLOGI_ANATOMI);
		List<Integer> listIdDJPLabPA = splitDataSettingDatafixed("penunjang_pa");

		List<Integer> listIdDokterLabPK = pegawaiDao.getDokterByKelompokKerja(Master.SubUnitKerja.KK_PATOLOGI_KLINIK);
		List<Integer> listIdDJPLabPK = splitDataSettingDatafixed("penunjang_pk");

		List<Integer> listIdDokterRad = pegawaiDao.getDokterByKelompokKerja(Master.SubUnitKerja.KK_RADIOLOGI);
		List<Integer> listIdDJPRad = splitDataSettingDatafixed("penunjang_radiologi");

		List<Integer> listIdDJPUtama = splitDataSettingDatafixed("medis_utama");

		List<Integer> listIdLaboranRadiolog = mapPegawaiLaboratRadiologiDao.findPegawaiLaboranRadiolog();
		List<Integer> listIdDJPAdmPK = splitDataSettingDatafixed("admin_nonpk");

		List<Map<String, Object>> dataRaw = ikiDanRemunerasiDao.getDataLayananLuarJamKerja(calTglAwal.getTime(),
				bulan.getTime(), pssbAwal, pssbAkhir, listIdNonjadwal, Master.JenisPegawai.DOKTER,
				Arrays.asList(Master.KedudukanPegawai.INACTIVE_LOGIN),
				Arrays.asList(Master.Departemen.GRUP_RAWAT_JALAN), Arrays.asList(Master.UnitKerja.KSM),
				Arrays.asList(Master.JenisProduk.NONTINDAKAN), Arrays.asList(Master.KelompokPasien.KELOMPOK_BPJS),
				Master.Produk.KARCIS);
		
		List<Integer> idsDokterUmumIGD = splitDataSettingDatafixed("pr_dokter_umum_igd");
		List<Integer> idsKonsultasiDokterJaga = splitDataSettingDatafixed("pr_konsultasi_dokter_jaga");
		List<Integer> idsPenunjangBukanAnestesi = splitDataSettingDatafixed("pr_penunjang_nonanestesi");

		// filter detail jenis produk
		for (Map<String, Object> map : dataRaw) {
			if (listIdDokterLabPA.contains(map.get("pegawaiId"))) {
				List<Integer> listIdTempLabPA = new ArrayList<Integer>(listIdDJPLabPA);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempLabPA);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempLabPA.addAll(listIdTempAdmPK);
					}
				}
				if (listIdTempLabPA.contains(map.get("djpId"))) {
					dataLayananRaw.add(map);
				}
			} else if (listIdDokterLabPK.contains(map.get("pegawaiId"))) {
				List<Integer> listIdTempLabPK = new ArrayList<Integer>(listIdDJPLabPK);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempLabPK);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempLabPK.addAll(listIdTempAdmPK);
					}
				}
				if (listIdTempLabPK.contains(map.get("djpId"))) {
					dataLayananRaw.add(map);
				}
			} else if (listIdDokterRad.contains(map.get("pegawaiId"))) {
				List<Integer> listIdTempRad = new ArrayList<Integer>(listIdDJPRad);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempRad);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempRad.addAll(listIdTempAdmPK);
					}
				}
				if (listIdTempRad.contains(map.get("djpId"))) {
					dataLayananRaw.add(map);
				}
			} else if (listIdDJPUtama.contains(map.get("djpId"))) {
				List<Integer> listIdTempUtama = new ArrayList<Integer>(listIdDJPUtama);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempUtama);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempUtama.addAll(listIdTempAdmPK);
					}
				}
				if (listIdTempUtama.contains(map.get("djpId"))) {
					dataLayananRaw.add(map);
				}
			} else if (!listIdDJPUtama.contains(map.get("djpId"))) {
				List<Integer> listIdTempUtama = new ArrayList<Integer>(listIdDJPUtama);
				List<Integer> listIdTempAdmPK = new ArrayList<Integer>(listIdDJPAdmPK);
				if (listIdLaboranRadiolog.contains(map.get("pegawaiId"))) {
					listIdTempAdmPK.removeAll(listIdTempUtama);
					if (CommonUtil.isNotNullOrEmpty(listIdTempAdmPK)) {
						listIdTempUtama.addAll(listIdTempAdmPK);
					}
				}
				if (!listIdTempUtama.contains(map.get("djpId"))
						&& idsDokterUmumIGD.contains(map.get("idTindakan"))
						&& listIdDokterKsmUmum.contains(map.get("pegawaiId"))
						&& Master.Departemen.IGD.equals(map.get("idDepartemen"))) {
					dataLayananRaw.add(map);
				}
			}
		}

		// get_kategori_bulan
		List<String> listBulanPelayanan = new ArrayList<>();
		List<String> listBulanPelayananSorted = new ArrayList<>();
		for (Map<String, Object> dat : dataLayananRaw) {
			if (!listBulanPelayanan.contains(sdf.format(dat.get("tglPelayanan")))) {
				listBulanPelayanan.add(sdf.format(dat.get("tglPelayanan")));
			}
		}
		listBulanPelayananSorted = listBulanPelayanan.stream().sorted().collect(Collectors.toList());

		// get_kategori_pegawai
		List<Integer> listIdPegawai = new ArrayList<>();
		for (Map<String, Object> map : dataLayananRaw) {
			if (!listIdPegawai.contains(map.get("pegawaiId"))) {
				listIdPegawai.add(Integer.parseInt(map.get("pegawaiId").toString()));
			}
		}
		List<Map<String, Object>> listPegawai = pegawaiDao.findPegawaiByListId(listIdPegawai);

		// get_kategori_jabatan
		List<Integer> listIdJabatan = new ArrayList<>();
		for (Map<String, Object> map : dataLayananRaw) {
			if (!listIdJabatan.contains(map.get("jabatanId"))) {
				listIdJabatan.add(Integer.parseInt(map.get("jabatanId").toString()));
			}
		}
		List<Map<String, Object>> listJabatan = jabatanDao.findJabatanByListId(listIdJabatan);

		List<Map<String, Object>> dataLastTargetLayanan = logbookKinerjaDokterDao.getLastTargetLayananLuarJamKerja(
				sdf.format(calTglAwal.getTime()), sdf.format(bulan.getTime()),
				Arrays.asList(Master.IndikatorKinerjaLuarJamKerja.INDIKATOR_PELAYANAN_MEDIS));

		List<Map<String, Object>> filterTarget = new ArrayList<>();
		// filtering target
		for (Map<String, Object> mapData : dataLastTargetLayanan) {
			boolean isContained = false;
			for (Map<String, Object> mapFilter : filterTarget) {
				if (mapData.get("pegawaiId").equals(mapFilter.get("pegawaiId"))
						&& mapData.get("jabatanId").equals(mapFilter.get("jabatanId"))
						&& mapData.get("indikatorId").equals(mapFilter.get("indikatorId"))
						&& mapData.get("periode").equals(mapFilter.get("periode"))) {
					isContained = true;
					break;
				}
			}
			if (!isContained) {
				Map<String, Object> mapFilter = new HashMap<>();
				mapFilter.put("pegawaiId", mapData.get("pegawaiId"));
				mapFilter.put("jabatanId", mapData.get("jabatanId"));
				mapFilter.put("indikatorId", mapData.get("indikatorId"));
				mapFilter.put("periode", mapData.get("periode"));
				filterTarget.add(mapFilter);
			}
		}

		List<Map<String, Object>> dataTargetFiltered = new ArrayList<>();
		// processing Target
		for (Map<String, Object> mapFilter : filterTarget) {
			for (Map<String, Object> mapData : dataLastTargetLayanan) {
				if (mapData.get("pegawaiId").equals(mapFilter.get("pegawaiId"))
						&& mapData.get("jabatanId").equals(mapFilter.get("jabatanId"))
						&& mapData.get("indikatorId").equals(mapFilter.get("indikatorId"))
						&& mapData.get("periode").equals(mapFilter.get("periode"))) {
					dataTargetFiltered.add(mapData);
					break;
				}
			}
		}

		List<Map<String, Object>> dataSkoringRaw = skoringTindakanMedisDao.findLatestActiveSkorByDokter();

		List<Map<String, Object>> filterSkoring = new ArrayList<>();
		// filtering skoring
		for (Map<String, Object> mapData : dataSkoringRaw) {
			boolean isContained = false;
			for (Map<String, Object> mapFilter : filterSkoring) {
				if (mapData.get("produkId").equals(mapFilter.get("produkId"))
						&& mapData.get("pegawaiId").equals(mapFilter.get("pegawaiId"))
						&& mapData.get("jabatanId").equals(mapFilter.get("jabatanId"))) {
					isContained = true;
					break;
				}
			}
			if (!isContained) {
				Map<String, Object> mapFilter = new HashMap<>();
				mapFilter.put("produkId", mapData.get("produkId"));
				mapFilter.put("pegawaiId", mapData.get("pegawaiId"));
				mapFilter.put("jabatanId", mapData.get("jabatanId"));
				filterSkoring.add(mapFilter);
			}
		}

		List<Map<String, Object>> dataSkoringFiltered = new ArrayList<>();
		// processing skoring
		for (Map<String, Object> mapFilter : filterSkoring) {
			for (Map<String, Object> mapData : dataSkoringRaw) {
				if (mapFilter.get("produkId").equals(mapData.get("produkId"))
						&& mapFilter.get("pegawaiId").equals(mapData.get("pegawaiId"))
						&& mapFilter.get("jabatanId").equals(mapData.get("jabatanId"))) {
					dataSkoringFiltered.add(mapData);
					break;
				}
			}
		}

		List<Map<String, Object>> dataLayananScored = new ArrayList<>();
		// scoring data layanan
		for (Map<String, Object> layanan : dataLayananRaw) {
			for (Map<String, Object> skoring : dataSkoringFiltered) {
				if (layanan.get("idTindakan").equals(skoring.get("produkId"))
						&& layanan.get("pegawaiId").equals(skoring.get("pegawaiId"))
						&& layanan.get("jabatanId").equals(skoring.get("jabatanId"))
						&& (((Date) skoring.get("tglBerlaku")).before(((Date) layanan.get("tglPelayanan")))
								|| ((Date) skoring.get("tglBerlaku")).equals(((Date) layanan.get("tglPelayanan"))))) {

					if (Double.valueOf(layanan.get("hargaDiskon").toString()) > 0.0
							&& (CommonUtil.isNullOrEmpty(layanan.get("statusDiskon"))
									|| Integer.valueOf(layanan.get("statusDiskon").toString()).equals(0))) {
						layanan.put("jumlahTindakan", 0.0);
					} else if (listRuangEks.contains(layanan.get("idRuangan"))
							&& !layanan.get("namaTindakan").toString().toLowerCase().contains(Master.KONSUL)
							&& !layanan.get("namaTindakan").toString().toLowerCase().contains(Master.VISIT)) {
						layanan.put("jumlahTindakan",
								Double.valueOf(layanan.get("jumlahTindakan").toString())
										* Double.valueOf(skoring.get("skor").toString())
										* Master.Remunerasi.PERSEN_SKOR_LUAR_JAM_KERJA);
					} else if (layanan.get("jenisPetugasId").equals(Master.JenisPetugasPelaksana.ASISTEN_SPESIALIS)) {
						layanan.put("jumlahTindakan",
								Double.valueOf(layanan.get("jumlahTindakan").toString())
										* Double.valueOf(skoring.get("skor").toString())
										* Master.Remunerasi.PERSEN_SKOR_LUAR_JAM_KERJA
										* Master.Remunerasi.PERSEN_SKOR_ASISTEN_SPESIALIS);
					} else {
						layanan.put("jumlahTindakan",
								Double.valueOf(layanan.get("jumlahTindakan").toString())
										* Double.valueOf(skoring.get("skor").toString())
										* Master.Remunerasi.PERSEN_SKOR_LUAR_JAM_KERJA);
					}

					break;
				}
			}
			dataLayananScored.add(layanan);
		}

		for (Map<String, Object> pegawai : listPegawai) {
			for (Map<String, Object> jabatan : listJabatan) {
				for (Integer idIndikator : listIndikatorPelayanan) {
					TargetLayananLuarJamKerjaVO resultVo = new TargetLayananLuarJamKerjaVO();
					List<TargetLayananLuarJamKerjaDetailVO> listDetail = new ArrayList<>();

					double capaianTriwulanKE = 0.0;
					double capaianTriwulanKG = 0.0;
					double capaianTriwulanKR = 0.0;
					double capaianTriwulanTE = 0.0;
					double capaianTriwulanTG = 0.0;
					double capaianTriwulanTO = 0.0;
					double capaianTriwulanTR = 0.0;
					double capaianTriwulanVI = 0.0;

					int i = 0;
					for (String datePelayanan : listBulanPelayananSorted) {
						i++;
						TargetLayananLuarJamKerjaDetailVO detail = new TargetLayananLuarJamKerjaDetailVO();

						double capaianBulanan = 0.0;
						double targetBulanan = 0.0;
						for (Map<String, Object> data : dataLayananScored) {
							if (pegawai.get("pegawaiId").equals(data.get("pegawaiId"))
									&& jabatan.get("jabatanId").equals(data.get("jabatanId"))
									&& datePelayanan.equals(sdf.format(data.get("tglPelayanan")))) {
								if (idIndikator.equals(Master.IndikatorKinerjaLuarJamKerja.VISITE)
										&& (listKonsulTapiVisit.contains(data.get("idTindakan")) || data
												.get("namaTindakan").toString().toLowerCase().contains(Master.VISIT))) {
									capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
									if (i < listBulanPelayananSorted.size()) {
										capaianTriwulanVI += Double.valueOf(data.get("jumlahTindakan").toString());
										for (Map<String, Object> target : dataTargetFiltered) {
											if (pegawai.get("pegawaiId").equals(target.get("pegawaiId"))
													&& jabatan.get("jabatanId").equals(target.get("jabatanId"))
													&& idIndikator.equals(target.get("indikatorId"))
													&& datePelayanan.equals(target.get("periode"))) {
												targetBulanan = Double.valueOf(target.get("target").toString());
												break;
											}
										}
									} else if (i == listBulanPelayananSorted.size()) {
										targetBulanan = Math
												.floor(capaianTriwulanVI / (listBulanPelayananSorted.size() - 1));
									}
								} else if (idIndikator.equals(Master.IndikatorKinerjaLuarJamKerja.KONSUL_EKS)
										&& data.get("namaTindakan").toString().toLowerCase().contains(Master.KONSUL)
										&& listRuangEks.contains(data.get("idRuangan"))) {
									capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
									if (i < listBulanPelayananSorted.size()) {
										capaianTriwulanKE += Double.valueOf(data.get("jumlahTindakan").toString());
										for (Map<String, Object> target : dataTargetFiltered) {
											if (pegawai.get("pegawaiId").equals(target.get("pegawaiId"))
													&& jabatan.get("jabatanId").equals(target.get("jabatanId"))
													&& idIndikator.equals(target.get("indikatorId"))
													&& datePelayanan.equals(target.get("periode"))) {
												targetBulanan = Double.valueOf(target.get("target").toString());
												break;
											}
										}
									} else if (i == listBulanPelayananSorted.size()) {
										targetBulanan = Math
												.floor(capaianTriwulanKE / (listBulanPelayananSorted.size() - 1));
									}
								} else if (idIndikator.equals(Master.IndikatorKinerjaLuarJamKerja.KONSUL_GADAR)
										&& data.get("namaTindakan").toString().toLowerCase().contains(Master.KONSUL)
										&& data.get("idDepartemen").equals(Master.Departemen.IGD)) {
									capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
									if (i < listBulanPelayananSorted.size()) {
										capaianTriwulanKG += Double.valueOf(data.get("jumlahTindakan").toString());
										for (Map<String, Object> target : dataTargetFiltered) {
											if (pegawai.get("pegawaiId").equals(target.get("pegawaiId"))
													&& jabatan.get("jabatanId").equals(target.get("jabatanId"))
													&& idIndikator.equals(target.get("indikatorId"))
													&& datePelayanan.equals(target.get("periode"))) {
												targetBulanan = Double.valueOf(target.get("target").toString());
												break;
											}
										}
									} else if (i == listBulanPelayananSorted.size()) {
										targetBulanan = Math
												.floor(capaianTriwulanKG / (listBulanPelayananSorted.size() - 1));
									}
								} else if (idIndikator.equals(Master.IndikatorKinerjaLuarJamKerja.KONSUL_REG)
										&& data.get("namaTindakan").toString().toLowerCase().contains(Master.KONSUL)) {
									capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
									if (i < listBulanPelayananSorted.size()) {
										capaianTriwulanKR += Double.valueOf(data.get("jumlahTindakan").toString());
										for (Map<String, Object> target : dataTargetFiltered) {
											if (pegawai.get("pegawaiId").equals(target.get("pegawaiId"))
													&& jabatan.get("jabatanId").equals(target.get("jabatanId"))
													&& idIndikator.equals(target.get("indikatorId"))
													&& datePelayanan.equals(target.get("periode"))) {
												targetBulanan = Double.valueOf(target.get("target").toString());
												break;
											}
										}
									} else if (i == listBulanPelayananSorted.size()) {
										targetBulanan = Math
												.floor(capaianTriwulanKR / (listBulanPelayananSorted.size() - 1));
									}
								} else if (idIndikator.equals(Master.IndikatorKinerjaLuarJamKerja.TINDAKAN_EKS)
										&& listRuangEks.contains(data.get("idRuangan"))) {
									capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
									if (i < listBulanPelayananSorted.size()) {
										capaianTriwulanTE += Double.valueOf(data.get("jumlahTindakan").toString());
										for (Map<String, Object> target : dataTargetFiltered) {
											if (pegawai.get("pegawaiId").equals(target.get("pegawaiId"))
													&& jabatan.get("jabatanId").equals(target.get("jabatanId"))
													&& idIndikator.equals(target.get("indikatorId"))
													&& datePelayanan.equals(target.get("periode"))) {
												targetBulanan = Double.valueOf(target.get("target").toString());
												break;
											}
										}
									} else if (i == listBulanPelayananSorted.size()) {
										targetBulanan = Math
												.floor(capaianTriwulanTE / (listBulanPelayananSorted.size() - 1));
									}
								} else if (idIndikator.equals(Master.IndikatorKinerjaLuarJamKerja.TINDAKAN_GADAR)
										&& data.get("idDepartemen").equals(Master.Departemen.IGD)) {
									capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
									if (i < listBulanPelayananSorted.size()) {
										capaianTriwulanTG += Double.valueOf(data.get("jumlahTindakan").toString());
										for (Map<String, Object> target : dataTargetFiltered) {
											if (pegawai.get("pegawaiId").equals(target.get("pegawaiId"))
													&& jabatan.get("jabatanId").equals(target.get("jabatanId"))
													&& idIndikator.equals(target.get("indikatorId"))
													&& datePelayanan.equals(target.get("periode"))) {
												targetBulanan = Double.valueOf(target.get("target").toString());
												break;
											}
										}
									} else if (i == listBulanPelayananSorted.size()) {
										targetBulanan = Math
												.floor(capaianTriwulanTG / (listBulanPelayananSorted.size() - 1));
									}
								} else if (idIndikator.equals(Master.IndikatorKinerjaLuarJamKerja.TINDAKAN_OPS)
										&& data.get("idRuangan").equals(Master.Ruangan.OK)) {
									capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
									if (i < listBulanPelayananSorted.size()) {
										capaianTriwulanTO += Double.valueOf(data.get("jumlahTindakan").toString());
										for (Map<String, Object> target : dataTargetFiltered) {
											if (pegawai.get("pegawaiId").equals(target.get("pegawaiId"))
													&& jabatan.get("jabatanId").equals(target.get("jabatanId"))
													&& idIndikator.equals(target.get("indikatorId"))
													&& datePelayanan.equals(target.get("periode"))) {
												targetBulanan = Double.valueOf(target.get("target").toString());
												break;
											}
										}
									} else if (i == listBulanPelayananSorted.size()) {
										targetBulanan = Math
												.floor(capaianTriwulanTO / (listBulanPelayananSorted.size() - 1));
									}
								} else if (idIndikator.equals(Master.IndikatorKinerjaLuarJamKerja.TINDAKAN_REG)) {
									capaianBulanan += Double.valueOf(data.get("jumlahTindakan").toString());
									if (i < listBulanPelayananSorted.size()) {
										capaianTriwulanTR += Double.valueOf(data.get("jumlahTindakan").toString());
										for (Map<String, Object> target : dataTargetFiltered) {
											if (pegawai.get("pegawaiId").equals(target.get("pegawaiId"))
													&& jabatan.get("jabatanId").equals(target.get("jabatanId"))
													&& idIndikator.equals(target.get("indikatorId"))
													&& datePelayanan.equals(target.get("periode"))) {
												targetBulanan = Double.valueOf(target.get("target").toString());
												break;
											}
										}
									} else if (i == listBulanPelayananSorted.size()) {
										targetBulanan = Math
												.floor(capaianTriwulanTR / (listBulanPelayananSorted.size() - 1));
									}
								}
							}
						}
						Date bulanPelayanan = sdf.parse(datePelayanan);

						detail.setDate(datePelayanan);
						detail.setBulan(sdfINA.format(bulanPelayanan));
						detail.setTarget(targetBulanan);
						detail.setCapaian(capaianBulanan);
						listDetail.add(detail);
					}
					if (Double.valueOf(listDetail.get(listDetail.size() - 1).getTarget()) > 0.0) {
						resultVo.setDetail(listDetail);

						PegawaiVO pegawaiVO = new PegawaiVO();
						pegawaiVO.setId(Integer.valueOf(pegawai.get("pegawaiId").toString()));
						resultVo.setPegawai(pegawaiVO);

						JabatanVO jabatanVO = new JabatanVO();
						jabatanVO.setId(Integer.valueOf(jabatan.get("jabatanId").toString()));
						resultVo.setJabatan(jabatanVO);

						IndikatorKinerjaDetailVO detailIndikatorVO = new IndikatorKinerjaDetailVO();
						detailIndikatorVO.setId(idIndikator);
						resultVo.setIndikator(detailIndikatorVO);

						saveTargetCapaianLayananPegawai(resultVo, sdf.parse(strPeriode));
					}
				}
			}
		}
	}

	@Override
	@Transactional(readOnly = false)
	public void saveTargetCapaianLayananPegawai(TargetLayananLuarJamKerjaVO vo, Date periodeHitung)
			throws ParseException {
		Date tglHitung = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		for (TargetLayananLuarJamKerjaDetailVO detail : vo.getDetail()) {
			LogbookKinerjaDokter logbook = new LogbookKinerjaDokter();
			logbook.setKdProfile((short) 0);
			logbook.setStatusEnabled(true);
			logbook.setBulan(sdf.parse(detail.getDate()));
			logbook.setDetailTarget(detail.getTarget());
			logbook.setDetailCapaian(detail.getCapaian());
			IndikatorKinerjaDetail indikator = new IndikatorKinerjaDetail();
			indikator.setId(vo.getIndikator().getId());
			logbook.setIndikatorDetail(indikator);
			Jabatan jabatan = new Jabatan();
			jabatan.setId(vo.getJabatan().getId());
			logbook.setJabatan(jabatan);
			Pegawai pegawai = new Pegawai();
			pegawai.setId(vo.getPegawai().getId());
			logbook.setPegawai(pegawai);
			logbook.setTglHitung(tglHitung);

			logbookKinerjaDokterDao.save(logbook);
		}
	}

	@Override
	public List<TargetLayananJamKerjaVO> findAllTargetCapaianLayananJamKerja(String strPeriode, Integer idKsm)
			throws ParseException {
		List<TargetLayananJamKerjaVO> result = new ArrayList<>();
		List<TargetLayanan> data = new ArrayList<>();
		List<Map<String, Object>> listKelompokKerja = new ArrayList<>();
		List<Integer> listIdKelompokKerja = new ArrayList<>();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
		SimpleDateFormat sdfINA = new SimpleDateFormat("MMMM yyyy", new Locale("in", "ID"));

		Date periode = sdf.parse(strPeriode);

		// get_few_months_earlier
		Calendar calTglAwal = Calendar.getInstance();
		calTglAwal.setTime(periode);
		calTglAwal.set(Calendar.HOUR_OF_DAY, 0);
		calTglAwal.set(Calendar.MINUTE, 0);
		calTglAwal.set(Calendar.SECOND, 0);
		calTglAwal.set(Calendar.DAY_OF_MONTH, 1);
		calTglAwal.add(Calendar.MONTH, -Integer.valueOf(GetSettingDataFixed("jmlBlnHitungTargetMedis")));

		// get_this_period
		Calendar bulan = Calendar.getInstance();
		bulan.setTime(periode);
		bulan.set(Calendar.HOUR_OF_DAY, 23);
		bulan.set(Calendar.MINUTE, 59);
		bulan.set(Calendar.SECOND, 0);
		bulan.set(Calendar.DAY_OF_MONTH, bulan.getActualMaximum(Calendar.DAY_OF_MONTH));

		if (CommonUtil.isNotNullOrEmpty(idKsm)) {
			data = targetLayananDao.findAllTargetLayanan(sdf.format(calTglAwal.getTime()), sdf.format(bulan.getTime()),
					idKsm);
		} else {
			data = targetLayananDao.findAllTargetLayanan(sdf.format(calTglAwal.getTime()), sdf.format(bulan.getTime()));
		}

		for (TargetLayanan map : data) {
			if (!listIdKelompokKerja.contains(map.getSubUnitKerjaPegawai().getId())) {
				listIdKelompokKerja.add(map.getSubUnitKerjaPegawai().getId());
			}
		}

		if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja)) {
			listKelompokKerja = subunitKerjaDao.findSubunitKerjaById(listIdKelompokKerja);
		}

		List<Map<String, Object>> listIndikatorPelayanan = indikatorKinerjaDetailDao
				.findByListId(Arrays.asList(Master.IndikatorKinerjaJamKerja.INDIKATOR_PELAYANAN_MEDIS));

		for (Map<String, Object> kelompokKerja : listKelompokKerja) {
			for (Map<String, Object> indikator : listIndikatorPelayanan) {

				List<String> paramPeriode = new ArrayList<>();
				TargetLayananJamKerjaVO resultVo = new TargetLayananJamKerjaVO();
				List<TargetLayananJamKerjaDetailVO> listDetail = new ArrayList<>();
				for (TargetLayanan targetLayanan : data) {
					if (kelompokKerja.get("subId").equals(targetLayanan.getSubUnitKerjaPegawai().getId())
							&& indikator.get("id").equals(targetLayanan.getIndikatorDetail().getId())) {
						TargetLayananJamKerjaDetailVO detail = new TargetLayananJamKerjaDetailVO();
						detail.setDate(sdf.format(targetLayanan.getPeriode()));
						detail.setBulan(sdfINA.format(targetLayanan.getPeriode()));
						detail.setTarget(targetLayanan.getTarget());
						detail.setCapaian(targetLayanan.getCapaian());
						detail.setTglHitung(formatter.format(targetLayanan.getTglHitung()));

						if (!paramPeriode.contains(sdf.format(targetLayanan.getPeriode()))) {
							listDetail.add(detail);

							if (!paramPeriode.contains(sdf.format(targetLayanan.getPeriode()))) {
								paramPeriode.add(sdf.format(targetLayanan.getPeriode()));
							}
						}
					}
				}

				if (listDetail.size() == 4 && listDetail.get(listDetail.size() - 1).getTarget() > 0.0) {
					resultVo.setDetail(listDetail);

					UnitKerjaPegawaiVO unitKerjaVO = new UnitKerjaPegawaiVO();
					unitKerjaVO.setId(Integer.valueOf(kelompokKerja.get("unitId").toString()));
					unitKerjaVO.setName(kelompokKerja.get("unitName").toString());

					SubUnitKerjaPegawaiVO kelompokKerjaVO = new SubUnitKerjaPegawaiVO();
					kelompokKerjaVO.setId(Integer.valueOf(kelompokKerja.get("subId").toString()));
					kelompokKerjaVO.setName(kelompokKerja.get("subName").toString());
					kelompokKerjaVO.setUnitKerja(unitKerjaVO);
					resultVo.setKelompokKerja(kelompokKerjaVO);

					IndikatorKinerjaDetailVO indikatorVO = new IndikatorKinerjaDetailVO();
					indikatorVO.setId(Integer.valueOf(indikator.get("id").toString()));
					indikatorVO.setDetailIndikator(indikator.get("detailIndikator").toString());
					resultVo.setIndikator(indikatorVO);

					result.add(resultVo);
				}
			}
		}

		return result;
	}

	@Override
	public List<TargetLayananLuarJamKerjaVO> findAllTargetCapaianLayananLuarJamKerja(String strPeriode)
			throws ParseException {
		List<TargetLayananLuarJamKerjaVO> result = new ArrayList<>();

		List<Map<String, Object>> listPegawai = new ArrayList<>();
		List<Integer> listIdPegawai = new ArrayList<>();

		List<Map<String, Object>> listJabatan = new ArrayList<>();
		List<Integer> listIdJabatan = new ArrayList<>();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
		SimpleDateFormat sdfINA = new SimpleDateFormat("MMMM yyyy", new Locale("in", "ID"));

		Date periode = sdf.parse(strPeriode);

		// get_few_months_earlier
		Calendar calTglAwal = Calendar.getInstance();
		calTglAwal.setTime(periode);
		calTglAwal.set(Calendar.HOUR_OF_DAY, 0);
		calTglAwal.set(Calendar.MINUTE, 0);
		calTglAwal.set(Calendar.SECOND, 0);
		calTglAwal.set(Calendar.DAY_OF_MONTH, 1);
		calTglAwal.add(Calendar.MONTH, -Integer.valueOf(GetSettingDataFixed("jmlBlnHitungTargetMedis")));

		// get_this_period
		Calendar bulan = Calendar.getInstance();
		bulan.setTime(periode);
		bulan.set(Calendar.HOUR_OF_DAY, 23);
		bulan.set(Calendar.MINUTE, 59);
		bulan.set(Calendar.SECOND, 0);
		bulan.set(Calendar.DAY_OF_MONTH, bulan.getActualMaximum(Calendar.DAY_OF_MONTH));

		List<LogbookKinerjaDokter> data = logbookKinerjaDokterDao.findAllTargetLayanan(sdf.format(calTglAwal.getTime()),
				sdf.format(bulan.getTime()));

		for (LogbookKinerjaDokter map : data) {
			if (!listIdPegawai.contains(map.getPegawai().getId())) {
				listIdPegawai.add(map.getPegawai().getId());
			}
			if (!listIdJabatan.contains(map.getJabatan().getId())) {
				listIdJabatan.add(map.getJabatan().getId());
			}
		}

		if (CommonUtil.isNotNullOrEmpty(listIdPegawai)) {
			listPegawai = pegawaiDao.findPegawaiByListId(listIdPegawai);
		}
		if (CommonUtil.isNotNullOrEmpty(listIdJabatan)) {
			listJabatan = jabatanDao.findJabatanByListId(listIdJabatan);
		}

		List<Map<String, Object>> listIndikatorPelayanan = indikatorKinerjaDetailDao
				.findByListId(Arrays.asList(Master.IndikatorKinerjaLuarJamKerja.INDIKATOR_PELAYANAN_MEDIS));

		for (Map<String, Object> pegawai : listPegawai) {
			for (Map<String, Object> jabatan : listJabatan) {
				for (Map<String, Object> indikator : listIndikatorPelayanan) {

					List<String> paramPeriode = new ArrayList<>();
					TargetLayananLuarJamKerjaVO resultVo = new TargetLayananLuarJamKerjaVO();
					List<TargetLayananLuarJamKerjaDetailVO> listDetail = new ArrayList<>();
					for (LogbookKinerjaDokter targetLayanan : data) {
						if (pegawai.get("pegawaiId").equals(targetLayanan.getPegawai().getId())
								&& jabatan.get("jabatanId").equals(targetLayanan.getJabatan().getId())
								&& indikator.get("id").equals(targetLayanan.getIndikatorDetail().getId())) {
							TargetLayananLuarJamKerjaDetailVO detail = new TargetLayananLuarJamKerjaDetailVO();
							detail.setDate(sdf.format(targetLayanan.getBulan()));
							detail.setBulan(sdfINA.format(targetLayanan.getBulan()));
							detail.setTarget(targetLayanan.getDetailTarget());
							detail.setCapaian(targetLayanan.getDetailCapaian());
							detail.setTglHitung(formatter.format(targetLayanan.getTglHitung()));

							if (!paramPeriode.contains(sdf.format(targetLayanan.getBulan()))) {
								listDetail.add(detail);

								if (!paramPeriode.contains(sdf.format(targetLayanan.getBulan()))) {
									paramPeriode.add(sdf.format(targetLayanan.getBulan()));
								}
							}
						}
					}

					if (listDetail.size() == 4 && listDetail.get(listDetail.size() - 1).getTarget() > 0.0) {
						resultVo.setDetail(listDetail);

						PegawaiVO pegawaiVO = new PegawaiVO();
						pegawaiVO.setId(Integer.valueOf(pegawai.get("pegawaiId").toString()));
						pegawaiVO.setNamaLengkap(pegawai.get("namaLengkap").toString());
						resultVo.setPegawai(pegawaiVO);

						JabatanVO jabatanVO = new JabatanVO();
						jabatanVO.setId(Integer.valueOf(jabatan.get("jabatanId").toString()));
						jabatanVO.setNamaJabatan(jabatan.get("namaJabatan").toString());
						resultVo.setJabatan(jabatanVO);

						IndikatorKinerjaDetailVO indikatorVO = new IndikatorKinerjaDetailVO();
						indikatorVO.setId(Integer.valueOf(indikator.get("id").toString()));
						indikatorVO.setDetailIndikator(indikator.get("detailIndikator").toString());
						resultVo.setIndikator(indikatorVO);

						result.add(resultVo);
					}
				}
			}
		}

		return result;
	}

}
