package com.jasamedika.medifirst2000.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.dao.PegawaiDao;
import com.jasamedika.medifirst2000.dao.RiwayatPenilaianKompetensiPegawaiDao;
import com.jasamedika.medifirst2000.dao.RunningNumberDao;
import com.jasamedika.medifirst2000.dao.StrukHistoriDao;
import com.jasamedika.medifirst2000.entities.KelompokTransaksi;
import com.jasamedika.medifirst2000.entities.KomponenEvaluasi;
import com.jasamedika.medifirst2000.entities.Pegawai;
import com.jasamedika.medifirst2000.entities.PegawaiHistoriEvaluasi;
import com.jasamedika.medifirst2000.entities.PegawaiHistoriEvaluasiKomponen;
import com.jasamedika.medifirst2000.entities.Ruangan;
import com.jasamedika.medifirst2000.entities.RunningNumber;
import com.jasamedika.medifirst2000.entities.StrukHistori;
import com.jasamedika.medifirst2000.service.RiwayatPenilaianKompetensiPegawaiService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.DateUtil;
import com.jasamedika.medifirst2000.util.StringUtil;
import com.jasamedika.medifirst2000.vo.KelompokTransaksiVO;
import com.jasamedika.medifirst2000.vo.KomponenEvaluasiVO;
import com.jasamedika.medifirst2000.vo.PegawaiHistoriEvaluasiKomponenVO;
import com.jasamedika.medifirst2000.vo.PegawaiHistoriEvaluasiVO;
import com.jasamedika.medifirst2000.vo.PegawaiVO;
import com.jasamedika.medifirst2000.vo.RuanganVO;
import com.jasamedika.medifirst2000.vo.StrukHistoriVO;

@Service("RiwayatPenilaianKompetensiPegawaiService")
public class RiwayatPenilaianKompetensiPegawaiServiceImpl implements RiwayatPenilaianKompetensiPegawaiService {

	@Autowired
	private RiwayatPenilaianKompetensiPegawaiDao riwayatPenilaianKompetensiPegawaiDao;

	@Autowired
	private BaseConverterImpl<RuanganVO, Ruangan> ruanganConverter;

	@Autowired
	private StrukHistoriDao strukHistoriDao;

	@Autowired
	private PegawaiDao pegawaiDao;

	@Autowired
	private BaseConverterImpl<StrukHistoriVO, StrukHistori> strukHistoriConverter;

	@Autowired
	private BaseConverterImpl<PegawaiHistoriEvaluasiVO, PegawaiHistoriEvaluasi> pegawaiHistoriEvaluasiConverter;

	@Autowired
	private BaseConverterImpl<PegawaiHistoriEvaluasiKomponenVO, PegawaiHistoriEvaluasiKomponen> pegawaiHistoriEvaluasiKomponenConverter;

	@Autowired
	private BaseConverterImpl<PegawaiVO, Pegawai> pegawaiConverter;

	@Autowired
	private BaseConverterImpl<KomponenEvaluasiVO, KomponenEvaluasi> komponenEvaluasiConverter;

	@Autowired
	private BaseConverterImpl<KelompokTransaksiVO, KelompokTransaksi> kelompokTransaksiConverter;

	@Autowired
	private RunningNumberDao runningNumberDao;

	public Date addingMonth(String tglPenilaian) {
		String tglExpired = "";
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance();
		try {
			calendar.setTime(format.parse(tglPenilaian));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		calendar.add(Calendar.MONTH, 3);
		int day = calendar.get(Calendar.DATE);
		int month = calendar.get(Calendar.MONTH);
		int year = calendar.get(Calendar.YEAR);
		tglExpired = year + "-" + month + "-" + day;
		return calendar.getTime();
	}

	@Override
	@Transactional(readOnly = true)
	public Map<String, Object> getPenilaianKompetensiPegawai(Integer idJabatan, String tglpenilaian,
			Integer idPegawai) {
		Map<String, Object> result = new HashMap<String, Object>();
		List<Map<String, Object>> listData = riwayatPenilaianKompetensiPegawaiDao
				.getPenilaianKompetensiRiwayat(idJabatan);
		// validasi penilaian hanya dapat dilakukan setelah 3 bulan semenjak
		// penilaian
		// terakhir dilakukan
		List<Map<String, Object>> dataPenilaian = riwayatPenilaianKompetensiPegawaiDao.getPenilaian(idPegawai);
		int index = 0;
		for (Map<String, Object> data : dataPenilaian) {
			index++;
			if (index == 1) {
				String tglHistory = (String) data.get("tglHistory");
				Date tglExpired = addingMonth(tglHistory);
				SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
				Calendar calendar = Calendar.getInstance();
				try {
					calendar.setTime(format.parse(tglpenilaian));
				} catch (ParseException e) {
					e.printStackTrace();
				}
				Date tglPenilaian = calendar.getTime();
				if (tglPenilaian.getTime() > tglExpired.getTime()) {
					result.put("status", false);
				} else {
					result.put("status", true);// ga boleh save
				}
			}
		}
		Map<String, Object> data = riwayatPenilaianKompetensiPegawaiDao.getPendidikan(idJabatan);
		String currentPendidikan = (String) data.get("namaPendidikan");
		String masaJabatan = "";
		if (CommonUtil.isNotNullOrEmpty(data.get("tglMasuk"))) {
			masaJabatan = reduceTime(new java.util.Date(), (Date) data.get("tglMasuk"));
		}
		result.put("masaJabatan", masaJabatan);
		result.put("currentPendidikan", currentPendidikan);
		result.put("penilaian", listData);
		return result;
	}

	@Transactional(readOnly = true)
	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
	@Transactional(readOnly = false)
	public Map<String, Object> savePenilaianKompetensiPegawai(StrukHistoriVO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		if (CommonUtil.isNotNullOrEmpty(vo)) {
			Set<PegawaiHistoriEvaluasi> listPegawaiHistoriEvaluasi = new HashSet<PegawaiHistoriEvaluasi>();
			Set<PegawaiHistoriEvaluasiKomponen> listPegawaiHistoriEvaluasiKomponen = new HashSet<PegawaiHistoriEvaluasiKomponen>();

			StrukHistori strukHistori = strukHistoriConverter.transferVOToModel(vo, new StrukHistori());
			if (CommonUtil.isNotNullOrEmpty(vo.getRuangan())) {
				strukHistori.setRuangan(ruanganConverter.transferVOToModelData(vo.getRuangan(), new Ruangan()));
			}
			strukHistori.setNonHistori(getRunningNumber("Struk Histori"));
			// PegawaiHistoriEvaluasi
			for (PegawaiHistoriEvaluasiVO data : vo.getPegawaiHistoriEvaluasi()) {

				PegawaiHistoriEvaluasi pegawaiHistoriEvaluasi = pegawaiHistoriEvaluasiConverter.transferVOToModel(data,
						new PegawaiHistoriEvaluasi());
				pegawaiHistoriEvaluasi.setStrukHistory(strukHistori);
				if (CommonUtil.isNotNullOrEmpty(data.getPegawai())) {
					pegawaiHistoriEvaluasi
							.setPegawai(pegawaiConverter.transferVOToModel(data.getPegawai(), new Pegawai()));
				}
				listPegawaiHistoriEvaluasi.add(pegawaiHistoriEvaluasi);
			}
			strukHistori.getPegawaiHistoriEvaluasi().clear();
			strukHistori.getPegawaiHistoriEvaluasi().addAll(listPegawaiHistoriEvaluasi);
			// PegawaiHistoriEvaluasiKomponen
			for (PegawaiHistoriEvaluasiKomponenVO temp : vo.getPegawaiHistoriEvaluasiKomponen()) {
				PegawaiHistoriEvaluasiKomponen pegawaiHistoriEvaluasiKomponen = pegawaiHistoriEvaluasiKomponenConverter
						.transferVOToModel(temp, new PegawaiHistoriEvaluasiKomponen());
				pegawaiHistoriEvaluasiKomponen.setStrukHistory(strukHistori);
				if (CommonUtil.isNotNullOrEmpty(temp.getPegawai())) {
					pegawaiHistoriEvaluasiKomponen
							.setPegawai(pegawaiConverter.transferVOToModel(temp.getPegawai(), new Pegawai()));
				}

				if (CommonUtil.isNotNullOrEmpty(temp.getKomponenEvaluasi())) {
					pegawaiHistoriEvaluasiKomponen.setKomponenEvaluasi(komponenEvaluasiConverter
							.transferVOToModel(temp.getKomponenEvaluasi(), new KomponenEvaluasi()));
				}
				listPegawaiHistoriEvaluasiKomponen.add(pegawaiHistoriEvaluasiKomponen);
			}
			strukHistori.setKelompokTransaksi(
					kelompokTransaksiConverter.transferVOToModel(vo.getKelompokTransaksi(), new KelompokTransaksi()));
			strukHistori.getPegawaiHistoriEvaluasiKomponen().clear();
			strukHistori.getPegawaiHistoriEvaluasiKomponen().addAll(listPegawaiHistoriEvaluasiKomponen);
			if (CommonUtil.isNotNullOrEmpty(strukHistori)) {
				StrukHistori model = strukHistoriDao.save(strukHistori);
				result.put(model.getNoRec() + "", model.noRec);
			}
		}
		return result;
	}

	@Override
	@Transactional(readOnly = true)
	public List<Map<String, Object>> getGapKompetensiPegawai(Integer idRuangan, String periode) {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		List<Map<String, Object>> listPegawai = pegawaiDao.findByRuanganKerja(idRuangan);// get
																							// id
																							// jabatan
																							// and
																							// id
																							// pegawai
																							// by
																							// ruangan
																							// kerja
		Date start = DateUtil.startMonth(periode);
		Date end = DateUtil.endMonth(periode);
		Integer nos = 0;
		for (Map<String, Object> temp : listPegawai) {

			if (CommonUtil.isNotNullOrEmpty(temp.get("idJabatanInternal"))) {
				Integer idJabatan = (Integer) temp.get("idJabatanInternal");
				List<Map<String, Object>> listKompetensiPegawai = this.filteringKompetensi(idJabatan);

				// get gap kompetensi
				if (CommonUtil.isNotNullOrEmpty(temp.get("idPegawai"))) {

					Map<String, Object> gapKompetensi = new HashMap<String, Object>();
					Integer idPegawai = (Integer) temp.get("idPegawai");
					gapKompetensi.put("idPegawai", idPegawai);
					gapKompetensi.put("namaPegawai", temp.get("namaPegawai"));
					gapKompetensi.put("namaJabatan", temp.get("namaJabatan"));
					gapKompetensi.put("idJabatan", temp.get("idJabatanInternal"));

					Double totalGap = 0.0;
					for (Map<String, Object> kompetensiPegawai : listKompetensiPegawai) {

						Double gap = 0.0;
						Integer idKomponenEvaluasi = (Integer) kompetensiPegawai.get("idKomponenEvaluasi");
						Map<String, Object> dataKompetensi = riwayatPenilaianKompetensiPegawaiDao
								.getKompetensiByPegawai(idPegawai, start, end, idKomponenEvaluasi);
						Double nilaiHasilEvaluasi = 0.0;
						String nilaiStandar = "0";
						if (CommonUtil.isNotNullOrEmpty(kompetensiPegawai.get("nilaiStandar"))) {
							nilaiStandar = (String) kompetensiPegawai.get("nilaiStandar");
						}

						if (CommonUtil.isNotNullOrEmpty(dataKompetensi)) {
							if (CommonUtil.isNotNullOrEmpty(dataKompetensi.get("nilaiHasilEvaluasi"))) {
								nilaiHasilEvaluasi = (Double) dataKompetensi.get("nilaiHasilEvaluasi");
								gap = nilaiHasilEvaluasi - Double.parseDouble(nilaiStandar);
							}
						}
						totalGap += gap;
						String gapHeader = ((String) kompetensiPegawai.get("kompetensi")).replace(" ", "");
						gapKompetensi.put(gapHeader, gap.toString());
						gapKompetensi.put("id" + kompetensiPegawai.get("jenisKompetensi"),
								kompetensiPegawai.get("idKelompokEvaluasi"));
						gapKompetensi.put("" + kompetensiPegawai.get("Kompetensi"),
								kompetensiPegawai.get("jenisKompetensi"));
						gapKompetensi.put("id" + kompetensiPegawai.get("kompetensi"), idKomponenEvaluasi);
						gapKompetensi.put("kompetensi-" + kompetensiPegawai.get("kompetensi"),
								kompetensiPegawai.get("kompetensi"));
					}
					gapKompetensi.put("totalGap", totalGap);
					nos += 1;
					gapKompetensi.put("no", nos);
					result.add(gapKompetensi);
				}
			}
		}
		return result;
	}

	@Override
	@Transactional(readOnly = true)
	public List<Map<String, Object>> filteringKompetensi(Integer idJabatan) {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();

		List<Map<String, Object>> listKompetensi = riwayatPenilaianKompetensiPegawaiDao
				.getKompetensiByRuangan(idJabatan);// getkompetensi basd on
													// jabatan
		List<String> listTempKompetensi = new ArrayList<String>();

		// filtering redundant kompetensi
		for (Map<String, Object> data : listKompetensi) {
			if (CommonUtil.isNotNullOrEmpty(data.get("kompetensi"))) {
				String kompetensi = (String) data.get("kompetensi");
				if (!listTempKompetensi.contains(kompetensi)) {
					listTempKompetensi.add(kompetensi);
					result.add(data);
				}
			}

		}
		return result;
	}

	public List<Map<String, Object>> filteringListKompetensi(List<Map<String, Object>> listKompetensi) {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();

		// List<Map<String,Object>> listKompetensi =
		// riwayatPenilaianKompetensiPegawaiDao.getKompetensiByRuangan(idJabatan);//getkompetensi
		// basd on jabatan
		List<String> listTempKompetensi = new ArrayList<String>();

		// filtering redundant kompetensi
		for (Map<String, Object> data : listKompetensi) {
			if (CommonUtil.isNotNullOrEmpty(data.get("kompetensi"))) {
				String kompetensi = (String) data.get("kompetensi");
				if (!listTempKompetensi.contains(kompetensi)) {
					listTempKompetensi.add(kompetensi);
					result.add(data);
				}
			}

		}
		return result;
	}

	@Override
	@Transactional(readOnly = true)
	public Map<String, Object> getKompetensiPegawai(Integer idRuangan) {
		List<Map<String, Object>> listPegawai = pegawaiDao.findByRuanganKerja(idRuangan);// get
																							// id
																							// jabatan
																							// and
																							// id
																							// pegawai
																							// by
																							// ruangan
																							// kerja
		List<Map<String, Object>> listKelompokEvaluasi = riwayatPenilaianKompetensiPegawaiDao.getKelompokEvaluasi();
		List<Map<String, Object>> listHeader = new ArrayList<Map<String, Object>>();
		Map<String, Object> MaplistHeaderFinal = new HashMap<String, Object>();
		List<Map<String, Object>> listKompetensi = new ArrayList<Map<String, Object>>();
		for (Map<String, Object> temp : listPegawai) {
			if (CommonUtil.isNotNullOrEmpty(temp.get("idJabatanInternal"))) {
				Integer idJabatan = (Integer) temp.get("idJabatanInternal");
				List<Map<String, Object>> tempListKompetensi = riwayatPenilaianKompetensiPegawaiDao
						.getKompetensiByRuangan(idJabatan);// getkompetensi basd
															// on jabatan
				listKompetensi.addAll(tempListKompetensi);
			}

		}
		List<Map<String, Object>> listKompetensiPegawai = this.filteringListKompetensi(listKompetensi);
		Map<String, Object> kompetensiPegawai1 = new HashMap<String, Object>();
		Map<String, Object> headerAttributes1 = new HashMap<String, Object>();
		headerAttributes1.put("style", "text-align: center;");
		kompetensiPegawai1.put("title", "No.");
		kompetensiPegawai1.put("field", "no");
		kompetensiPegawai1.put("width", "50px");
		kompetensiPegawai1.put("headerAttributes", headerAttributes1);
		listHeader.add(kompetensiPegawai1);
		kompetensiPegawai1 = new HashMap<String, Object>();
		kompetensiPegawai1.put("title", "Nama");
		kompetensiPegawai1.put("field", "namaPegawai");
		kompetensiPegawai1.put("width", "200px");
		kompetensiPegawai1.put("headerAttributes", headerAttributes1);
		listHeader.add(kompetensiPegawai1);
		kompetensiPegawai1 = new HashMap<String, Object>();
		kompetensiPegawai1.put("title", "Jabatan.");
		kompetensiPegawai1.put("field", "namaJabatan");
		kompetensiPegawai1.put("width", "200px");
		kompetensiPegawai1.put("headerAttributes", headerAttributes1);
		listHeader.add(kompetensiPegawai1);

		for (Map<String, Object> data : listKelompokEvaluasi) {
			Map<String, Object> kompetensiPegawai = new HashMap<String, Object>();

			List<Map<String, Object>> listTemp = new ArrayList<>();

			for (Map<String, Object> kompetensi : listKompetensiPegawai) {
				String kompete = (String) kompetensi.get("kompetensi");
				kompete = kompete.replace(" ", "");
				if (data.get("idKelompokEvaluasi").equals(kompetensi.get("idKelompokEvaluasi"))) {
					Map<String, Object> kompetensiData = new HashMap<String, Object>();
					String title = "<span class='verticalText'>" + (String) kompetensi.get("kompetensi") + "</span>";
					kompetensiData.put("field", kompete);
					kompetensiData.put("title", title);
					// String style = "{ style: ' width: 15px !important;'}";
					Map<String, Object> headerAttributes = new HashMap<String, Object>();
					headerAttributes.put("style", "width: 15px !important;");
					kompetensiData.put("headerAttributes", headerAttributes);
					listTemp.add(kompetensiData);
				}
			}
			kompetensiPegawai.put("columns", listTemp);
			kompetensiPegawai.put("title", (String) data.get("title"));
			Map<String, Object> headerAttributes = new HashMap<String, Object>();
			headerAttributes.put("style", "height: 10px !important;text-align: center;");
			kompetensiPegawai.put("headerAttributes", headerAttributes);
			listHeader.add(kompetensiPegawai);
		}
		MaplistHeaderFinal.put("scrollable", true);
		MaplistHeaderFinal.put("columns", listHeader);
		return MaplistHeaderFinal;
	}

	public String reduceTime(Date now, Date tglMasuk) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		String result = "";
		if (CommonUtil.isNotNullOrEmpty(now) && CommonUtil.isNotNullOrEmpty(tglMasuk)) {
			Calendar calNow = Calendar.getInstance();
			Calendar calTglMasuk = Calendar.getInstance();
			try {
				calNow.setTime(format.parse(new SimpleDateFormat("yyyy-MM-dd").format(now)));
				calTglMasuk.setTime(format.parse(new SimpleDateFormat("yyyy-MM-dd").format(tglMasuk)));

			} catch (ParseException e) {
				e.printStackTrace();
			}

			int month = calNow.get(Calendar.MONTH) - calTglMasuk.get(Calendar.MONTH);
			int year = calNow.get(Calendar.YEAR) - calTglMasuk.get(Calendar.YEAR);
			if (month < 0) {
				year = year - 1;
				month = 12 + calNow.get(Calendar.MONTH);
				month = month - calTglMasuk.get(Calendar.MONTH);
			}
			result = year + " tahun " + month + " bulan ";
		}

		return result;
	}

	@Override
	@Transactional(readOnly = true)
	public List<Map<String, Object>> getRencanaTindakLanjut() {
		List<Map<String, Object>> result = riwayatPenilaianKompetensiPegawaiDao.getRencanaTindakLanjut();
		return result;
	}

}
