package com.jasamedika.medifirst2000.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.stereotype.Service;

import com.jasamedika.medifirst2000.constants.Master;
import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.dao.LoggingUserDao;
import com.jasamedika.medifirst2000.dao.MapPegawaiJabatanToUnitKerjaDao;
import com.jasamedika.medifirst2000.dao.ProdukDao;
import com.jasamedika.medifirst2000.dao.SettingDataFixedDao;
import com.jasamedika.medifirst2000.dao.SkoringTindakanMedisDao;
import com.jasamedika.medifirst2000.dao.SubUnitKerjaDao;
import com.jasamedika.medifirst2000.entities.LoggingUser;
import com.jasamedika.medifirst2000.entities.LoginUser;
import com.jasamedika.medifirst2000.entities.Produk;
import com.jasamedika.medifirst2000.entities.SkoringTindakanMedis;
import com.jasamedika.medifirst2000.entities.SubUnitKerjaPegawai;
import com.jasamedika.medifirst2000.exception.ServiceVOException;
import com.jasamedika.medifirst2000.service.SkoringTindakanMedisService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.vo.ProdukVO;
import com.jasamedika.medifirst2000.vo.SkoringTindakanMedisVO;
import com.jasamedika.medifirst2000.vo.SubUnitKerjaPegawaiVO;

@Service("skoringTindakanMedisService")
public class SkoringTindakanMedisServiceImpl extends BaseVoServiceImpl implements SkoringTindakanMedisService {

	@Autowired
	private BaseConverterImpl<ProdukVO, Produk> produkConverter;

	@Autowired
	private BaseConverterImpl<SubUnitKerjaPegawaiVO, SubUnitKerjaPegawai> subunitKerjaConverter;

	@Autowired
	private BaseConverterImpl<SkoringTindakanMedisVO, SkoringTindakanMedis> skoringTindakanMedisConverter;

	@Autowired
	private SkoringTindakanMedisDao skoringTindakanMedisDao;

	@Autowired
	private ProdukDao produkDao;

	@Autowired
	private SettingDataFixedDao settingDataFixedDao;

	@Autowired
	private LoggingUserDao loggingUserDao;

	@Autowired
	private MapPegawaiJabatanToUnitKerjaDao mappingJabatanDao;

	@Autowired
	private SubUnitKerjaDao subUnitKerjaDao;

	public void addLoggingUser(Integer idLoginUser, String idReferensi, String keterangan) {
		LoggingUser loggingUser = new LoggingUser();
		LoginUser loginUser = new LoginUser();

		loggingUser.setKdProfile((short) 0);
		loggingUser.setStatusEnabled(true);
		loggingUser.setTanggal(new Date());
		loginUser.setId(idLoginUser);
		loggingUser.setLoginUser(loginUser);
		loggingUser.setJenisLog("Skoring Tindakan Medis");
		loggingUser.setReferensiId(idReferensi);
		loggingUser.setReferensi("sdm_skoringtindakanmedis_t");
		loggingUser.setKeterangan(keterangan);

		loggingUserDao.save(loggingUser);
	}

	@Override
	public SkoringTindakanMedisVO add(SkoringTindakanMedisVO vo) throws JpaSystemException, ServiceVOException {
		Produk produk = produkConverter.transferVOToModel(vo.getProduk(), new Produk());
		SubUnitKerjaPegawai kelompokKerja = subunitKerjaConverter.transferVOToModel(vo.getKelompokKerja(),
				new SubUnitKerjaPegawai());
		SkoringTindakanMedis skoringTindakanMedis = skoringTindakanMedisConverter.transferVOToModel(vo,
				new SkoringTindakanMedis());

		skoringTindakanMedis.setProduk(produk);
		skoringTindakanMedis.setKelompokKerja(kelompokKerja);
		skoringTindakanMedis.setTanggalPembaharuanData(new Date());
		SkoringTindakanMedis resultModel = skoringTindakanMedisDao.save(skoringTindakanMedis);

		addLoggingUser(vo.getLoginUserId(), resultModel.getNoRec(), "Buat data");

		SkoringTindakanMedisVO resultVO = new SkoringTindakanMedisVO();
		resultVO = skoringTindakanMedisConverter.transferModelToVO(resultModel, resultVO);

		return resultVO;
	}

	@Override
	public SkoringTindakanMedisVO update(SkoringTindakanMedisVO vo) throws JpaSystemException, ServiceVOException {
		SkoringTindakanMedis skoringTindakanMedisLama = skoringTindakanMedisDao.findOne(vo.getNoRec());

		Produk produk = produkConverter.transferVOToModel(vo.getProduk(), new Produk());
		SubUnitKerjaPegawai kelompokKerja = subunitKerjaConverter.transferVOToModel(vo.getKelompokKerja(),
				new SubUnitKerjaPegawai());
		SkoringTindakanMedis skoringTindakanMedisBaru = skoringTindakanMedisConverter.transferVOToModel(vo,
				skoringTindakanMedisLama);

		skoringTindakanMedisBaru.setProduk(produk);
		skoringTindakanMedisBaru.setKelompokKerja(kelompokKerja);
		skoringTindakanMedisBaru.setTanggalPembaharuanData(new Date());
		SkoringTindakanMedis resultModel = skoringTindakanMedisDao.save(skoringTindakanMedisBaru);

		if (vo.getStatusEnabled()) {
			addLoggingUser(vo.getLoginUserId(), resultModel.getNoRec(), "Edit data");
		} else if (!vo.getStatusEnabled()) {
			addLoggingUser(vo.getLoginUserId(), resultModel.getNoRec(), "Hapus data");
		}

		SkoringTindakanMedisVO resultVO = new SkoringTindakanMedisVO();
		resultVO = skoringTindakanMedisConverter.transferModelToVO(resultModel, resultVO);

		return resultVO;
	}

	@Override
	public Boolean delete(String key) throws JpaSystemException {
		skoringTindakanMedisDao.delete(key);

		return true;
	}

	@Override
	public SkoringTindakanMedisVO findById(String key) throws JpaSystemException {
		SkoringTindakanMedisVO result = new SkoringTindakanMedisVO();

		SkoringTindakanMedis skoringTindakanMedis = skoringTindakanMedisDao.findOne(key);
		if (CommonUtil.isNotNullOrEmpty(skoringTindakanMedis)) {
			result = skoringTindakanMedisConverter.transferModelToVO(skoringTindakanMedis, result);
		}

		return result;
	}

	@Override
	public List<SkoringTindakanMedisVO> findAll() throws JpaSystemException {
		List<SkoringTindakanMedisVO> result = new ArrayList<SkoringTindakanMedisVO>();
		Iterable<SkoringTindakanMedis> models = skoringTindakanMedisDao.findAll();
		for (SkoringTindakanMedis model : models) {
			SkoringTindakanMedisVO vo = new SkoringTindakanMedisVO();
			vo = skoringTindakanMedisConverter.transferModelToVO(model, vo);
			result.add(vo);
		}

		return result;
	}

	@Override
	public Map<String, Object> findAllWithPageAndLimitAndSortByAndDirectionParameter(Integer page, Integer limit,
			String sort, String dir) {

		return null;
	}

	@Override
	public List<Map<String, Object>> findAllEnabled(List<Integer> listIdKelompokKerja, String namaProduk,
			String detailProduk, Boolean statusVerifikasi) throws JpaSystemException {
		List<Map<String, Object>> result = new ArrayList<>();
		List<Map<String, Object>> data = new ArrayList<>();
		List<Map<String, Object>> filter = new ArrayList<>();

		if (CommonUtil.isNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNullOrEmpty(namaProduk)
				&& CommonUtil.isNullOrEmpty(detailProduk) && CommonUtil.isNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabled();
		} else if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNullOrEmpty(namaProduk)
				&& CommonUtil.isNullOrEmpty(detailProduk) && CommonUtil.isNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByUnit(listIdKelompokKerja);
		} else if (CommonUtil.isNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNotNullOrEmpty(namaProduk)
				&& CommonUtil.isNullOrEmpty(detailProduk) && CommonUtil.isNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByProduk(namaProduk.toLowerCase());
		} else if (CommonUtil.isNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNullOrEmpty(namaProduk)
				&& CommonUtil.isNotNullOrEmpty(detailProduk) && CommonUtil.isNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByDetail(detailProduk.toLowerCase());
		} else if (CommonUtil.isNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNullOrEmpty(namaProduk)
				&& CommonUtil.isNullOrEmpty(detailProduk) && CommonUtil.isNotNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByVerif(statusVerifikasi);
		} else if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNotNullOrEmpty(namaProduk)
				&& CommonUtil.isNullOrEmpty(detailProduk) && CommonUtil.isNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByUnitProduk(listIdKelompokKerja, namaProduk.toLowerCase());
		} else if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNullOrEmpty(namaProduk)
				&& CommonUtil.isNotNullOrEmpty(detailProduk) && CommonUtil.isNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByUnitDetail(listIdKelompokKerja, detailProduk.toLowerCase());
		} else if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNullOrEmpty(namaProduk)
				&& CommonUtil.isNullOrEmpty(detailProduk) && CommonUtil.isNotNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByUnitVerif(listIdKelompokKerja, statusVerifikasi);
		} else if (CommonUtil.isNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNotNullOrEmpty(namaProduk)
				&& CommonUtil.isNotNullOrEmpty(detailProduk) && CommonUtil.isNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByProdukDetail(namaProduk.toLowerCase(),
					detailProduk.toLowerCase());
		} else if (CommonUtil.isNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNotNullOrEmpty(namaProduk)
				&& CommonUtil.isNullOrEmpty(detailProduk) && CommonUtil.isNotNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByProdukVerif(namaProduk.toLowerCase(), statusVerifikasi);
		} else if (CommonUtil.isNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNullOrEmpty(namaProduk)
				&& CommonUtil.isNotNullOrEmpty(detailProduk) && CommonUtil.isNotNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByDetailVerif(detailProduk.toLowerCase(), statusVerifikasi);
		} else if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNotNullOrEmpty(namaProduk)
				&& CommonUtil.isNotNullOrEmpty(detailProduk) && CommonUtil.isNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByUnitProdukDetail(listIdKelompokKerja,
					namaProduk.toLowerCase(), detailProduk.toLowerCase());
		} else if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNotNullOrEmpty(namaProduk)
				&& CommonUtil.isNullOrEmpty(detailProduk) && CommonUtil.isNotNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByUnitProdukVerif(listIdKelompokKerja,
					namaProduk.toLowerCase(), statusVerifikasi);
		} else if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNullOrEmpty(namaProduk)
				&& CommonUtil.isNotNullOrEmpty(detailProduk) && CommonUtil.isNotNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByUnitDetailVerif(listIdKelompokKerja,
					detailProduk.toLowerCase(), statusVerifikasi);
		} else if (CommonUtil.isNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNotNullOrEmpty(namaProduk)
				&& CommonUtil.isNotNullOrEmpty(detailProduk) && CommonUtil.isNotNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByProdukDetailVerif(namaProduk.toLowerCase(),
					detailProduk.toLowerCase(), statusVerifikasi);
		} else if (CommonUtil.isNotNullOrEmpty(listIdKelompokKerja) && CommonUtil.isNotNullOrEmpty(namaProduk)
				&& CommonUtil.isNotNullOrEmpty(detailProduk) && CommonUtil.isNotNullOrEmpty(statusVerifikasi)) {
			data = skoringTindakanMedisDao.findAllEnabledByUnitProdukDetailVerif(listIdKelompokKerja,
					namaProduk.toLowerCase(), detailProduk.toLowerCase(), statusVerifikasi);
		}

		// filtering
		for (Map<String, Object> mapData : data) {
			boolean isContained = false;
			for (Map<String, Object> mapFilter : filter) {
				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"));
				filter.add(mapFilter);
			}
		}

		for (Map<String, Object> mapFilter : filter) {
			for (Map<String, Object> mapData : data) {
				if (mapFilter.get("produkId").equals(mapData.get("produkId"))
						&& mapFilter.get("kelompokKerjaId").equals(mapData.get("kelompokKerjaId"))) {
					result.add(mapData);
					break;
				}
			}
		}

		return result;
	}

	@Override
	public List<Map<String, Object>> findDaftarInputTindakanByRuanganKelas(Integer idRuangan)
			throws JpaSystemException {
		List<Map<String, Object>> result = produkDao.findDaftarInputTindakanByRuangan(idRuangan);

		return result;
	}

	@Override
	public List<Map<String, Object>> findDuplicateSkoring(String namaProduk, Integer idKelompokKerja, Double skor,
			String detailProduk, String noRec) throws JpaSystemException {
		List<Map<String, Object>> result = new ArrayList<>();
		List<String> listNorec = new ArrayList<>();

		String patternText = settingDataFixedDao.getSettingDataFixed("patternTextDuplicate");
		String replacedNamaProduk = namaProduk.replaceAll(patternText, "").toLowerCase();
		String replacedDetailProduk = detailProduk.replaceAll(patternText, "").toLowerCase();
		if (CommonUtil.isNotNullOrEmpty(noRec)) {
			listNorec = skoringTindakanMedisDao.findDupSkoring(replacedNamaProduk, idKelompokKerja, skor, patternText,
					replacedDetailProduk, noRec);
		} else {
			listNorec = skoringTindakanMedisDao.findDupSkoring(replacedNamaProduk, idKelompokKerja, skor, patternText,
					replacedDetailProduk);
		}

		if (CommonUtil.isNotNullOrEmpty(listNorec)) {
			result = skoringTindakanMedisDao.findAllDup(listNorec);
		}

		return result;
	}

	@Override
	public Map<String, Object> findAkses(Integer idPegawai) throws JpaSystemException {
		Map<String, Object> result = new HashMap<>();
		List<Integer> listRs = new ArrayList<>();
		List<Integer> listIdUnitKerja = new ArrayList<>();
		List<Integer> listUnitKerjaSuperuser = new ArrayList<>();

		listIdUnitKerja.addAll(Arrays.asList(Master.UnitKerja.KSM));
		listUnitKerjaSuperuser.add(Master.UnitKerja.BAG_SDM);

		List<Map<String, Object>> listSuperuser = mappingJabatanDao.findAksesPegawaiPenilai(listIdUnitKerja, idPegawai);
		listSuperuser.addAll(mappingJabatanDao.findAksesPegawaiStaf(listUnitKerjaSuperuser, idPegawai));
		listSuperuser.addAll(mappingJabatanDao.findAksesPegawaiAtasan(listUnitKerjaSuperuser, idPegawai));
		listSuperuser.addAll(mappingJabatanDao.findAksesPegawaiPenilai(listUnitKerjaSuperuser, idPegawai));
		if (CommonUtil.isNotNullOrEmpty(listSuperuser)) {
			listRs.addAll(listIdUnitKerja);

			result.put("isSuperuser", true);
			result.put("isAtasan", false);
			result.put("isStaf", false);
			result.put("listId", listRs);
			result.put("listKk", subUnitKerjaDao.getSubunitKerjaByUnitKerja(listRs));
		} else {
			List<Map<String, Object>> listAtasan = mappingJabatanDao.findAksesPegawaiAtasan(listIdUnitKerja, idPegawai);
			if (CommonUtil.isNotNullOrEmpty(listAtasan)) {
				for (Map<String, Object> map : listAtasan) {
					if (!listRs.contains(Integer.valueOf(map.get("unitKerjaId").toString()))) {
						listRs.add(Integer.valueOf(map.get("unitKerjaId").toString()));
					}
				}

				result.put("isSuperuser", false);
				result.put("isAtasan", true);
				result.put("isStaf", false);
				result.put("listId", listRs);
				result.put("listKk", subUnitKerjaDao.getSubunitKerjaByUnitKerja(listRs));
			} else {
				List<Map<String, Object>> listStaf = mappingJabatanDao.findAksesPegawaiStaf(listIdUnitKerja, idPegawai);
				if (CommonUtil.isNotNullOrEmpty(listStaf)) {
					for (Map<String, Object> map : listStaf) {
						if (!listRs.contains(Integer.valueOf(map.get("unitKerjaId").toString()))) {
							listRs.add(Integer.valueOf(map.get("unitKerjaId").toString()));
						}
					}

					result.put("isSuperuser", false);
					result.put("isAtasan", false);
					result.put("isStaf", true);
					result.put("listId", listRs);
					result.put("listKk", subUnitKerjaDao.getSubunitKerjaByUnitKerja(listRs));
				} else {
					List<Map<String, Object>> listSuperElse = mappingJabatanDao.findAksesPegawaiPenilai(idPegawai);
					if (CommonUtil.isNotNullOrEmpty(listSuperElse)) {
						for (Map<String, Object> map : listSuperElse) {
							if (!listRs.contains(Integer.valueOf(map.get("unitKerjaId").toString()))) {
								listRs.add(Integer.valueOf(map.get("unitKerjaId").toString()));
							}
						}

						result.put("isSuperuser", false);
						result.put("isAtasan", false);
						result.put("isStaf", false);
						result.put("listId", listRs);
						result.put("listKk", subUnitKerjaDao.getSubunitKerjaByUnitKerja(listRs));
					} else {
						List<Map<String, Object>> listAtasanElse = mappingJabatanDao.findAksesPegawaiAtasan(idPegawai);
						if (CommonUtil.isNotNullOrEmpty(listAtasanElse)) {
							for (Map<String, Object> map : listAtasanElse) {
								if (!listRs.contains(Integer.valueOf(map.get("unitKerjaId").toString()))) {
									listRs.add(Integer.valueOf(map.get("unitKerjaId").toString()));
								}
							}

							result.put("isSuperuser", false);
							result.put("isAtasan", false);
							result.put("isStaf", false);
							result.put("listId", listRs);
							result.put("listKk", subUnitKerjaDao.getSubunitKerjaByUnitKerja(listRs));
						} else {
							List<Map<String, Object>> listStafElse = mappingJabatanDao.findAksesPegawaiStaf(idPegawai);
							if (CommonUtil.isNotNullOrEmpty(listStafElse)) {
								for (Map<String, Object> map : listStafElse) {
									if (!listRs.contains(Integer.valueOf(map.get("unitKerjaId").toString()))) {
										listRs.add(Integer.valueOf(map.get("unitKerjaId").toString()));
									}
								}

								result.put("isSuperuser", false);
								result.put("isAtasan", false);
								result.put("isStaf", false);
								result.put("listId", listRs);
								result.put("listKk", subUnitKerjaDao.getSubunitKerjaByUnitKerja(listRs));
							}
						}
					}
				}
			}
		}

		return result;
	}

}
