package com.jasamedika.medifirst2000.service.impl;

import com.jasamedika.medifirst2000.constants.Master;
import com.jasamedika.medifirst2000.dao.*;
import com.jasamedika.medifirst2000.dto.DataCutiDto;
import com.jasamedika.medifirst2000.dto.JatahCutiRequest;
import com.jasamedika.medifirst2000.dto.HariLiburTerpakai;
import com.jasamedika.medifirst2000.entities.ListTanggalCuti;
import com.jasamedika.medifirst2000.service.JatahCutiDanIzinService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

import static com.jasamedika.medifirst2000.constants.Master.HariLibur.LIBUR_CB;
import static com.jasamedika.medifirst2000.constants.Master.StatusPegawai.CUTI_TAHUNAN;

/**
 * @author Salman
 * @version 1.0.0
 * @since 09/01/2025
 */
@Service
public class JatahCutiDanIzinServiceImpl implements JatahCutiDanIzinService {

	@Autowired
	private PlanningPegawaiStatusDao planningPegawaiStatusDao;

	@Autowired
	private JatahCutiDanIzinDao jatahCutiDanIzinDao;

	@Autowired
	private PegawaiDao pegawaiDao;

	@Autowired
	private PegawaiHistoriRekapIndexDao pegawaiHistoriRekapIndexDao;

	@Autowired
	private PegawaiJadwalKerjaDao pegawaiJadwalKerjaDao;

	@Autowired
	private MapKalenderToHariLiburDao mapKalenderToHariLiburDao;

	@Autowired
	private HabsenDao habsenDao;

	@Autowired
	private ListTanggalCutiDao tanggalCutiDao;

	@Override
	public DataCutiDto getDataCuti(Integer pegawaiId, String year, Integer statusPegawaiId) {
		return calculateCutiIzin(pegawaiId, year, statusPegawaiId);
	}

	private DataCutiDto calculateCutiIzin(Integer pegawaiId, String year, Integer statusPegawaiId) {
		DataCutiDto.DataCutiDtoBuilder cutiIzinBuilder = DataCutiDto.builder();
		List<Integer> listKomponenIndex = new ArrayList<>();
		int sisaCuti;
		Integer sisaCutiB2 = 0;
		Integer sisaCutiB1 = 0;
		int sisaCutiB;
		int sisaCutiN2;
		int sisaCutiN1;
		int sisaCutiN;
		Integer jatahCuti = 0;
		int sisaJatahRawatJalan = 0;
		int sisaJatahRawatInap = 0;
		int sisaIzin;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy");
		if (CommonUtil.isNullOrEmpty(year))
			year = formatter.format(DateUtil.now());
		int yearn1 = Integer.parseInt(year) - 1;
		int yearn2 = Integer.parseInt(year) - 2;
		int yearn3 = Integer.parseInt(year) + 1;
		String yearN1 = Integer.toString(yearn1);
		String yearN2 = Integer.toString(yearn2);
		String yearN3 = Integer.toString(yearn3);
		if (statusPegawaiId == 5 || statusPegawaiId == 1 || statusPegawaiId == 21) {
			String komponen = Master.KomponenIndex.CUTI_NONSHIFT.toString();
			String komponenIndeksCutiShift = Master.KomponenIndex.CUTI_SHIFT.toString();
			String komponenIndeksCutiBersama = Master.KomponenIndex.CUTI_BERSAMA.toString();
			listKomponenIndex.add(Integer.valueOf(komponen));
			listKomponenIndex.add(Integer.valueOf(komponenIndeksCutiShift));
			// Initiate cuti bersama
			Integer cutiTerpakaiB2;
			Integer cutiTerpakaiB1;
			Integer cutiTerpakaiB;
			// Menghitung cuti terpakai tahun n-2
			Integer cutiTerpakaiN2 = pegawaiHistoriRekapIndexDao.getCutiTerpakai(yearN2, pegawaiId, listKomponenIndex);
			if (CommonUtil.isNullOrEmpty(cutiTerpakaiN2))
				cutiTerpakaiN2 = 0;
			// Menghitung cuti terpakai tahun n-1
			Integer cutiTerpakaiN1 = pegawaiHistoriRekapIndexDao.getCutiTerpakai(yearN1, pegawaiId, listKomponenIndex);
			if (CommonUtil.isNullOrEmpty(cutiTerpakaiN1))
				cutiTerpakaiN1 = 0;
			// Menghitung cuti terpakai tahun n
			Integer cutiTerpakaiN = pegawaiHistoriRekapIndexDao.getCutiTerpakai(year, pegawaiId, listKomponenIndex);
			if (CommonUtil.isNullOrEmpty(cutiTerpakaiN))
				cutiTerpakaiN = 0;
			// Menghitung cuti terpakai by histori pengajuan
			Integer jumlahTglByPengajuan = pegawaiHistoriRekapIndexDao.getHistoriCutiTerpakaiByTahunPengajuan(year,
					pegawaiId, listKomponenIndex);
			if (CommonUtil.isNullOrEmpty(jumlahTglByPengajuan))
				jumlahTglByPengajuan = 0;
			Integer rekapHistoriCutiTerpakai = pegawaiHistoriRekapIndexDao.getHistoriCutiTerpakai(yearN2, pegawaiId,
					listKomponenIndex);
			if (CommonUtil.isNullOrEmpty(rekapHistoriCutiTerpakai))
				rekapHistoriCutiTerpakai = 0;
			Integer dataHistoriCutiTerpakai = jatahCutiDanIzinDao.getHistoriCutiTerpakai(pegawaiId, yearN2);
			if (CommonUtil.isNullOrEmpty(dataHistoriCutiTerpakai))
				dataHistoriCutiTerpakai = 0;
			Integer diffHistori = dataHistoriCutiTerpakai - rekapHistoriCutiTerpakai;
			if (rekapHistoriCutiTerpakai < dataHistoriCutiTerpakai) {
				if (cutiTerpakaiN2 > diffHistori) {
					cutiTerpakaiN2 -= diffHistori;
				} else {
					diffHistori -= cutiTerpakaiN2;
					cutiTerpakaiN2 = 0;
					if (cutiTerpakaiN1 > diffHistori) {
						cutiTerpakaiN1 -= diffHistori;
					} else {
						diffHistori -= cutiTerpakaiN1;
						cutiTerpakaiN1 = 0;
						if (cutiTerpakaiN > diffHistori) {
							cutiTerpakaiN -= diffHistori;
						} else {
							cutiTerpakaiN = 0;
						}
					}
				}
			}
			// Mendapatkan seluruh data jatah cuti untuk pegawai tertentu
			Integer dataCutiB2 = jatahCutiDanIzinDao.getDataCuti(yearN2, pegawaiId,
					Integer.valueOf(komponenIndeksCutiBersama)); // dataCutiBersama_di_n-2
			Integer dataCutiB1 = jatahCutiDanIzinDao.getDataCuti(yearN1, pegawaiId,
					Integer.valueOf(komponenIndeksCutiBersama)); // dataCutiBersama_di_n-1
			Integer dataCutiB = jatahCutiDanIzinDao.getDataCuti(year, pegawaiId,
					Integer.valueOf(komponenIndeksCutiBersama)); // dataCutiBersama_di_n
			Integer dataCutiN2 = jatahCutiDanIzinDao.getDataCuti(yearN2, pegawaiId, Integer.valueOf(komponen)); // dataCutiTahunan_tahun_n-2
			Integer dataCutiN1 = jatahCutiDanIzinDao.getDataCuti(yearN1, pegawaiId, Integer.valueOf(komponen)); // dataCutiTahunan_tahun_n-1
			Integer dataCutiN = jatahCutiDanIzinDao.getDataCuti(year, pegawaiId, Integer.valueOf(komponen)); // dataCutiTahunan_tahun_n
			Integer dataCutiN3 = jatahCutiDanIzinDao.getDataCuti(yearN3, pegawaiId, Integer.valueOf(komponen)); // dataCutiTahunan_tahun_n+1
			// Validasi existing data
			if (CommonUtil.isNullOrEmpty(dataCutiB2))
				dataCutiB2 = 0;
			if (CommonUtil.isNullOrEmpty(dataCutiB1))
				dataCutiB1 = 0;
			if (CommonUtil.isNullOrEmpty(dataCutiB))
				dataCutiB = 0;
			if (CommonUtil.isNullOrEmpty(dataCutiN2))
				dataCutiN2 = 0;
			if (CommonUtil.isNullOrEmpty(dataCutiN1))
				dataCutiN1 = 0;
			if (CommonUtil.isNullOrEmpty(dataCutiN))
				dataCutiN = 0;
			if (CommonUtil.isNullOrEmpty(dataCutiN3))
				dataCutiN3 = 12;
			// mapping jatah cuti
			cutiIzinBuilder.dataCutiB2(dataCutiB2);
			cutiIzinBuilder.dataCutiB1(dataCutiB1);
			cutiIzinBuilder.dataCutiB(dataCutiB);
			cutiIzinBuilder.dataCutiN2(dataCutiN2);
			cutiIzinBuilder.dataCutiN1(dataCutiN1);
			cutiIzinBuilder.dataCutiN(dataCutiN);
			cutiIzinBuilder.dataCutiN3(dataCutiN3);

			// Hitung Absen di tanggal cuti bersama
			List<String> listTglCutiBersama = mapKalenderToHariLiburDao.getTglCutiBersama(year);
			int countDataHabsen = 0;
			Date awal2025 = new Date(1735664400000L);
			for (String tglStr : listTglCutiBersama) {
				Date tglCheck;
				try {
					tglCheck = sdf.parse(tglStr);
				} catch (ParseException e) {
					tglCheck = new Date();
				}
				List<Date> dataHabsen = new ArrayList<>();
				// cek shift malam
				String tglPrev = sdf.format(java.sql.Date.valueOf(LocalDate.parse(tglStr).minusDays(1)));
				List<Map<String, Object>> listMap = pegawaiJadwalKerjaDao.getNamaShiftKerjaPegawaiByTanggal(tglPrev,
						tglStr, pegawaiId);
				if (listMap.size() == 2) {
					if (!listMap.get(0).get("namaShift").toString().toLowerCase().contains("malam")
							&& listMap.get(1).get("namaShift").toString().toLowerCase().contains("malam")) {
						dataHabsen = habsenDao.countAbsenTglCutiBersama(tglStr, pegawaiDao.getidFinger(pegawaiId));
					} else if (listMap.get(0).get("namaShift").toString().toLowerCase().contains("malam")
							&& listMap.get(1).get("namaShift").toString().toLowerCase().contains("malam")) {
						dataHabsen = habsenDao.countAbsenTglCutiBersama(tglStr, pegawaiDao.getidFinger(pegawaiId));
					} else if (!listMap.get(0).get("namaShift").toString().toLowerCase().contains("malam")
							&& !listMap.get(1).get("namaShift").toString().toLowerCase().contains("malam")) {
						dataHabsen = habsenDao.countAbsenTglCutiBersama(tglStr, pegawaiDao.getidFinger(pegawaiId));
					}
				}
				if (CommonUtil.isNotNullOrEmpty(dataHabsen)) {
					if (listMap.size() == 2) {
						if (Arrays.asList(Master.ShiftKerja.TUJUH_BELAS_JAM_SHIFT)
								.contains(Integer.parseInt(listMap.get(1).get("idShift").toString()))) {
							if (Integer.parseInt(year) < 2023) {
								countDataHabsen += 2;
							} else {
								countDataHabsen += 1;
							}
						} else {
							countDataHabsen += 1;
						}
					} else {
						countDataHabsen += 1;
					}
				} else if (tglCheck.before(awal2025)) {
					// cuti tahunan di tanggal cuti bersama
					List<Date> tglCutiTahunanDiTglCutiBersama = jatahCutiDanIzinDao
							.getCutiTahunanDiTglCutiBersama(CUTI_TAHUNAN, pegawaiId, tglStr);
					if (CommonUtil.isNotNullOrEmpty(tglCutiTahunanDiTglCutiBersama)) {
						if (listMap.size() == 2) {
							if (Arrays.asList(Master.ShiftKerja.TUJUH_BELAS_JAM_SHIFT)
									.contains(Integer.parseInt(listMap.get(1).get("idShift").toString()))) {
								if (Integer.parseInt(year) < 2023) {
									countDataHabsen += 2;
								} else {
									countDataHabsen += 1;
								}
							} else {
								countDataHabsen += 1;
							}
						} else {
							countDataHabsen += 1;
						}
					}
				}
			}
			dataCutiB = countDataHabsen;
			// kondisikan cuti bersama yg sudah berlalu
			if (cutiTerpakaiN2 > dataCutiB2) {
				cutiTerpakaiB2 = dataCutiB2;
			} else {
				cutiTerpakaiB2 = cutiTerpakaiN2;
			}
			if (cutiTerpakaiN1 > dataCutiB1) {
				cutiTerpakaiB1 = dataCutiB1;
			} else {
				cutiTerpakaiB1 = cutiTerpakaiN1;
			}
			JatahCutiRequest jatahCutiRequest = transform(pegawaiId, year, statusPegawaiId);
			int jatahCutiBersamaDitangguhkan = tangguhkanCutiBersama(cutiTerpakaiB1, jatahCutiRequest);
			dataCutiB += jatahCutiBersamaDitangguhkan;
			cutiIzinBuilder.dataCutiB(dataCutiB);
			// Mendapatkan kondisi penangguhan saat ini
			cutiIzinBuilder.isTangguhkanB2(false);
			cutiIzinBuilder.isTangguhkanB1(false);
			cutiIzinBuilder.isTangguhkanB(false);
			Boolean jCutiN2 = jatahCutiDanIzinDao.getPenangguhanSisaCuti(yearN2, pegawaiId, Integer.valueOf(komponen));
			if (CommonUtil.isNotNullOrEmpty(jCutiN2)) {
				cutiIzinBuilder.isTangguhkanN2(jCutiN2);
			} else {
				jCutiN2 = false;
				cutiIzinBuilder.isTangguhkanN2(false);
			}
			Boolean jCutiN1 = jatahCutiDanIzinDao.getPenangguhanSisaCuti(yearN1, pegawaiId, Integer.valueOf(komponen));
			if (CommonUtil.isNotNullOrEmpty(jCutiN1)) {
				cutiIzinBuilder.isTangguhkanN1(jCutiN1);
			} else {
				jCutiN1 = false;
				cutiIzinBuilder.isTangguhkanN1(false);
			}
			Boolean jCutiN = jatahCutiDanIzinDao.getPenangguhanSisaCuti(year, pegawaiId, Integer.valueOf(komponen));
			if (CommonUtil.isNotNullOrEmpty(jCutiN)) {
				cutiIzinBuilder.isTangguhkanN(jCutiN);
			} else {
				cutiIzinBuilder.isTangguhkanN(false);
			}
			if (dataCutiB >= cutiTerpakaiN) {
				sisaCutiB = dataCutiB - cutiTerpakaiN;
				cutiTerpakaiB = cutiTerpakaiN;
			} else {
				sisaCutiB = 0;
				cutiTerpakaiB = dataCutiB;
			}
			cutiIzinBuilder.sisaCutiB2(sisaCutiB2);
			cutiIzinBuilder.sisaCutiB1(sisaCutiB1);
			cutiIzinBuilder.sisaCutiB(sisaCutiB);
			cutiIzinBuilder.cutiTerpakaiB2(cutiTerpakaiB2);
			cutiIzinBuilder.cutiTerpakaiB1(cutiTerpakaiB1);
			cutiIzinBuilder.cutiTerpakaiB(cutiTerpakaiB);
			// menghitung jatah cuti yang terpakai
			Integer jatahCutiTerpakaiN2 = 0, jatahCutiTerpakaiN1 = 0, jatahCutiTerpakaiN = 0;
			int allCutiTerpakai = difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
					+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) + difCutiTerpakai(cutiTerpakaiN, dataCutiB);
			if (dataCutiN2 > 0) {
				if (allCutiTerpakai >= dataCutiN2) {
					if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
							+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) < dataCutiN2) {
						jatahCutiTerpakaiN2 = difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
								+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1);
					} else {
						jatahCutiTerpakaiN2 = dataCutiN2;
					}
				} else {
					if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
							+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) < dataCutiN2) {
						jatahCutiTerpakaiN2 = difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
								+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1);
					} else {
						jatahCutiTerpakaiN2 = allCutiTerpakai;
					}
				}
				if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
						+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) < dataCutiN2) {
					if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2) > 0) {
						sisaCutiN2 = 0; // hangus
					} else {
						if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
								+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) < 6) {
							if (jatahCutiTerpakaiN2 == 0 && !jCutiN1) {
								sisaCutiN2 = 6;
							} else if (jatahCutiTerpakaiN2 == 0) {
								sisaCutiN2 = 0;
							} else if (!jCutiN2 && !jCutiN1) {
								sisaCutiN2 = 6 - jatahCutiTerpakaiN2;
							} else {
								sisaCutiN2 = 0;
							}
						} else {
							sisaCutiN2 = dataCutiN2 - jatahCutiTerpakaiN2;
						}
					}
				} else {
					if (dataCutiN2 - jatahCutiTerpakaiN2 >= 6 && !jCutiN2) {
						sisaCutiN2 = 6 - jatahCutiTerpakaiN2;
					} else {
						sisaCutiN2 = dataCutiN2 - jatahCutiTerpakaiN2;
					}
				}
				if (sisaCutiN2 > 0 && difCutiTerpakai(cutiTerpakaiN, dataCutiB) > 0) {
					if (sisaCutiN2 > difCutiTerpakai(cutiTerpakaiN, dataCutiB)) {
						jatahCutiTerpakaiN2 += difCutiTerpakai(cutiTerpakaiN, dataCutiB);
					} else {
						jatahCutiTerpakaiN2 += sisaCutiN2;
					}
				}
				allCutiTerpakai = allCutiTerpakai - jatahCutiTerpakaiN2;
				if (allCutiTerpakai > 0) {
					if (allCutiTerpakai >= dataCutiN1) {
						jatahCutiTerpakaiN1 = dataCutiN1;
						allCutiTerpakai = allCutiTerpakai - jatahCutiTerpakaiN1;
						if ((allCutiTerpakai > 0) && (allCutiTerpakai <= dataCutiN)) {
							jatahCutiTerpakaiN = allCutiTerpakai;
						} else {
							jatahCutiTerpakaiN = 0;
						}
					} else {
						jatahCutiTerpakaiN1 = allCutiTerpakai;
					}
				}
			} else if (dataCutiN1 > 0) {
				if (allCutiTerpakai >= dataCutiN1) {
					jatahCutiTerpakaiN1 = dataCutiN1;
					allCutiTerpakai = allCutiTerpakai - jatahCutiTerpakaiN1;
					if ((allCutiTerpakai > 0) && (allCutiTerpakai <= dataCutiN)) {
						jatahCutiTerpakaiN = allCutiTerpakai;
					} else {
						jatahCutiTerpakaiN = 0;
					}
				} else {
					jatahCutiTerpakaiN1 = allCutiTerpakai;
				}
			} else if (dataCutiN > 0) {
				if (allCutiTerpakai <= dataCutiN) {
					jatahCutiTerpakaiN = allCutiTerpakai;
				} else {
					jatahCutiTerpakaiN = 0;
				}
			}
			// Menghitung cuti terpakai tahun n+1
			Integer cutiTerpakaiN3 = pegawaiHistoriRekapIndexDao.getCutiTerpakai(yearN3, pegawaiId, listKomponenIndex);
			if (CommonUtil.isNullOrEmpty(cutiTerpakaiN3))
				cutiTerpakaiN3 = 0;
			if (cutiTerpakaiN3 > 0) {
				// menghitung sisa cuti n-1 terlebih dahulu
				if (dataCutiN1 - jatahCutiTerpakaiN1 >= 6 && !jCutiN1) {
					sisaCutiN1 = 6 - jatahCutiTerpakaiN1;
				} else {
					sisaCutiN1 = dataCutiN1 - jatahCutiTerpakaiN1;
				}
				// juga menghitung sisa cuti n terlebih dahulu
				sisaCutiN = dataCutiN - jatahCutiTerpakaiN;
				// menghitung jatah cuti terpakai karena pengajuan lintas tahun
				if (difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) == 0 && !jCutiN1) {
					if (sisaCutiN1 > 0) {
						if (cutiTerpakaiN3 > sisaCutiN1) {
							jatahCutiTerpakaiN1 += sisaCutiN1;
							cutiTerpakaiN3 -= sisaCutiN1;
							if (sisaCutiN > 0) {
								if (cutiTerpakaiN3 > sisaCutiN) {
									jatahCutiTerpakaiN += sisaCutiN;
								} else {
									jatahCutiTerpakaiN += cutiTerpakaiN3;
								}
							}
						} else {
							jatahCutiTerpakaiN1 += cutiTerpakaiN3;
						}
					} else if (sisaCutiN > 0) {
						if (cutiTerpakaiN3 > sisaCutiN) {
							jatahCutiTerpakaiN += sisaCutiN;
						} else {
							jatahCutiTerpakaiN += cutiTerpakaiN3;
						}
					}
				} else {
					if (sisaCutiN > 0) {
						if (cutiTerpakaiN3 > sisaCutiN) {
							jatahCutiTerpakaiN += sisaCutiN;
						} else {
							jatahCutiTerpakaiN += cutiTerpakaiN3;
						}
					}
				}
			}
			// put all data jatah cuti terpakai
			cutiIzinBuilder.cutiTerpakaiN2(jatahCutiTerpakaiN2);
			cutiIzinBuilder.cutiTerpakaiN1(jatahCutiTerpakaiN1);
			cutiIzinBuilder.cutiTerpakaiN(jatahCutiTerpakaiN);
			// menghitung sisa cuti
			if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2) + difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) < 12) {
				if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2) > 0) {
					sisaCutiN2 = 0; // hangus
				} else {
					if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2) + difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) < 6
							&& dataCutiN2 > 0) {
						if (jatahCutiTerpakaiN2 == 0 && !jCutiN1) {
							sisaCutiN2 = 6;
						} else if (jatahCutiTerpakaiN2 == 0) {
							sisaCutiN2 = 0;
						} else if (!jCutiN2 && !jCutiN1) {
							sisaCutiN2 = 6 - jatahCutiTerpakaiN2;
						} else {
							sisaCutiN2 = 0;
						}
					} else if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
							+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) < 6 && dataCutiN2 <= 0) {
						sisaCutiN2 = 0;
					} else if (difCutiTerpakai(cutiTerpakaiN2, dataCutiB2)
							+ difCutiTerpakai(cutiTerpakaiN1, dataCutiB1) > 6 && jCutiN1) {
						sisaCutiN2 = 0;
					} else {
						sisaCutiN2 = dataCutiN2 - jatahCutiTerpakaiN2;
					}
				}
			} else {
				if (dataCutiN2 - jatahCutiTerpakaiN2 >= 6 && !jCutiN2) {
					sisaCutiN2 = 6 - jatahCutiTerpakaiN2;
				} else {
					sisaCutiN2 = dataCutiN2 - jatahCutiTerpakaiN2;
				}
			}
			if (dataCutiN1 - jatahCutiTerpakaiN1 >= 6 && !jCutiN1) {
				jumlahTglByPengajuan -= (dataHistoriCutiTerpakai + jatahCutiTerpakaiN2 + cutiTerpakaiB + cutiTerpakaiB1
						+ cutiTerpakaiB2);
				if (jumlahTglByPengajuan < 0)
					jumlahTglByPengajuan = 0;
				if (jumlahTglByPengajuan > jatahCutiTerpakaiN1) {
					sisaCutiN1 = 6;
				} else {
					sisaCutiN1 = 6 - (jatahCutiTerpakaiN1 - jumlahTglByPengajuan);
				}
			} else {
				sisaCutiN1 = dataCutiN1 - jatahCutiTerpakaiN1;
			}
			sisaCutiN = dataCutiN - jatahCutiTerpakaiN;
			// put all data sisa cuti
			cutiIzinBuilder.sisaCutiN2(sisaCutiN2);
			cutiIzinBuilder.sisaCutiN1(sisaCutiN1);
			cutiIzinBuilder.sisaCutiN(sisaCutiN);
		}
		if (statusPegawaiId == 24) {
			if (CommonUtil.isNotNullOrEmpty(jatahCuti))
				cutiIzinBuilder.jatahCuti("-");
			cutiIzinBuilder.sisaCuti("-");
		}
		if (statusPegawaiId == 25) {
			Map<String, Object> data = planningPegawaiStatusDao.getJatahCutiMelahirkan(statusPegawaiId);
			if (CommonUtil.isNotNullOrEmpty(jatahCuti))
				cutiIzinBuilder.jatahCuti(data.get("kuotaTotalHari").toString());
			cutiIzinBuilder.sisaCuti("-");
		}
		if (statusPegawaiId == 26) {
			if (CommonUtil.isNotNullOrEmpty(jatahCuti))
				cutiIzinBuilder.jatahCuti("-");
			cutiIzinBuilder.sisaCuti("-");
		}
		// Izin
		if (statusPegawaiId == 27) {
			Integer komponenIzin = 17; // komponenIndex untuk izin
			Integer jatahIzin = 2; // sesuai kesepakatan
			Integer jumlahIzinTerpakai = pegawaiHistoriRekapIndexDao.getIzinTerpakai(pegawaiId, komponenIzin);
			if (CommonUtil.isNotNullOrEmpty(jumlahIzinTerpakai)) {
				sisaIzin = jatahIzin - jumlahIzinTerpakai;
			} else {
				sisaIzin = jatahIzin;
			}
			cutiIzinBuilder.jatahIzin(jatahIzin);
			cutiIzinBuilder.sisaIzin(sisaIzin);
		}
		if (statusPegawaiId == 28) {
			if (CommonUtil.isNotNullOrEmpty(jatahCuti))
				cutiIzinBuilder.jatahCuti("-");
			cutiIzinBuilder.sisaCuti("-");
		}
		if (statusPegawaiId == 17) {
			Integer cutiTerpakai = pegawaiHistoriRekapIndexDao.getNilaiIndexPegawaiHistoriRekapIndex(pegawaiId, 17);
			Integer dataCuti = jatahCutiDanIzinDao.getDataCuti(year, pegawaiId, 17);
			if (CommonUtil.isNotNullOrEmpty(dataCuti)) {
				if (CommonUtil.isNullOrEmpty(cutiTerpakai))
					cutiTerpakai = 0;
				sisaCuti = dataCuti - cutiTerpakai;
				if (sisaCuti < 0)
					sisaCuti = 0;
			} else {
				sisaCuti = 0;
				dataCuti = 0;
			}
			cutiIzinBuilder.sisaCuti(String.valueOf(sisaCuti));
			cutiIzinBuilder.jatahCuti(String.valueOf(dataCuti));
		}
		// sakit
		if (statusPegawaiId == 29 || statusPegawaiId == 6) {
			Integer komponenSakit = 7;
			Integer komponenSakitShift = 8;
			Integer jumlahRawatJalan = pegawaiHistoriRekapIndexDao.getSakitTerpakai(pegawaiId, komponenSakit, 1);
			if (CommonUtil.isNullOrEmpty(jumlahRawatJalan))
				jumlahRawatJalan = pegawaiHistoriRekapIndexDao.getSakitTerpakai(pegawaiId, komponenSakitShift, 1);
			Integer jumlahRawatInap = pegawaiHistoriRekapIndexDao.getSakitTerpakai(pegawaiId, komponenSakit, 2);
			if (CommonUtil.isNullOrEmpty(jumlahRawatInap))
				jumlahRawatInap = pegawaiHistoriRekapIndexDao.getSakitTerpakai(pegawaiId, komponenSakitShift, 2);
			if ((CommonUtil.isNotNullOrEmpty(jumlahRawatJalan)) || (CommonUtil.isNotNullOrEmpty(jumlahRawatInap))) {
				sisaJatahRawatJalan = 3 - jumlahRawatJalan;
				sisaJatahRawatInap = 5 - jumlahRawatInap;
			}
			cutiIzinBuilder.sisaJatahRawatJalan(sisaJatahRawatJalan);
			cutiIzinBuilder.sisaJatahRawatInap(sisaJatahRawatInap);
		}
		return cutiIzinBuilder.build();
	}

	private Integer difCutiTerpakai(Integer cutiTerpakai, Integer dataCuti) {
		int difCutiTerpakai = 0;
		if (cutiTerpakai > dataCuti)
			difCutiTerpakai = cutiTerpakai - dataCuti;
		return difCutiTerpakai;
	}

	private JatahCutiRequest transform(Integer pegawaiId, String year, Integer statusPegawaiId) {
		return JatahCutiRequest.builder().pegawaiId(pegawaiId).year(year).statusPegawaiId(statusPegawaiId).build();
	}

	private int tangguhkanCutiBersama(Integer cutiBersamaTerpakaiTahunLalu, JatahCutiRequest request) {
		Date awal2024 = new Date(1704042000000L);
		if (CommonUtil.isNullOrEmpty(request.getYear()))
			request.setYear(String.valueOf(DateUtil.getYear(new Date())));
		Date tahunLalu = DateUtil.getInstanceCalendar(-1);
		Date awalTahunLalu = DateUtil.startYear(tahunLalu);
		Date akhirTahunLalu = DateUtil.endYear(tahunLalu);
		List<HariLiburTerpakai> listPresensiTahunLalu = mapKalenderToHariLiburDao
				.getPresensiByTahun(request.getPegawaiId(), LIBUR_CB, awalTahunLalu, akhirTahunLalu);
		List<HariLiburTerpakai> listPresensiCutiBersamaBisaDitangguhkan = listPresensiTahunLalu.stream()
				.filter(HariLiburTerpakai::getIsCutiBersamaDitangguhkan).collect(Collectors.toList());
		if (listPresensiCutiBersamaBisaDitangguhkan.isEmpty())
			return 0;
		int cutiDiCutiBersama = 0;
		if (tahunLalu.before(awal2024)) {
			List<HariLiburTerpakai> listCutiDiCutiBersamaTahunLalu = tanggalCutiDao
					.getCutiByTahun(request.getPegawaiId(), LIBUR_CB, awalTahunLalu, akhirTahunLalu);
			cutiDiCutiBersama = listCutiDiCutiBersamaTahunLalu.size();
		}
		if (DateUtil.getYear(new Date()) == Integer.parseInt(request.getYear())) {
			List<ListTanggalCuti> listCutiTahunLaluBelumDisetujui = tanggalCutiDao
					.notApprovedByPermohonan(request.getPegawaiId(), CUTI_TAHUNAN, awalTahunLalu, akhirTahunLalu);
			int presensiCutiBersama = listPresensiTahunLalu.size();
			int sisaJatah = presensiCutiBersama + cutiDiCutiBersama - cutiBersamaTerpakaiTahunLalu;
			int jatahDitangguhkan = listPresensiCutiBersamaBisaDitangguhkan.size()
					- listCutiTahunLaluBelumDisetujui.size();
			if (sisaJatah >= jatahDitangguhkan && jatahDitangguhkan > 0)
				return jatahDitangguhkan;
		}
		return 0;
	}

}
