package com.jasamedika.medifirst2000.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

import com.jasamedika.medifirst2000.converter.BaseConverterImpl;
import com.jasamedika.medifirst2000.dao.KelasDao;
import com.jasamedika.medifirst2000.dao.KelompokTransaksiDao;
import com.jasamedika.medifirst2000.dao.LogAccDao;
import com.jasamedika.medifirst2000.dao.PasienDaftarDao;
import com.jasamedika.medifirst2000.dao.PasienDao;
import com.jasamedika.medifirst2000.dao.ProdukDao;
import com.jasamedika.medifirst2000.dao.RuanganDao;
import com.jasamedika.medifirst2000.dao.RunningNumberDao;
import com.jasamedika.medifirst2000.dao.StrukPelayananDao;
import com.jasamedika.medifirst2000.dao.StrukPelayananDetailDao;
import com.jasamedika.medifirst2000.dao.custom.TagihanRekananDaoCustom;
import com.jasamedika.medifirst2000.entities.KelompokTransaksi;
import com.jasamedika.medifirst2000.entities.LogAcc;
import com.jasamedika.medifirst2000.entities.Pasien;
import com.jasamedika.medifirst2000.entities.PasienDaftar;
import com.jasamedika.medifirst2000.entities.Produk;
import com.jasamedika.medifirst2000.entities.Ruangan;
import com.jasamedika.medifirst2000.entities.RunningNumber;
import com.jasamedika.medifirst2000.entities.StrukPelayanan;
import com.jasamedika.medifirst2000.entities.StrukPelayananDetail;
import com.jasamedika.medifirst2000.exception.ServiceVOException;
import com.jasamedika.medifirst2000.service.StrukBuktiPengeluaranService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.StringUtil;
import com.jasamedika.medifirst2000.vo.StrukPengeluaranDetailVO;
import com.jasamedika.medifirst2000.vo.StrukPengeluaranVO;

@Service("StrukBuktiPengeluaranUmumService")
public class StrukBuktiPengeluaranServiceImpl implements StrukBuktiPengeluaranService {
	
	@Autowired
	private StrukPelayananDao strukPelayananDao;
	
	@Autowired
	private PasienDao pasienDao;
	
	@Autowired
	private TagihanRekananDaoCustom daoCustom;
	
	@Autowired
	private PasienDaftarDao pasienDaftarDao;
	
	@Autowired
	private RuanganDao ruanganDao;
	
	@Autowired
	private KelasDao kelasDao;
	
	@Autowired
	private RunningNumberDao runningNumberDao;
	
	@Autowired
	private ProdukDao produkDao;
	
	@Autowired
	private StrukPelayananDetailDao strukPelayananDetailDao;
	
	@Autowired
	private KelompokTransaksiDao kelompokTransaksiDao;
	
	@Autowired
	private LogAccDao logAccDao;
	
	@Autowired
	private BaseConverterImpl<StrukPengeluaranVO, StrukPelayanan> strukPelayananConverter;
	
	@Autowired
	private BaseConverterImpl<StrukPengeluaranDetailVO, StrukPelayananDetail> strukPelayananDetailConverter;
	
	@Override
	public Map<String, Object> ambilPengeluaranUmum(String norec) {
		Map<String, Object> result = new HashMap<>();
//		StrukPelayanan sp = strukPelayananDao.findOneStrukPengeluaran(norec);
//		if (sp != null) {
//			StrukPengeluaranVO vo = strukPelayananConverter.transferModelToVO(sp, new StrukPengeluaranVO());
//			List<StrukPelayananDetail> details = strukPelayananDetailDao.findPengeluaranDetailByNoRecStrukPelayanan(norec);
//			List<StrukPengeluaranDetailVO> vos = new ArrayList<>();
//			vos = strukPelayananDetailConverter.transferListOfModelToListOfVO(details, vos);
//			vo.getStrukPengeluaranDetail().addAll(vos);
//			
//			result.put("strukPengeluaranUmum", vo);
//			return result;
//		} else {
//			result.put("strukPengeluaranUmum", "Data not found");
//		}
		return result;
	}

	@Transactional
	@Override
	public Map<String, Object> simpanPengeluaranUmum(StrukPengeluaranVO vo)
			throws ServiceVOException, JpaSystemException {
		StrukPelayanan strukPelayanan = strukPelayananConverter.transferVOToModel(vo, new StrukPelayanan());
		
		// input data pasien, jika ada NOCM 
		if (!vo.getNocm().getNoCm().isEmpty() || vo.getNocm().getNoCm() != null) {
			List<Pasien> listPasien = pasienDao.findByNoCm(vo.getNocm().getNoCm());
			if (!listPasien.isEmpty()) {
				strukPelayanan.setNocm(listPasien.get(0));
				strukPelayanan.setNamapasien_klien(listPasien.get(0).getNamaPasien());
			}
		} 
		
		// input jika nama pasien tidak kosong (nocm kosong, noregistrasi kosong, kode/nama rekanan kosong)
		if (CommonUtil.isNullOrEmpty(vo.getNocm().getNoCm()) 
				&& CommonUtil.isNullOrEmpty(vo.getNamarekanan()) 
				&& CommonUtil.isNullOrEmpty(vo.getNoregistrasi())) {
			if ((!vo.getNamapasien_klien().isEmpty() || vo.getNamapasien_klien() != null)) {
				strukPelayanan.setNamapasien_klien(vo.getNamapasien_klien());
			}
		}
		
		strukPelayanan.setNostruk(getRunningNumber("StrukPelayanan"));
		
		if (!vo.getNoregistrasi().getNoRegistrasi().isEmpty() || vo.getNoregistrasi().getNoRegistrasi() != null) {
			List<PasienDaftar> listPasienDaftar = pasienDaftarDao.findAll(vo.getNoregistrasi().getNoRegistrasi());
			if (!listPasienDaftar.isEmpty()) {
				strukPelayanan.setNoregistrasi(listPasienDaftar.get(0));
			}
		}
		
		Ruangan ruangan = ruanganDao.findById(vo.getKdruangan().getId());
		if (ruangan != null) {
			strukPelayanan.setKdruangan(ruangan);
		} else {
			throw new ServiceVOException("Ruangan dengan ID: " + vo.getKdruangan().getId() + " tidak ditemukan");
		}
		
		if (!vo.getStrukPengeluaranDetail().isEmpty()) {
			Double lineTotal = Double.parseDouble("0"); // qty * hargasatuan - discount
			Double totalDiscount = Double.parseDouble("0"); // sum of line discount
			Double totalBiaya = vo.getTotalbiayatambahan(); //
			Double hargaSatuan = Double.parseDouble("0");
			Double totalHargaSatuan = Double.parseDouble("0"); // total g  
			Double totalBruto = Double.parseDouble("0"); // total before tax (ppn/pph)
			Double totalTax = Double.parseDouble("0"); // total tax = total before tax * 10%
			Double totalHarusDibayar = Double.parseDouble("0"); // total hargasatuan + biaya - diskon - 10% (jika ppn dihitung maka 10, jika tidak ppn bernilai 0)
			
			Set<StrukPelayananDetail> details = new HashSet<>();
//			if (strukPelayanan.getNoRec() != null || !strukPelayanan.getNoRec().isEmpty()) {
				for (StrukPengeluaranDetailVO detailVo : vo.getStrukPengeluaranDetail()) {
					StrukPelayananDetail detail = strukPelayananDetailConverter.transferVOToModel(detailVo, new StrukPelayananDetail());
					Produk produk = produkDao.findById(detailVo.getKdproduk().getId());
					detail.setKdproduk(produk);
					detail.setNostruk(strukPelayanan);
					
					// calculate total line
					Double discount = Double.parseDouble("0");
					discount = detail.getHargadiscount();
					lineTotal = (detail.getQtyproduk() * detail.getHargasatuan()) - discount;
						
					totalDiscount += discount;
					totalBruto += lineTotal;
					hargaSatuan = detail.getQtyproduk() * detail.getHargasatuan();
					totalHargaSatuan += hargaSatuan;
					
					details.add(detail);
				}
				
				if (!vo.isHitungppn()) {
					totalHarusDibayar = totalHargaSatuan + totalBiaya - totalDiscount; 
				} else {
					totalTax = (totalHargaSatuan + totalBiaya - totalDiscount) * 0.1;
					totalHarusDibayar = totalHargaSatuan + totalBiaya - totalDiscount + totalTax;
				}
				
				// set kelompok transaksi
				KelompokTransaksi kt = kelompokTransaksiDao.findById(vo.getIdKelompokTransaksi());
				if (kt != null) {
					strukPelayanan.setKdkelompoktransaksi(kt);
				} else {
					throw new ServiceVOException("Kelompok Transaksi dengan ID " + vo.getIdKelompokTransaksi() + " tidak valid");
				}
				
				strukPelayanan.setTotaldiscount(totalDiscount);
				strukPelayanan.setTotaldiscount(totalDiscount);
				strukPelayanan.setTotalhargasatuan(totalHargaSatuan);
				strukPelayanan.setTotalbiayatambahan(totalBiaya);
				strukPelayanan.setTotalppn(totalTax);
				strukPelayanan.setTotalharusdibayar(totalHarusDibayar);
				strukPelayanan.setStrukPelayananDetail(details);
				strukPelayananDao.save(strukPelayanan);
				
				// implement pencatatan jurnal (LogAcc) jika data berhasil disimpan
				if(CommonUtil.isNotNullOrEmpty(strukPelayanan.getNoRec())) {
					LogAcc log = new LogAcc();
					log.setTanggal(strukPelayanan.getTglstruk());
					log.setNoReff(strukPelayanan.getNoRec());
					log.setJenisTransaksi("save struk bukti pengeluaran");
					if(CommonUtil.isNotNullOrEmpty(log)) {
						logAccDao.save(log);
					}
				}
				
//			} else {
//				throw new ServiceVOException("Gagal simpan StrukPelayanan: " + strukPelayanan.getNostruk());
//			}
		} else {
			throw new ServiceVOException("Daftar Detail Pengeluaran tidak boleh kosong");
		}
		
		Map<String, Object> result = new HashMap<>();
		if (!strukPelayanan.getNoRec().isEmpty()) {
			result.put("noRec", strukPelayanan.getNoRec());
		}
		return result;
	}
	
	private String getRunningNumber(String kegunaan) {
		RunningNumber runningNumber = runningNumberDao.findByResetAndKegunaan("0", kegunaan);
		if (runningNumber == null) {
			runningNumber = new RunningNumber();
			runningNumber.setKegunaan(kegunaan);
			runningNumber.setReset("0");
			runningNumber.setNomerTerbaru((Integer) 0);
		}
		Integer number = (runningNumber.getNomerTerbaru() + (Integer) 1);
		runningNumber.setNomerTerbaru(runningNumber.getNomerTerbaru() + (Integer) 1);
		String noOrderIntern = StringUtil.formatNumber(number.toString(), 10);
		return noOrderIntern;
	}

	@Override
	public List<Map<String, Object>> getStrukBuktiPengeluaran(String startDate, String endDate, String ketLain,
			Integer idPegawai, String noSBK, Integer idRuangan) throws ServiceVOException, JpaSystemException {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		result = daoCustom.getStrukBuktiPengeluaran(startDate,endDate, ketLain, idPegawai, noSBK, idRuangan);
		return result;
	}

}
