package com.jasamedika.medifirst2000.service.impl;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
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.SkoringTindakanFarmakologiDao;
import com.jasamedika.medifirst2000.dao.SubUnitKerjaDao;
import com.jasamedika.medifirst2000.entities.LoggingUser;
import com.jasamedika.medifirst2000.entities.LoginUser;
import com.jasamedika.medifirst2000.entities.ProdukFarmakologi;
import com.jasamedika.medifirst2000.entities.SkoringTindakanFarmakologi;
import com.jasamedika.medifirst2000.exception.ServiceVOException;
import com.jasamedika.medifirst2000.service.SkoringTindakanFarmakologiService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.vo.ProdukFarmakologiVO;
import com.jasamedika.medifirst2000.vo.SkoringTindakanFarmakologiVO;

/**
 * @author salmanoe
 * @since Jun 20, 2022
 * 
 */
@Service("skoringTindakanFarmakologiService")
public class SkoringTindakanFarmakologiServiceImpl extends BaseVoServiceImpl
		implements SkoringTindakanFarmakologiService {

	@Autowired
	private BaseConverterImpl<SkoringTindakanFarmakologiVO, SkoringTindakanFarmakologi> skoringTindakanConverter;

	@Autowired
	private BaseConverterImpl<ProdukFarmakologiVO, ProdukFarmakologi> produkFarmakologiConverter;

	@Autowired
	private SkoringTindakanFarmakologiDao 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 Farmakologi");
		loggingUser.setReferensiId(idReferensi);
		loggingUser.setReferensi("sdm_skoringtindakanfarmakologi_t");
		loggingUser.setKeterangan(keterangan);

		loggingUserDao.save(loggingUser);
	}

	@Override
	public SkoringTindakanFarmakologiVO add(SkoringTindakanFarmakologiVO vo)
			throws JpaSystemException, ServiceVOException {
		ProdukFarmakologi produk = produkFarmakologiConverter.transferVOToModel(vo.getProduk(),
				new ProdukFarmakologi());
		SkoringTindakanFarmakologi skoringTindakan = skoringTindakanConverter.transferVOToModel(vo,
				new SkoringTindakanFarmakologi());

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

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

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

		return resultVO;
	}

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

		ProdukFarmakologi produk = produkFarmakologiConverter.transferVOToModel(vo.getProduk(),
				new ProdukFarmakologi());
		SkoringTindakanFarmakologi skoringTindakanBaru = skoringTindakanConverter.transferVOToModel(vo,
				skoringTindakanLama);

		skoringTindakanBaru.setProduk(produk);
		skoringTindakanBaru.setTanggalPembaharuanData(new Date());
		SkoringTindakanFarmakologi 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");
		}

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

		return resultVO;
	}

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

		return true;
	}

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

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

		return result;
	}

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

		Iterable<SkoringTindakanFarmakologi> models = skoringTindakanDao.findAll();
		if (CommonUtil.isNotNullOrEmpty(models)) {
			for (SkoringTindakanFarmakologi model : models) {
				SkoringTindakanFarmakologiVO vo = new SkoringTindakanFarmakologiVO();
				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) 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)) {
			data = skoringTindakanDao.findAllEnabled();
		} else if (CommonUtil.isNotNullOrEmpty(namaProduk) && CommonUtil.isNullOrEmpty(isVerif)) {
			data = skoringTindakanDao.findAllEnabledByProduk(namaProduk.toLowerCase());
		} else if (CommonUtil.isNullOrEmpty(namaProduk) && CommonUtil.isNotNullOrEmpty(isVerif)) {
			data = skoringTindakanDao.findAllEnabledByVerif(isVerif);
		} else if (CommonUtil.isNotNullOrEmpty(namaProduk) && CommonUtil.isNotNullOrEmpty(isVerif)) {
			data = skoringTindakanDao.findAllEnabledByProdukVerif(namaProduk.toLowerCase(), isVerif);
		}

		// filtering
		for (Map<String, Object> mapData : data) {
			boolean isContained = false;
			for (Map<String, Object> mapFilter : filter) {
				if (mapData.get("produkId").equals(mapFilter.get("produkId"))) {
					isContained = true;
					break;
				}
			}
			if (!isContained) {
				Map<String, Object> mapFilter = new HashMap<>();
				mapFilter.put("produkId", mapData.get("produkId"));
				filter.add(mapFilter);
			}
		}

		for (Map<String, Object> mapFilter : filter) {
			for (Map<String, Object> mapData : data) {
				if (mapFilter.get("produkId").equals(mapData.get("produkId"))) {
					mapData.put("unitKerjaId", Master.UnitKerja.KSM_LAIN);
					
					result.add(mapData);
					break;
				}
			}
		}

		return result;
	}

	@Override
	public List<Map<String, Object>> findDuplicateSkoring(String namaProduk, Double skor, 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, skor, patternText, noRec);
			if (CommonUtil.isNullOrEmpty(listNorec)) {
				listNorec = skoringTindakanDao.findDupSkoring(replacedNamaProduk, df.format(new Date(tglMulaiBerlaku)),
						patternText, noRec);
			}
		} else {
			listNorec = skoringTindakanDao.findLastDupSkoring(replacedNamaProduk, skor, patternText);
			if (CommonUtil.isNullOrEmpty(listNorec)) {
				listNorec = skoringTindakanDao.findDupSkoring(replacedNamaProduk, 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.KSM_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;
	}

}
