package com.jasamedika.medifirst2000.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
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.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
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.converter.PegawaiConverter;
import com.jasamedika.medifirst2000.dao.OrderPelayananDao;
import com.jasamedika.medifirst2000.dao.OrderPemakaianRuangRapatService;
import com.jasamedika.medifirst2000.dao.ProdukDao;
import com.jasamedika.medifirst2000.dao.RuanganDao;
import com.jasamedika.medifirst2000.dao.RunningNumberDao;
import com.jasamedika.medifirst2000.dao.StrukOrderDao;
import com.jasamedika.medifirst2000.entities.JenisKonsumsi;
import com.jasamedika.medifirst2000.entities.JenisKonsumsiSet;
import com.jasamedika.medifirst2000.entities.OrderPelayanan;
import com.jasamedika.medifirst2000.entities.Pegawai;
import com.jasamedika.medifirst2000.entities.PenambahanKebutuhanSarana;
import com.jasamedika.medifirst2000.entities.Produk;
import com.jasamedika.medifirst2000.entities.Ruangan;
import com.jasamedika.medifirst2000.entities.RunningNumber;
import com.jasamedika.medifirst2000.entities.StrukOrder;
import com.jasamedika.medifirst2000.enums.Status;
import com.jasamedika.medifirst2000.exception.ServiceVOException;
import com.jasamedika.medifirst2000.service.LoginUserService;
import com.jasamedika.medifirst2000.util.CommonUtil;
import com.jasamedika.medifirst2000.util.DateUtil;
import com.jasamedika.medifirst2000.util.StringUtil;
import com.jasamedika.medifirst2000.vo.JenisKonsumsiSetVO;
import com.jasamedika.medifirst2000.vo.JenisKonsumsiVO;
import com.jasamedika.medifirst2000.vo.OrderPelayananVO;
import com.jasamedika.medifirst2000.vo.OrderPemakaianRuangRapatVO;
import com.jasamedika.medifirst2000.vo.PegawaiVO;
import com.jasamedika.medifirst2000.vo.PenambahanKebutuhanSaranaVO;
import com.jasamedika.medifirst2000.vo.ProdukVO;
import com.jasamedika.medifirst2000.vo.RuanganVO;
import com.jasamedika.medifirst2000.vo.StrukOrderVO;

@Service("orderPemakaianRuangRapatService")
public class OrderPemakaianRuangRapatServiceImpl extends BaseVoServiceImpl implements OrderPemakaianRuangRapatService {

	@Autowired
	private StrukOrderDao strukOrderDao;

	@Autowired
	private RuanganDao ruanganDao;

	@Autowired
	private ProdukDao produkDao;

	@Autowired
	private RunningNumberDao runningNumberDao;

	@Autowired
	private OrderPelayananDao orderPelayananDao;

	@Autowired
	private BaseConverterImpl<StrukOrderVO, StrukOrder> strukOrderConverter;

	@Autowired
	private BaseConverterImpl<OrderPelayananVO, OrderPelayanan> orderPelayananConverter;

	@Autowired
	private BaseConverterImpl<RuanganVO, Ruangan> ruanganConverter;

	@Autowired
	private BaseConverterImpl<JenisKonsumsiSetVO, JenisKonsumsiSet> jenisKonsumsiSetConverter;

	@Autowired
	private BaseConverterImpl<JenisKonsumsiVO, JenisKonsumsi> jenisKonsumsiConverter;

	@Autowired
	private BaseConverterImpl<PenambahanKebutuhanSaranaVO, PenambahanKebutuhanSarana> penambahanKebutuhanSaranaConverter;

	@Autowired
	private BaseConverterImpl<ProdukVO, Produk> produkConverter;

	@Autowired
	private LoginUserService loginUserService;
	
	@Autowired
	private BaseConverterImpl<PegawaiVO, Pegawai> pegawaiConverter;

	@Transactional(readOnly = false)
	private String getRunningNumber(String kegunaan) {

		RunningNumber runningNumber = runningNumberDao.findByResetAndKegunaan("0", kegunaan);
		Integer number = (runningNumber.getNomerTerbaru() + (Integer) 1);
		runningNumber.setNomerTerbaru(runningNumber.getNomerTerbaru() + (Integer) 1);
		String noOrderIntern = StringUtil.formatNumber(number.toString(), 6);
		runningNumberDao.save(runningNumber);
		return noOrderIntern;
	}

	@Override
	public Map<String, Object> saveOrderPemakaianRuangRapat(OrderPemakaianRuangRapatVO vo)
			throws JpaSystemException, ServiceVOException {

		Map<String, Object> result = new HashMap<String, Object>();

		try {
			System.out.println("==================START SAVE ORDER PEMAKAIAN RUANG RAPAT======================");
			if (CommonUtil.isNotNullOrEmpty(vo.getNoRecStrukOrder())){
				StrukOrder strukOrder = this.strukOrderDao.findByNoRec(vo.getNoRecStrukOrder());
				strukOrder.setStatusEnabled(vo.getStatusEnabled());
				strukOrder.setTglPelayananAwal(vo.getStrukOrder().getTglPelayananAwal());
				strukOrder.setTglPelayananAkhir(vo.getStrukOrder().getTglPelayananAkhir());
				
				StrukOrder strukOrderResult = null;
				strukOrderResult = this.strukOrderDao.save(strukOrder);
				if(CommonUtil.isNotNullOrEmpty(strukOrderResult)){
					result.put("noRec", strukOrderResult.getNoRec());
				}
				
				OrderPelayanan orderPelayanan = this.orderPelayananDao.findByNoRecStrukOrder(vo.getNoRecStrukOrder());
				orderPelayanan.setRuanganTujuan(ruanganConverter
						.transferVOToModel(vo.getOrderPelayanan().getRuanganTujuan(), new Ruangan()));
				OrderPelayanan orderPelayananResult = null;
				orderPelayananResult = this.orderPelayananDao.save(orderPelayanan);
				if(CommonUtil.isNotNullOrEmpty(orderPelayananResult)){
					result.put("noRecOrderPelayanan", orderPelayananResult.getNoRec());
				}
				
			}else{
				if (CommonUtil.isNotNullOrEmpty(vo.getStrukOrder())) {
					System.out.println(":::START STRUK ORDER:::");
					StrukOrder strukOrder = strukOrderConverter.transferVOToModel(vo.getStrukOrder(), new StrukOrder());
					// set status
					strukOrder.setStatus(Status.ORDER.getVal());
					// set noOrder
					//strukOrder.setNoOrder(StringUtil
					//		.formatNumber(String.valueOf(strukOrderDao.getCountByMonthAndYear(new Date()) + 1), 10));
					strukOrder.setNoOrder("ORR" + generateNoOrderByDayMonthAndYear(vo));
					strukOrder.setNoOrderIntern("ORR" + generateNoOrderByDayMonthAndYear(vo));
					// get unit pemesan
					if (CommonUtil.isNotNullOrEmpty(vo.getStrukOrder().getUnitPemesan())) {
						strukOrder.setUnitPemesan(
								ruanganConverter.transferVOToModel(vo.getStrukOrder().getUnitPemesan(), new Ruangan()));
					}
					// get jenis konsumsi (makan atau snack)
					List<JenisKonsumsiSet> detailJenisKonsumsi = new ArrayList<JenisKonsumsiSet>();
					for (JenisKonsumsiSetVO jenisKonsumsiSetVO : vo.getStrukOrder().getJenisKonsumsiSet()) {
						if (CommonUtil.isNotNullOrEmpty(jenisKonsumsiSetVO)) {
							JenisKonsumsiSet jenisKonsumsiSet = jenisKonsumsiSetConverter
									.transferVOToModel(jenisKonsumsiSetVO, new JenisKonsumsiSet());
							jenisKonsumsiSet.setJenisKonsumsi(jenisKonsumsiConverter
									.transferVOToModel(jenisKonsumsiSetVO.getJenisKonsumsi(), new JenisKonsumsi()));
							jenisKonsumsiSet.setStrukOrder(strukOrder);
							detailJenisKonsumsi.add(jenisKonsumsiSet);
						}
					}
					strukOrder.getJenisKonsumsiSet().clear();
					strukOrder.getJenisKonsumsiSet().addAll(detailJenisKonsumsi);
					// input penambahan kebutuhan sarana
					List<PenambahanKebutuhanSarana> detailPenambahanKebutuhanSarana = new ArrayList<PenambahanKebutuhanSarana>();
					for (PenambahanKebutuhanSaranaVO penambahanKebutuhanSaranaVO : vo.getStrukOrder()
							.getPenambahanKebutuhanSarana()) {
						if (CommonUtil.isNotNullOrEmpty(penambahanKebutuhanSaranaVO)) {
							PenambahanKebutuhanSarana penambahanKebutuhanSarana = penambahanKebutuhanSaranaConverter
									.transferVOToModel(penambahanKebutuhanSaranaVO, new PenambahanKebutuhanSarana());
							penambahanKebutuhanSarana.setStrukOrder(strukOrder);
							detailPenambahanKebutuhanSarana.add(penambahanKebutuhanSarana);
						}
					}
					strukOrder.getPenambahanKebutuhanSarana().clear();
					strukOrder.getPenambahanKebutuhanSarana().addAll(detailPenambahanKebutuhanSarana);
					strukOrder.setTglOrder(DateUtil.getShortDate());
					strukOrder.setQtyJenisProduk(1.0);
					strukOrder.setQtyProduk(1.0);
					strukOrder.setTotalBeaMaterai(0.0);
					strukOrder.setTotalBiayaKirim(0.0);
					strukOrder.setTotalBiayaTambahan(0.0);
					strukOrder.setTotalDiscount(0.0);
					strukOrder.setTotalHarusDibayar(0.0);
					strukOrder.setTotalPph(0.0);
					strukOrder.setTotalPpn(0.0);
					strukOrder.setTotalHargaSatuan(0.0);
					strukOrder.setPegawaiOrder(loginUserService.getLoginUser().getPegawai());
					strukOrder.setPetugas(pegawaiConverter.transferVOToModel(vo.getStrukOrder().getPetugas(), new Pegawai()));
					strukOrder.setIsDelivered((byte) 1);
					strukOrder.setKeteranganOrder("Order Ruang Rapat");
					//strukOrder.setStatusEnabled(true);
					strukOrder.setStatusEnabled(vo.getStatusEnabled());
					StrukOrder resultModelStrukOrder = strukOrderDao.save(strukOrder);
					result.put("noRecStrukOrder", resultModelStrukOrder.getNoRec());
					System.out.println(":::END STRUK ORDER:::");
					if (CommonUtil.isNotNullOrEmpty(vo.getOrderPelayanan())) {
						System.out.println(":::START ORDER PELAYANAN:::");
						OrderPelayanan orderPelayanan = orderPelayananConverter.transferVOToModel(vo.getOrderPelayanan(),
								new OrderPelayanan());
						orderPelayanan.setStrukOrder(strukOrder);// set strukorderfk
						orderPelayanan.setNoOrder(strukOrder);// set noOrderfk
						orderPelayanan.setIsCito((byte) 1);
						orderPelayanan.setQtyProduk(1.0);
						orderPelayanan.setQtyProdukRetur(1.0);
						orderPelayanan.setTglPelayanan(strukOrder.getTglOrder());
						orderPelayanan.setRuangan(
								ruanganConverter.transferVOToModel(vo.getOrderPelayanan().getRuangan(), new Ruangan()));
						orderPelayanan.setRuanganTujuan(ruanganConverter
								.transferVOToModel(vo.getOrderPelayanan().getRuanganTujuan(), new Ruangan()));
						orderPelayanan.setRuanganTujuan(
								ruanganDao.findById(Integer.parseInt((String) this.GetSettingDataFixed("KdRuanganRapat"))));
						if (CommonUtil.isNotNullOrEmpty(vo.getOrderPelayanan().getProduk())) {
							orderPelayanan.setProduk(
									produkConverter.transferVOToModel(vo.getOrderPelayanan().getProduk(), new Produk()));
							orderPelayanan.setProduk(produkDao
									.findById(Integer.parseInt((String) this.GetSettingDataFixed("KdProdukRuangRapat"))));
							orderPelayanan.getProduk().setNilaiNormal((short) 1);
							orderPelayanan.getProduk().setqProduk(1);
							orderPelayanan.getProduk().setQtyJualTerkecil(1.0);
							orderPelayanan.getProduk().setQtySatuKemasan(1);
							orderPelayanan.getProduk().setQtyTerkecil(1.0);
						}
						OrderPelayanan resultModelOrderPelayanan = orderPelayananDao.save(orderPelayanan);
						result.put("noRecOrderPelayanan", resultModelOrderPelayanan.getNoRec());
						System.out.println(":::END ORDER PELAYANAN:::");
					}
				}
			}
			
			System.out.println("==================END SAVE ORDER PEMAKAIAN RUANG RAPAT======================");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;

	}

	@Override
	public Map<String, Object> findByNoOrder(String noOrder) {

		Map<String, Object> result = new HashMap<String, Object>();
		try {
			System.out.println("============START SEARCH ORDER PEMAKAIAN RUANG RAPAT BY NO ORDER============");
			StrukOrder resultModel = strukOrderDao.findByNoOrder(noOrder);
			if (CommonUtil.isNotNullOrEmpty(resultModel)) {
				result.put("data", resultModel);
				result.put("RuangRapatByNoOrder", true);
			} else {
				result.put("RuangRapatByNoOrder", false);
			}
			System.out.println("============END SEARCH ORDER PEMAKAIAN RUANG RAPAT BY NO ORDER============");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	@Override
	public String generateNoOrderByDayMonthAndYear(OrderPemakaianRuangRapatVO vo) {

		StrukOrder strukOrder = strukOrderConverter.transferVOToModel(vo.getStrukOrder(), new StrukOrder());

		Date dateNow = strukOrder.getTglPelayananAwal();
		Integer day = getDayFromDate(dateNow);
		Integer month = DateUtil.getMonthFromDate(dateNow);
		Integer year = DateUtil.getYearFromDate(dateNow);
		Integer countByDayMonthAndYear = 0;

		countByDayMonthAndYear = strukOrderDao.getCountByDayMonthAndYear(day, month, year);

		Integer dayNow = getDayFromDate(dateNow);
		Integer monthNow = DateUtil.getMonthFromDate(dateNow);
		Integer yearNow = DateUtil.getYearFromDate(dateNow);
		String dayNowString = dayNow.toString();
		String monthNowString = monthNow.toString();
		String yearNowString = yearNow.toString().substring(2, 4);
		String countString = null;
		countByDayMonthAndYear++;

		if (CommonUtil.isNotNullOrEmpty(countByDayMonthAndYear)) {
			if (countByDayMonthAndYear.toString().length() == 1) {
				countString = "000" + countByDayMonthAndYear.toString();
			} else if (countByDayMonthAndYear.toString().length() == 2) {
				countString = "000" + countByDayMonthAndYear.toString();
			} else if (countByDayMonthAndYear.toString().length() == 3) {
				countString = "000" + countByDayMonthAndYear.toString();
			} else if (countByDayMonthAndYear.toString().length() == 4) {
				countString = "000" + countByDayMonthAndYear.toString();
			} else if (countByDayMonthAndYear.toString().length() == 5) {
				countString = "000" + countByDayMonthAndYear.toString();
			}
		}

		if ((monthNowString.length()) == 1) {
			monthNowString = "0" + monthNow;
		} else if ((monthNowString.length()) == 2) {
			monthNowString = "0" + monthNow;
		} else if ((monthNowString.length()) == 3) {
			monthNowString = "0" + monthNow;
		} else if ((monthNowString.length()) == 4) {
			monthNowString = "0" + monthNow;
		} else if ((monthNowString.length()) == 5) {
			monthNowString = "0" + monthNow;
		}

		return dayNowString + "" + monthNowString + "" + yearNowString + "" + countString;
	}

	private Integer getDayFromDate(Date date) {

		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int day = cal.get(Calendar.DAY_OF_MONTH);
		return day;
	}

	@Override
	public Map<String, Object> findRuangRapat(String namaRuangan) {

		List<Ruangan> model = new ArrayList<Ruangan>();
		Map<String, Object> result = new HashMap<String, Object>();
		try {
			System.out.println("==================START FIND RUANG RAPAT======================");
			model = ruanganDao.findRuangRapat(namaRuangan);
			if (CommonUtil.isNotNullOrEmpty(model)) {
				result.put("data", model);
				result.put("RuangRapat", true);
			} else {
				result.put("RuangRapat", false);
			}
			System.out.println("==================END FIND RUANG RAPAT======================");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	@Override
	public Map<String, Object> findStatusRuangRapat(Long periodeAwal, Long periodeAkhir, Integer idRuangan) {

		List<Ruangan> model = new ArrayList<Ruangan>();
		Map<String, Object> result = new HashMap<String, Object>();
		try {
			System.out.println("==========START FIND STATUS RUANG RAPAT==========");
			Date dtAwal = new Date(periodeAwal);
			Date dtAkhir = new Date(periodeAkhir);
			model = ruanganDao.findStatusRuangRapat(dtAwal, dtAkhir, idRuangan);
			if (CommonUtil.isNotNullOrEmpty(model)) {
				result.put("data", model);
				result.put("StatusRuangRapat", true);
			} else {
				result.put("StatusRuangRapat", false);
			}
			System.out.println("==========END FIND STATUS RUANG RAPAT==========");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	@Override
	public Map<String, Object> ruangRapatPaging(Integer page, Integer limit, String sort, String dir,
			Specification<StrukOrder> spec) {

		Map<String, Object> result = new HashMap<String, Object>();
		try {
			System.out.println("=======START FIND STATUS RUANG RAPAT=======");
			Direction direction = null;

			if (sort.equalsIgnoreCase("asc")) {
				direction = Sort.Direction.ASC;
			} else {
				direction = Sort.Direction.DESC;
			}

			Pageable pageable = new PageRequest(page, limit, direction, sort);
			Page<StrukOrder> resultPage = strukOrderDao.findAll(spec, pageable);
			List<StrukOrder> penilaianList = resultPage.getContent();
			if (CommonUtil.isNotNullOrEmpty(penilaianList)) {
				result.put("data", penilaianList);
				result.put("dataFound", true);
			} else {
				result.put("dataFound", false);
			}
			System.out.println("=======END FIND STATUS RUANG RAPAT=======");
			return constructMapReturn(penilaianList, resultPage.getTotalElements(), resultPage.getTotalPages());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

}