package com.jasamedika.medifirst2000.service.impl;

import com.jasamedika.medifirst2000.constants.Master;
import com.jasamedika.medifirst2000.dao.*;
import com.jasamedika.medifirst2000.entities.*;
import com.jasamedika.medifirst2000.etl.pasien.constant.StatusMigrasi;
import com.jasamedika.medifirst2000.etl.pasien.dto.*;
import com.jasamedika.medifirst2000.service.MigrasiPasienService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.jasamedika.medifirst2000.etl.pasien.constant.CaraMeninggal.*;
import static com.jasamedika.medifirst2000.etl.pasien.constant.HubunganKeluarga.ANAK;
import static com.jasamedika.medifirst2000.etl.pasien.constant.JenisAlamat.DOMISILI;
import static com.jasamedika.medifirst2000.etl.pasien.constant.JenisAlamat.IDENTITAS;
import static com.jasamedika.medifirst2000.etl.pasien.constant.JenisIdentitas.KTP;
import static com.jasamedika.medifirst2000.etl.pasien.constant.Pekerjaan.*;
import static com.jasamedika.medifirst2000.etl.pasien.constant.Pendidikan.*;
import static com.jasamedika.medifirst2000.etl.pasien.constant.StatusMigrasi.*;
import static com.jasamedika.medifirst2000.etl.pasien.constant.StatusPerkawinan.*;

/**
 * @author Salman
 * @version 1.0.0
 * @since 06/11/2023
 */
@Service
@Transactional
public class MigrasiPasienServiceImpl implements MigrasiPasienService {
	@Autowired
	private MigrasiPasienDao migrasiPasienDao;

	@Autowired
	private PasienDaftarDao pasienDaftarDao;

	@Autowired
	private PasienDao pasienDao;

	@Autowired
	private AlamatDao alamatDao;

	@Autowired
	private DokumenVedikaDao dokumenVedikaDao;

	@Autowired
	private AsuransiPasienDao asuransiPasienDao;

	@Override
	public void newMigrate() {
		List<MigrasiPasien> models = new ArrayList<>();
		List<Pasien> oneHundredPasien = pasienDao.find100LatestByNotMigrateYet();
		List<Integer> oneHundredIdPasien = oneHundredPasien.stream().map(Pasien::getId).collect(Collectors.toList());
		oneHundredIdPasien.forEach(id -> {
			MigrasiPasien migrasiPasien = new MigrasiPasien();
			Pasien pasien = new Pasien();
			pasien.setId(id);
			migrasiPasien.setPasien(pasien);
			migrasiPasien.setKdProfile((short) 0);
			migrasiPasien.setStatusEnabled(true);
			models.add(migrasiPasien);
		});
		migrasiPasienDao.save(models);
	}

	@Override
	public List<PasienDto> extractAndTransform() {
		List<PasienDto> dtoList = new ArrayList<>();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
		List<StatusMigrasi> statusMigrasiList = new ArrayList<>(Arrays.asList(BELUM_KIRIM, PEMBAHARUAN));
		List<Pasien> listPasien = migrasiPasienDao.findPasienByStatusMigrasiIn(statusMigrasiList);
		if (CommonUtil.isNotNullOrEmpty(listPasien)) {
			List<Integer> listIdPasien = listPasien.stream().map(Pasien::getId).collect(Collectors.toList());
			List<String> listNoCmPasien = listPasien.stream().map(Pasien::getNoCm).collect(Collectors.toList());
			List<Map<String, Object>> listCaraMeninggal = pasienDaftarDao
					.findPenyebabKematianByPasienIdIn(listIdPasien);
			List<Alamat> listAlamat = alamatDao.findByPasienIdIn(listIdPasien);
			List<DokumenVedika> listDokumenVedika = dokumenVedikaDao.findByPasienNoMrIn(listNoCmPasien);
			List<Pasien> listPasienAnak = pasienDao.findAnakByNoCmOfIbu(listNoCmPasien);
			List<AsuransiPasien> listAsuransi = asuransiPasienDao.findByPasienIdIn(listIdPasien);
			listPasien.forEach(pasien -> {
				PasienDto.PasienDtoBuilder dtoBuilder = PasienDto.builder();
				dtoBuilder.status("AKTIF");
				dtoBuilder.noRekamMedis(Long.parseLong(pasien.getNoCm()));
				dtoBuilder.namaLengkap(pasien.getNamaPasien());
				dtoBuilder.namaPanggilan(CommonUtil.isNotNullOrEmpty(pasien.getNamaDepan()) ? pasien.getNamaDepan()
						: pasien.getNamaPasien().split(" ")[0]);
				dtoBuilder.isKelahiranRS(pasien.getNoCm().equals(pasien.getReportDisplay()));
				dtoBuilder.tempatLahir(pasien.getTempatLahir());
				dtoBuilder.caraRegistrasi("INTERNAL");
				if (CommonUtil.isNotNullOrEmpty(pasien.getTglLahir()))
					dtoBuilder.tanggalLahir(dateFormat.format(pasien.getTglLahir()));
				dtoBuilder.surel(pasien.getEmail());
				if (CommonUtil.isNotNullOrEmpty(pasien.getTitlePasienId()))
					dtoBuilder.sapaan(SapaanDto.builder().id(pasien.getTitlePasienId().longValue()).build());
				dtoBuilder.identitas(new HashSet<>(Collections.singletonList(
						IdentitasDto.builder().jenisIdentitas(JenisIdentitasDto.builder().id(KTP.id()).build())
								.noIdentitas(pasien.getNoIdentitas()).build())));
				if (CommonUtil.isNotNullOrEmpty(pasien.getJenisKelaminId()))
					dtoBuilder
							.jenisKelamin(JenisKelaminDto.builder().id(pasien.getJenisKelaminId().longValue()).build());
				if (CommonUtil.isNotNullOrEmpty(pasien.getGolonganDarahId()) && pasien.getGolonganDarahId() != 0)
					dtoBuilder.golonganDarah(
							GolonganDarahDto.builder().id(pasien.getGolonganDarahId().longValue()).build());
				listCaraMeninggal.stream().filter(c -> pasien.getId().equals(c.get("idPasien"))).findFirst()
						.ifPresent(c -> {
							if (CommonUtil.isNotNullOrEmpty(c.get("idPenyebabKematian"))) {
								if (Master.CaraMeninggal.BAWAH_DAN_48_JAM.equals(c.get("idPenyebabKematian")))
									dtoBuilder.caraMeninggal(
											CaraMeninggalDto.builder().id(BAWAH_DAN_48_JAM.id()).build());
								if (Master.CaraMeninggal.ATAS_48_JAM.equals(c.get("idPenyebabKematian")))
									dtoBuilder.caraMeninggal(CaraMeninggalDto.builder().id(ATAS_48_JAM.id()).build());
								if (Master.CaraMeninggal.BAWAH_DAN_8_JAM.equals(c.get("idPenyebabKematian")))
									dtoBuilder
											.caraMeninggal(CaraMeninggalDto.builder().id(BAWAH_DAN_8_JAM.id()).build());
								if (Master.CaraMeninggal.ATAS_8_JAM.equals(c.get("idPenyebabKematian")))
									dtoBuilder.caraMeninggal(CaraMeninggalDto.builder().id(ATAS_8_JAM.id()).build());
								if (Master.CaraMeninggal.DOA.equals(c.get("idPenyebabKematian")))
									dtoBuilder.caraMeninggal(CaraMeninggalDto.builder().id(DOA.id()).build());
								if (Master.CaraMeninggal.BLUECODE.equals(c.get("idPenyebabKematian")))
									dtoBuilder.caraMeninggal(CaraMeninggalDto.builder().id(BLUECODE.id()).build());
								if (Arrays.asList(Master.CaraMeninggal.LAHIR)
										.contains(Integer.parseInt(c.get("idPenyebabKematian").toString())))
									dtoBuilder.caraMeninggal(CaraMeninggalDto.builder().id(LAHIR.id()).build());
							}
						});
				if (CommonUtil.isNotNullOrEmpty(pasien.getKebangsaanId()))
					dtoBuilder.kewarganegaraan(
							KewarganegaraanDto.builder().id(pasien.getKebangsaanId().longValue()).build());
				if (CommonUtil.isNotNullOrEmpty(pasien.getNegaraId()))
					dtoBuilder.negara(NegaraDto.builder().id(pasien.getNegaraId().longValue()).build());
				if (CommonUtil.isNotNullOrEmpty(pasien.getAgamaId()))
					dtoBuilder.agama(AgamaDto.builder().id(pasien.getAgamaId().longValue()).build());
				{
					if (Master.Pendidikan.TIDAK_SEKOLAH.equals(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(TIDAK_SEKOLAH.id()).build());
					if (Master.Pendidikan.SD.equals(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(SD.id()).build());
					if (Master.Pendidikan.SLTP_SEDERAJAT.equals(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(SLTP_SEDERAJAT.id()).build());
					if (Master.Pendidikan.SLTA_SEDERAJAT.equals(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(SLTA_SEDERAJAT.id()).build());
					if (Arrays.asList(Master.Pendidikan.D1_SAMPAI_D3_SEDERAJAT).contains(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(D1_SAMPAI_D3_SEDERAJAT.id()).build());
					if (Master.Pendidikan.D4.equals(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(D4.id()).build());
					if (Master.Pendidikan.S1.equals(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(S1.id()).build());
					if (Master.Pendidikan.S2.equals(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(S2.id()).build());
					if (Master.Pendidikan.S3.equals(pasien.getPendidikanId()))
						dtoBuilder.pendidikan(PendidikanDto.builder().id(S3.id()).build());
				}
				{
					List<Alamat> alamatPasien = listAlamat.stream()
							.filter(alamat -> pasien.getId().equals(alamat.getPasienId())).collect(Collectors.toList());
					dtoBuilder.alamat(setAlamat(alamatPasien));
				}
				{
					Set<GawaiDto> gawaiDto = new HashSet<>();
					if (NumberUtils.isNumber(pasien.getNoTelepon()) && pasien.getNoTelepon().charAt(0) == '0')
						gawaiDto.add(
								GawaiDto.builder().noGawai(Long.parseLong("62" + numbersOnly(pasien.getNoTelepon())))
										.jenisGawai(JenisGawaiDto.builder().id(1L).build()).build());
					if (NumberUtils.isNumber(pasien.getNoHp()) && pasien.getNoHp().charAt(0) == '0')
						gawaiDto.add(GawaiDto.builder().noGawai(Long.parseLong("62" + numbersOnly(pasien.getNoHp())))
								.jenisGawai(JenisGawaiDto.builder().id(2L).build()).build());
					dtoBuilder.gawai(gawaiDto);
				}
				{
					if (Master.Pekerjaan.TIDAK_BEKERJA.equals(pasien.getPekerjaanId()))
						dtoBuilder.pekerjaan(PekerjaanDto.builder().id(TIDAK_BEKERJA.id()).build());
					if (Master.Pekerjaan.PNS.equals(pasien.getPekerjaanId()))
						dtoBuilder.pekerjaan(PekerjaanDto.builder().id(PNS.id()).build());
					if (Master.Pekerjaan.TNI_ATAU_POLRI.equals(pasien.getPekerjaanId()))
						dtoBuilder.pekerjaan(PekerjaanDto.builder().id(TNI_ATAU_POLRI.id()).build());
					if (Master.Pekerjaan.BUMN.equals(pasien.getPekerjaanId()))
						dtoBuilder.pekerjaan(PekerjaanDto.builder().id(BUMN.id()).build());
					if (Arrays.asList(Master.Pekerjaan.PEGAWAI_SWASTA_ATAU_WIRAUSAHA).contains(pasien.getPekerjaanId()))
						dtoBuilder.pekerjaan(PekerjaanDto.builder().id(PEGAWAI_SWASTA_ATAU_WIRAUSAHA.id()).build());
				}
				{
					if (Master.StatusPerkawinan.KAWIN.equals(pasien.getStatusPerkawinanId())) {
						dtoBuilder.statusPerkawinan(StatusPerkawinanDto.builder().id(KAWIN.id()).build());
					} else if (Master.StatusPerkawinan.CERAI_HIDUP.equals(pasien.getStatusPerkawinanId())) {
						dtoBuilder.statusPerkawinan(StatusPerkawinanDto.builder().id(CERAI_HIDUP.id()).build());
					} else if (Master.StatusPerkawinan.CERAI_MATI.equals(pasien.getStatusPerkawinanId())) {
						dtoBuilder.statusPerkawinan(StatusPerkawinanDto.builder().id(CERAI_MATI.id()).build());
					} else {
						dtoBuilder.statusPerkawinan(StatusPerkawinanDto.builder().id(BELUM_KAWIN.id()).build());
					}
				}
				{
					dtoBuilder.berkas(setBerkas(listDokumenVedika));
				}
				{
					List<Pasien> pasienAnak = listPasienAnak.stream()
							.filter(anak -> pasien.getNoCm().equals(anak.getReportDisplay()))
							.collect(Collectors.toList());
					dtoBuilder.keluarga(setAnak(pasienAnak));
				}
				{
					List<AsuransiPasien> asuransiPasien = listAsuransi.stream()
							.filter(asuransi -> pasien.getId().equals(asuransi.getNoCmId()))
							.collect(Collectors.toList());
					dtoBuilder.jaminan(setJaminan(asuransiPasien));
				}
				dtoList.add(dtoBuilder.build());
			});
		}
		return dtoList;
	}

	private Set<AlamatDto> setAlamat(List<Alamat> listAlamat) {
		Set<AlamatDto> dtoList = new HashSet<>();
		listAlamat.forEach(alamat -> {
			AlamatDto.AlamatDtoBuilder dtoBuilder = AlamatDto.builder();
			dtoBuilder.alamat(alamat.getAlamatLengkap());
			if (CommonUtil.isNotNullOrEmpty(alamat.getRtrw())) {
				if (alamat.getRtrw().split(" ")[0].equals("RT"))
					dtoBuilder.rt(Integer.parseInt(alamat.getRtrw().split(" ")[1]));
				if (alamat.getRtrw().split(" ")[2].equals("RW"))
					dtoBuilder.rw(Integer.parseInt(alamat.getRtrw().split(" ")[3]));
			}
			if (NumberUtils.isNumber(alamat.getKodePos()))
				dtoBuilder.kodePos(Integer.valueOf(alamat.getKodePos()));
			{
				if (Master.JenisAlamat.IDENTITAS.equals(alamat.getJenisAlamatId()))
					dtoBuilder.jenisAlamat(JenisAlamatDto.builder().id(IDENTITAS.id()).build());
				if (Master.JenisAlamat.DOMISILI.equals(alamat.getJenisAlamatId())
						|| Master.JenisAlamat.RUMAH.equals(alamat.getJenisAlamatId()))
					dtoBuilder.jenisAlamat(JenisAlamatDto.builder().id(DOMISILI.id()).build());
			}
			if (CommonUtil.isNotNullOrEmpty(alamat.getDesaKelurahan())
					&& CommonUtil.isNotNullOrEmpty(alamat.getDesaKelurahan().getMigrasiKelurahanDesaId()))
				dtoBuilder.kelurahanDesa(
						KelurahanDesaDto.builder().id(alamat.getDesaKelurahan().getMigrasiKelurahanDesaId()).build());
			if (CommonUtil.isNotNullOrEmpty(alamat.getNegaraId()))
				dtoBuilder.negara(NegaraDto.builder().id(alamat.getNegaraId().longValue()).build());
			dtoList.add(dtoBuilder.build());
		});
		return dtoList;
	}

	private Set<BerkasDto> setBerkas(List<DokumenVedika> listDokumenVedika) {
		Set<BerkasDto> dtoList = new HashSet<>();
		listDokumenVedika.forEach(dokumenVedika -> {
			BerkasDto.BerkasDtoBuilder dtoBuilder = BerkasDto.builder();
			dtoBuilder.judulBerkas(dokumenVedika.getNamaFile());
			dtoBuilder.lss(dokumenVedika.getUrl());
			if (CommonUtil.isNotNullOrEmpty(dokumenVedika.getJenisBerkasId()))
				dtoBuilder
						.jenisBerkas(JenisBerkasDto.builder().id(dokumenVedika.getJenisBerkasId().longValue()).build());
			dtoList.add(dtoBuilder.build());
		});
		return dtoList;
	}

	private Set<KeluargaDto> setAnak(List<Pasien> listPasienAnak) {
		Set<KeluargaDto> dtoList = new HashSet<>();
		listPasienAnak.forEach(anak -> {
			KeluargaDto.KeluargaDtoBuilder dtoBuilder = KeluargaDto.builder();
			dtoBuilder.namaLengkap(anak.getNamaPasien());
			dtoBuilder.namaPanggilan(anak.getNamaDepan());
			dtoBuilder.surel(anak.getEmail());
			if (NumberUtils.isNumber(anak.getNoHp()) && anak.getNoHp().charAt(0) == '0')
				dtoBuilder.noGawai(Long.parseLong("62" + numbersOnly(anak.getNoHp())));
			dtoBuilder.hubunganKeluarga(HubunganKeluargaDto.builder().id(ANAK.id()).build());
			dtoList.add(dtoBuilder.build());
		});
		return dtoList;
	}

	private Set<JaminanDto> setJaminan(List<AsuransiPasien> listAsuransiPasien) {
		Set<JaminanDto> dtoList = new HashSet<>();
		listAsuransiPasien.forEach(asuransi -> {
			JaminanDto.JaminanDtoBuilder dtoBuilder = JaminanDto.builder();
			if (CommonUtil.isNotNullOrEmpty(asuransi.getNoAsuransi()) && !"-".equals(asuransi.getNoAsuransi())) {
				dtoBuilder.nomorKartu(asuransi.getNoAsuransi());
				if (CommonUtil.isNotNullOrEmpty(asuransi.getRekanan())
						&& CommonUtil.isNotNullOrEmpty(asuransi.getRekanan().getNamaRekanan()))
					dtoBuilder.asuransi(AsuransiDto.builder().asuransi(asuransi.getRekanan().getNamaRekanan()).build());
				dtoList.add(dtoBuilder.build());
			}
		});
		return dtoList;
	}

	private String numbersOnly(String str) {
		return str.replaceAll("\\D", "");
	}

	@Override
	public void setStatus(List<String> noRekamMedisList) {
		List<String> statusMigrasiList = new ArrayList<>(Arrays.asList(BELUM_KIRIM, PEMBAHARUAN)).stream()
				.map(Enum::toString).collect(Collectors.toList());
		List<MigrasiPasien> listMigrasiPasien = migrasiPasienDao.findByStatusMigrasiInAndPasienNoCmIn(statusMigrasiList,
				noRekamMedisList);
		listMigrasiPasien.forEach(migrasiPasien -> migrasiPasien.setStatusMigrasi(TERKIRIM));
		migrasiPasienDao.save(listMigrasiPasien);
	}
}
