package com.jasamedika.medifirst2000.service.impl;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
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.SettingDataFixedDao;
import com.jasamedika.medifirst2000.dao.SkoringTindakanNakesDao;
import com.jasamedika.medifirst2000.dao.SubUnitKerjaDao;
import com.jasamedika.medifirst2000.entities.LoggingUser;
import com.jasamedika.medifirst2000.entities.LoginUser;
import com.jasamedika.medifirst2000.entities.ProdukNakes;
import com.jasamedika.medifirst2000.entities.SkoringTindakanNakes;
import com.jasamedika.medifirst2000.exception.ServiceVOException;
import com.jasamedika.medifirst2000.service.SkoringTindakanNakesService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.vo.ProdukNakesVO;
import com.jasamedika.medifirst2000.vo.SkoringTindakanNakesVO;

@Service("skoringTindakanNakesService")
public class SkoringTindakanNakesServiceImpl extends BaseVoServiceImpl implements SkoringTindakanNakesService {

	@Autowired
	private BaseConverterImpl<SkoringTindakanNakesVO, SkoringTindakanNakes> skoringTindakanConverter;

	@Autowired
	private BaseConverterImpl<ProdukNakesVO, ProdukNakes> produkNakesConverter;

	@Autowired
	private SkoringTindakanNakesDao skoringTindakanDao;

	@Autowired
	private LoggingUserDao loggingUserDao;

	@Autowired
	private SettingDataFixedDao settingDataFixedDao;

	@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 Nakes");
		loggingUser.setReferensiId(idReferensi);
		loggingUser.setReferensi("sdm_skoringtindakannakes_t");
		loggingUser.setKeterangan(keterangan);

		loggingUserDao.save(loggingUser);
	}

	@Override
	public SkoringTindakanNakesVO add(SkoringTindakanNakesVO vo) throws JpaSystemException, ServiceVOException {
		ProdukNakes produk = produkNakesConverter.transferVOToModel(vo.getProduk(), new ProdukNakes());
		SkoringTindakanNakes skoringTindakan = skoringTindakanConverter.transferVOToModel(vo,
				new SkoringTindakanNakes());

		skoringTindakan.setProduk(produk);
		skoringTindakan.setTanggalPembaharuanData(new Date());
		SkoringTindakanNakes resultModel = skoringTindakanDao.save(skoringTindakan);

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

		SkoringTindakanNakesVO resultVO = new SkoringTindakanNakesVO();
		resultVO = skoringTindakanConverter.transferModelToVO(resultModel, resultVO);

		return resultVO;
	}

	@Override
	public SkoringTindakanNakesVO update(SkoringTindakanNakesVO vo) throws JpaSystemException, ServiceVOException {
		SkoringTindakanNakes skoringTindakanLama = skoringTindakanDao.findOne(vo.getNoRec());

		ProdukNakes produk = produkNakesConverter.transferVOToModel(vo.getProduk(), new ProdukNakes());
		SkoringTindakanNakes skoringTindakanBaru = skoringTindakanConverter.transferVOToModel(vo, skoringTindakanLama);

		skoringTindakanBaru.setProduk(produk);
		skoringTindakanBaru.setTanggalPembaharuanData(new Date());
		SkoringTindakanNakes resultModel = skoringTindakanDao.save(skoringTindakanBaru);

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

		SkoringTindakanNakesVO resultVO = new SkoringTindakanNakesVO();
		resultVO = skoringTindakanConverter.transferModelToVO(resultModel, resultVO);

		return resultVO;
	}

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

		return true;
	}

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

		SkoringTindakanNakes skoringTindakan = skoringTindakanDao.findOne(key);
		if (CommonUtil.isNotNullOrEmpty(skoringTindakan)) {
			result = skoringTindakanConverter.transferModelToVO(skoringTindakan, result);
		}

		return result;
	}

	@Override
	public List<SkoringTindakanNakesVO> findAll() throws JpaSystemException {
		List<SkoringTindakanNakesVO> result = new ArrayList<SkoringTindakanNakesVO>();

		Iterable<SkoringTindakanNakes> models = skoringTindakanDao.findAll();
		if (CommonUtil.isNotNullOrEmpty(models)) {
			for (SkoringTindakanNakes model : models) {
				SkoringTindakanNakesVO vo = new SkoringTindakanNakesVO();
				vo = skoringTindakanConverter.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(String namaProduk, Boolean isVerif, Integer idProfesi)
			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(namaProduk) && CommonUtil.isNullOrEmpty(isVerif)
				&& CommonUtil.isNullOrEmpty(idProfesi)) {
			data = skoringTindakanDao.findAllEnabled();
		} else if (CommonUtil.isNotNullOrEmpty(namaProduk) && CommonUtil.isNullOrEmpty(isVerif)
				&& CommonUtil.isNullOrEmpty(idProfesi)) {
			data = skoringTindakanDao.findAllEnabledByProduk(namaProduk.toLowerCase());
		} else if (CommonUtil.isNullOrEmpty(namaProduk) && CommonUtil.isNotNullOrEmpty(isVerif)
				&& CommonUtil.isNullOrEmpty(idProfesi)) {
			data = skoringTindakanDao.findAllEnabledByVerif(isVerif);
		} else if (CommonUtil.isNullOrEmpty(namaProduk) && CommonUtil.isNullOrEmpty(isVerif)
				&& CommonUtil.isNotNullOrEmpty(idProfesi)) {
			data = skoringTindakanDao.findAllEnabledByProfesi(idProfesi);
		} else if (CommonUtil.isNotNullOrEmpty(namaProduk) && CommonUtil.isNotNullOrEmpty(isVerif)
				&& CommonUtil.isNullOrEmpty(idProfesi)) {
			data = skoringTindakanDao.findAllEnabledByProdukVerif(namaProduk.toLowerCase(), isVerif);
		} else if (CommonUtil.isNotNullOrEmpty(namaProduk) && CommonUtil.isNullOrEmpty(isVerif)
				&& CommonUtil.isNotNullOrEmpty(idProfesi)) {
			data = skoringTindakanDao.findAllEnabledByProdukProfesi(namaProduk.toLowerCase(), idProfesi);
		} else if (CommonUtil.isNullOrEmpty(namaProduk) && CommonUtil.isNotNullOrEmpty(isVerif)
				&& CommonUtil.isNotNullOrEmpty(idProfesi)) {
			data = skoringTindakanDao.findAllEnabledByVerifProfesi(isVerif, idProfesi);
		} else if (CommonUtil.isNotNullOrEmpty(namaProduk) && CommonUtil.isNotNullOrEmpty(isVerif)
				&& CommonUtil.isNotNullOrEmpty(idProfesi)) {
			data = skoringTindakanDao.findAllEnabledByProdukVerifProfesi(namaProduk.toLowerCase(), isVerif, idProfesi);
		}

		// 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("profesiId").equals(mapFilter.get("profesiId"))) {
					isContained = true;
					break;
				}
			}
			if (!isContained) {
				Map<String, Object> mapFilter = new HashMap<>();
				mapFilter.put("produkId", mapData.get("produkId"));
				mapFilter.put("profesiId", mapData.get("profesiId"));
				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("profesiId").equals(mapData.get("profesiId"))) {

					if (Arrays.asList(Master.Profesi.FARMASI).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.INS_FARMASI);
					} else if (Arrays.asList(Master.Profesi.GIZI).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.INS_GIZI);
					} else if (Arrays.asList(Master.Profesi.IK3KL).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.IK3KL);
					} else if (Arrays.asList(Master.Profesi.IP3RS).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.IP3RS);
					} else if (Arrays.asList(Master.Profesi.LAB).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.INS_LAB_TERPADU);
					} else if (Arrays.asList(Master.Profesi.RADIOLOGI).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.INS_RADIOLOGI);
					} else if (Arrays.asList(Master.Profesi.RAJAL).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.INS_RAWAT_JALAN);
					} else if (Arrays.asList(Master.Profesi.REHAB_MEDIK).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.INS_REHAB_MEDIK);
					} else if (Arrays.asList(Master.Profesi.REKAM_MEDIK).contains(mapData.get("profesiId"))) {
						mapData.put("unitKerjaId", Master.UnitKerja.INS_REKAM_MEDIK);
					} else {
						mapData.put("unitKerjaId", Master.UnitKerja.BID_JANG);
					}

					result.add(mapData);
					break;
				}
			}
		}

		return result;
	}

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

		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

		String patternText = settingDataFixedDao.getSettingDataFixed("patternTextDuplicate");
		String replacedNamaProduk = namaProduk.replaceAll(patternText, "").toLowerCase();
		if (CommonUtil.isNotNullOrEmpty(noRec)) {
			listNorec = skoringTindakanDao.findLastDupSkoring(replacedNamaProduk, idProfesi, skor, patternText, noRec);
			if (CommonUtil.isNullOrEmpty(listNorec)) {
				listNorec = skoringTindakanDao.findDupSkoring(replacedNamaProduk, idProfesi,
						df.format(new Date(tglMulaiBerlaku)), patternText, noRec);
			}
		} else {
			listNorec = skoringTindakanDao.findLastDupSkoring(replacedNamaProduk, idProfesi, skor, patternText);
			if (CommonUtil.isNullOrEmpty(listNorec)) {
				listNorec = skoringTindakanDao.findDupSkoring(replacedNamaProduk, idProfesi,
						df.format(new Date(tglMulaiBerlaku)), patternText);
			}
		}

		if (CommonUtil.isNotNullOrEmpty(listNorec)) {
			result = skoringTindakanDao.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.add(Master.UnitKerja.BID_JANG);
		listIdUnitKerja.addAll(Arrays.asList(Master.UnitKerja.NAKES_LAIN));
		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("listSk", 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("listSk", 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("listSk", 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("listSk", 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("listSk", 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("listSk", subUnitKerjaDao.getSubunitKerjaByUnitKerja(listRs));
							}
						}
					}
				}
			}
		}

		return result;
	}

}
