package com.jasamedika.medifirst2000.service.impl;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
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.stereotype.Service;

import com.jasamedika.medifirst2000.constants.Master;
import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.dao.AntrianPasienDiPeriksaDao;
import com.jasamedika.medifirst2000.dao.LogAccDao;
import com.jasamedika.medifirst2000.dao.PasienDaftarDao;
import com.jasamedika.medifirst2000.dao.PelayananPasienDao;
import com.jasamedika.medifirst2000.dao.StrukPelayananDao;
import com.jasamedika.medifirst2000.entities.JenisObat;
import com.jasamedika.medifirst2000.entities.LogAcc;
import com.jasamedika.medifirst2000.entities.PasienDaftar;
import com.jasamedika.medifirst2000.entities.PelayananPasien;
import com.jasamedika.medifirst2000.entities.PelayananPasienDetail;
import com.jasamedika.medifirst2000.entities.Produk;
import com.jasamedika.medifirst2000.service.PelayananPasienService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.vo.JenisObatVO;
import com.jasamedika.medifirst2000.vo.PelayananPasienVO;
import com.jasamedika.medifirst2000.vo.ProdukVO;

/**
 * Implement class for PelayananPasienService
 * 
 * @author Generator
 * @param <T>
 */
@Service("pelayananPasienService")
public class PelayananPasienServiceImpl extends BaseVoServiceImpl implements PelayananPasienService {

	@Autowired
	private BaseConverterImpl<PelayananPasienVO, PelayananPasien> pelayananPasienConverter;

	@Autowired
	private BaseConverterImpl<JenisObatVO, JenisObat> jenisObatConverter;

	@Autowired
	private BaseConverterImpl<ProdukVO, Produk> produkConverter;

	@Autowired
	private PasienDaftarDao pasienDaftarDao;

	@Autowired
	private PelayananPasienDao pelayananPasienDao;

	@Autowired
	private AntrianPasienDiPeriksaDao antrianPasienDiPeriksaDao;

	@Autowired
	private LogAccDao logAccDao;

	@Autowired
	private StrukPelayananDao strukPelayananDao;

	@Override
	public Map<String, Object> savePelayananPasien(PelayananPasienVO vo) {
		Map<String, Object> result = new HashMap<String, Object>();
		PelayananPasien model = new PelayananPasien();
		model = pelayananPasienConverter.transferVOToModel(vo, model);
		model.setPasien(antrianPasienDiPeriksaDao.finByNoIdAndTglRegistrasi(Short.parseShort("0"),
				vo.getPasien().getId(), vo.getTglRegistrasi()));
		if (CommonUtil.isNotNullOrEmpty(vo.getJenisObat())) {
			model.setJenisObat(jenisObatConverter.transferVOToModel(vo.getJenisObat(), new JenisObat()));
		}
		if (CommonUtil.isNotNullOrEmpty(vo.getProduk())) {
			model.setProduk(produkConverter.transferVOToModel(vo.getProduk(), new Produk()));
		}

		PelayananPasien resultDomain = pelayananPasienDao.save(model);
		if (CommonUtil.isNotNullOrEmpty(resultDomain)) {
			result.put("noRec", resultDomain.getNoRec());
		}

		return result;
	}

	@Override
	public Map<String, Object> deletePelayanan(List<Map<String, Object>> listVO) {
		Map<String, Object> result = new HashMap<>();

		if (CommonUtil.isNotNullOrEmpty(listVO)) {

			for (Map<String, Object> vo : listVO) {
				Map<String, Object> check = strukPelayananDao.checkDeletePelayanan((String) vo.get("noRecStruk"));

				if (CommonUtil.isNullOrEmpty(check)) {
					PelayananPasien pelayananPasien = pelayananPasienDao.findOne((String) vo.get("noRec"));
					String norec = pelayananPasien.getNoRec();
					if (CommonUtil.isNotNullOrEmpty(pelayananPasien)) {
						pelayananPasienDao.delete(pelayananPasien);

						LogAcc log = new LogAcc();
						log.setTanggal(new Date());
						if (CommonUtil.isNotNullOrEmpty(norec)) {
							log.setNoReff(norec);
						}
						if (CommonUtil.isNotNullOrEmpty(log)) {
							log.setJenisTransaksi("hapus pelayanan");
							if (CommonUtil.isNotNullOrEmpty(log)) {
								logAccDao.save(log);
							}
						}
					}
				}
			}
		}

		return result;
	}

	@Override
	public Map<String, Object> findTindakanPasienMeninggal(Integer noCm) {
		Map<String, Object> result = new HashMap<>();

		List<Integer> listDetailProdukJenazah = splitDataSettingDatafixed("listDetailProdukJenazah");

		List<Map<String, Object>> tindakanPasienMeninggal = pelayananPasienDao.getTindakanPasienMeninggal(noCm,
				listDetailProdukJenazah);
		Double totalHargaTindakanPasienMeninggal = pelayananPasienDao.getTotalHargaTindakanPasienMeninggal(noCm,
				listDetailProdukJenazah);
		Map<String, Object> dataPasienMeninggal = pelayananPasienDao.getDataPasienMeninggal(noCm);

		result.put("tindakan", tindakanPasienMeninggal);
		result.put("totalHarga", totalHargaTindakanPasienMeninggal);
		result.put("namaPasien", dataPasienMeninggal.get("namaPasien"));
		result.put("alamat", dataPasienMeninggal.get("alamat"));

		return result;
	}

	public Double calculateRemunWithFfs(Integer idKelPasien, Integer idDepartemen, Integer idLayanan,
			String namaLayanan, Integer tipePegawai, Double hargaJual, Double hargaDiskon, Double jumlahLayanan) {
		Double result = 0.0;
		
		List<Integer> idsKonsultasiDokterJaga = splitDataSettingDatafixed("pr_konsultasi_dokter_jaga");

		if (Arrays.asList(Master.KelompokPasien.KELOMPOK_BPJS).contains(idKelPasien)) {
			if (idDepartemen.equals(Master.Departemen.IGD)) {
				if (idsKonsultasiDokterJaga.contains(idLayanan)) {
					result = 30000.0;
				} else {
					result = (hargaJual - hargaDiskon) * jumlahLayanan
							* Master.FeeForService.HK_02_04_III_558_2015_5_B_C_D;
				}
			} else if (idDepartemen.equals(Master.Departemen.RAWAT_INAP)) {
				if (tipePegawai.equals(Master.TipePegawai.PURNA_WAKTU)) {
					result = (hargaJual - hargaDiskon) * jumlahLayanan
							* Master.FeeForService.HK_02_04_III_558_2015_5_B_C_D;
				} else {
					result = 0.0;
				}
			} else {
				result = (hargaJual - hargaDiskon) * jumlahLayanan * Master.FeeForService.HK_02_04_III_558_2015_5_B_C_D;
			}
		} else {
			if (idDepartemen.equals(Master.Departemen.IGD)) {
				if (idsKonsultasiDokterJaga.contains(idLayanan)) {
					result = 30000.0;
				} else {
					result = (hargaJual - hargaDiskon) * jumlahLayanan;
				}
			} else if (idDepartemen.equals(Master.Departemen.RAWAT_INAP)) {
				if (Arrays.stream(Master.KONSUL_VISIT).anyMatch(namaLayanan.toLowerCase()::contains)) {
					if (tipePegawai.equals(Master.TipePegawai.PURNA_WAKTU)) {
						if ((hargaJual - hargaDiskon) < Master.FeeForService.HK_02_04_III_558_2015_4_B_1) {
							result = (hargaJual - hargaDiskon) * jumlahLayanan;
						} else {
							result = Master.FeeForService.HK_02_04_III_558_2015_4_B_1 * jumlahLayanan;
						}
					} else {
						result = (hargaJual - hargaDiskon) * jumlahLayanan;
					}
				} else {
					result = (hargaJual - hargaDiskon) * jumlahLayanan;
				}
			} else {
				result = (hargaJual - hargaDiskon) * jumlahLayanan;
			}
		}

		return result;
	}

	@Override
	public List<Map<String, Object>> hitungRemunerasiDokterDenganFfs(String tglAwal, String tglAkhir) {
		List<Map<String, Object>> result = new ArrayList<>();
		List<Integer> listIdPegawai = new ArrayList<>();

		DecimalFormatSymbols formatRp = new DecimalFormatSymbols();
		formatRp.setCurrencySymbol("Rp");
		formatRp.setMonetaryDecimalSeparator(',');
		formatRp.setGroupingSeparator('.');

		DecimalFormat kursINA = (DecimalFormat) DecimalFormat.getCurrencyInstance();
		kursINA.setDecimalFormatSymbols(formatRp);

		DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		Date dateAwal = new Date();
		Date dateAkhir = new Date();
		try {
			dateAwal = sdf.parse(tglAwal);
			dateAkhir = sdf.parse(tglAkhir);
		} catch (ParseException e) {
			e.printStackTrace();
		}

		List<Map<String, Object>> data = pelayananPasienDao.getDataPendapatan(Master.JenisPegawai.DOKTER, dateAwal,
				dateAkhir);

		for (Map<String, Object> map : data) {
			if (!listIdPegawai.contains(Integer.parseInt(map.get("idPegawai").toString()))
					&& !map.get("namaPegawai").equals("-")) {
				listIdPegawai.add(Integer.parseInt(map.get("idPegawai").toString()));
			}
		}

		for (Integer idPegawai : listIdPegawai) {
			Double remun = 0.0;
			Map<String, Object> mapRes = new HashMap<>();
			for (Map<String, Object> map : data) {
				if (idPegawai.equals(Integer.parseInt(map.get("idPegawai").toString()))) {
					Integer idKelPasien = Integer.parseInt(map.get("idKelPasien").toString());
					Integer idDepartemen = Integer.parseInt(map.get("idDepartemen").toString());
					Integer idLayanan = Integer.parseInt(map.get("idLayanan").toString());
					String namaLayanan = map.get("namaLayanan").toString();
					Integer tipePegawai = Integer.parseInt(map.get("tipePegawai").toString());
					Double hargaJual = Double.parseDouble(map.get("hargaJual").toString());
					Double hargaDiskon = Double.parseDouble(map.get("hargaDiskon").toString());
					Double jumlahLayanan = Double.parseDouble(map.get("jumlahLayanan").toString());

					if (!map.get("idJenisProduk").equals(Master.JenisProduk.OBAT_ALKES)) {
						remun += calculateRemunWithFfs(idKelPasien, idDepartemen, idLayanan, namaLayanan, tipePegawai,
								hargaJual, hargaDiskon, jumlahLayanan);
					}

					mapRes.put("namaPegawai", map.get("namaPegawai"));
				}
			}
			if (!remun.equals(0.0)) {
				mapRes.put("remunValue", remun);
				mapRes.put("remunKurs", kursINA.format(remun).toString());
				result.add(mapRes);
			}
		}

		return result;
	}

	@Override
	public List<String> updateKlaimDiskon(String noRegistrasi, Double totalKlaim, Integer jenisDiskon) {
		List<String> result = new ArrayList<>();

		List<Integer> labRadiologi = new ArrayList<>();
		labRadiologi.add(Master.Ruangan.LABORATORIUM_PATOLOGI_ANATOMI);
		labRadiologi.add(Master.Ruangan.LABORATORIUM_PATOLOGI_KLINIK);
		labRadiologi.add(Master.Ruangan.RADIOLOGI);

		List<Integer> listProdukKlinik = splitDataSettingDatafixed("listProdukDiskonPegawai");
		List<Integer> listProdukTht = splitDataSettingDatafixed("listProdukDiskonThtPegawai");
		List<Integer> listProdukMata = splitDataSettingDatafixed("listProdukDiskonMataPegawai");
		List<Integer> listProdukGigi = splitDataSettingDatafixed("listProdukDiskonGigiPegawai");
		List<Integer> listProdukLabRadiologi = splitDataSettingDatafixed("listProdukDiskonLabRadiologiPasien");
		List<Integer> listProdukFarmasi = splitDataSettingDatafixed("listProdukDiskonObatPegawai");
		List<Integer> listProdukMpp = splitDataSettingDatafixed("listProdukDiskonPasien");

		List<Map<String, Object>> data = pelayananPasienDao.findLayananTagihan(noRegistrasi, jenisDiskon,
				Master.Ruangan.KLINIK_KARYAWAN, listProdukKlinik, Master.Ruangan.POLI_THT, listProdukTht,
				Master.Ruangan.POLI_MATA, listProdukMata, Master.Ruangan.KLINIK_GIGI_KARYAWAN, listProdukGigi,
				labRadiologi, listProdukLabRadiologi, listProdukFarmasi, listProdukMpp);

		List<PelayananPasien> models = new ArrayList<>();
		for (Map<String, Object> map : data) {
			PelayananPasien pp = pelayananPasienDao.findOne(map.get("noRec").toString());
			pp.setHargaDiscount(Double.valueOf(map.get("hargaDiskon").toString()));
			if (CommonUtil.isNotNullOrEmpty(map.get("jasa"))) {
				pp.setJasa(Double.valueOf(map.get("jasa").toString()));
			}
			models.add(pp);
		}

		Iterable<PelayananPasien> resultModels = pelayananPasienDao.save(models);
		if (CommonUtil.isNotNullOrEmpty(resultModels)) {
			for (PelayananPasien pp : resultModels) {
				result.add(pp.getNoRec());
			}
		}

		return result;
	}

	@Override
	public String resetKlaimDiskon(String noRegistrasi) {
		String result = "";

		List<PelayananPasienDetail> detailLayanan = pelayananPasienDao.findDetail(noRegistrasi);
		List<PelayananPasien> layanan = pelayananPasienDao.findAll(noRegistrasi);
		List<PasienDaftar> pendaftaran = pasienDaftarDao.findAll(noRegistrasi);

		boolean exception = false;
		for (PasienDaftar pd : pendaftaran) {
			if (CommonUtil.isNotNullOrEmpty(pd.getStrukPelayanan())
					&& CommonUtil.isNotNullOrEmpty(pd.getStrukPelayanan().getNoRec())
					&& CommonUtil.isNotNullOrEmpty(pd.getStrukBuktiPenerimaan())
					&& CommonUtil.isNotNullOrEmpty(pd.getStrukBuktiPenerimaan().getNoRec())) {
				exception = true;

				result = "Batal diskon gagal, tagihan layanan sudah lunas!";
				break;
			} else if (CommonUtil.isNotNullOrEmpty(pd.getStrukPelayanan())
					&& CommonUtil.isNotNullOrEmpty(pd.getStrukPelayanan().getNoRec())
					&& CommonUtil.isNullOrEmpty(pd.getStrukBuktiPenerimaan())) {
				exception = true;

				result = "Batal diskon gagal, pelayanan sudah terverifikasi!";
				break;
			} else if (CommonUtil.isNullOrEmpty(pd.getDiskonPegawai())
					|| (CommonUtil.isNotNullOrEmpty(pd.getDiskonPegawai()) && pd.getDiskonPegawai() == 0)) {
				exception = true;

				result = "Belum dilakukan diskon!";
				break;
			}
		}

		if (!exception) {
			/*
			 * Update Pelayanan Pasien
			 */
			double jasaObat = 800.00;
			for (PelayananPasien pp : layanan) {
				/*
				 * Get diskon jasamedis
				 */
				double diskonJasamedis = 0.0;
				for (PelayananPasienDetail ppd : detailLayanan) {
					if (pp.getNoRec().equals(ppd.getPelayananPasien().getNoRec())
							&& CommonUtil.isNotNullOrEmpty(ppd.getHargaDiscount()) && ppd.getHargaDiscount() > 0.0) {
						diskonJasamedis += ppd.getHargaDiscount();
					}
				}

				if (CommonUtil.isNotNullOrEmpty(pp.getHargaDiscount()) && pp.getHargaDiscount() > 0.0) {
					/*
					 * Set diskon layanan
					 */
					if (diskonJasamedis > 0.0 && pp.getHargaDiscount() >= diskonJasamedis) {
						pp.setHargaDiscount(diskonJasamedis);
					} else {
						pp.setHargaDiscount(0.0);
					}
					/*
					 * Set diskon obat
					 */
					if (CommonUtil.isNotNullOrEmpty(pp.getStrukResep())
							&& CommonUtil.isNotNullOrEmpty(pp.getStrukResep().getNoRec())) {
						pp.setJasa(jasaObat);
					}
				}
			}
			pelayananPasienDao.save(layanan);

			/*
			 * Update Flag Jenis Diskon Pasien Daftar
			 */
			for (PasienDaftar pd : pendaftaran) {
				pd.setDiskonPegawai(0);
			}
			pasienDaftarDao.save(pendaftaran);

			result = "SUKSES";
		}

		return result;
	}

}