package com.eksad.masterdata.service;

import com.eksad.ddms.common.util.DateUtil;
import com.eksad.ddms.common.util.StringUtil;
import com.eksad.masterdata.common.dto.UnpaidDPHLOPullParamDTO;
import com.eksad.masterdata.common.dto.responseDto.UnpaidDPHLOPullHeaderResponseDTO;
import com.eksad.masterdata.common.dto.responseDto.UnpaidDPHLOPullPartResponseDTO;
import com.eksad.masterdata.common.dto.responseDto.UnpaidDPHLOPullResponseDTO;
import com.eksad.masterdata.domain.UnpaidHLODetail;
import com.eksad.masterdata.domain.UnpaidHLOHeader;
import com.eksad.masterdata.repository.UnpaidHLORepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author eksad
 */
@Service
public class UnpaidHLOHystrixService {

    @Autowired
    UnpaidHLORepository unpaidHLORepository;

    public ResponseEntity<Object> getUnpaidHLO(UnpaidDPHLOPullParamDTO dto) {
        try {
            List<UnpaidDPHLOPullResponseDTO> listResponse = new ArrayList<>();
            if (!StringUtil.hasValue(dto.getDealerId())) {
//                return ResponseEntity.ok(new ResponsePullNJBNSCGetListDTO(0, "Mohon isi dealerId.", null));
            }
            if (StringUtil.hasValue(dto.getFromTime())) {
                if (!StringUtil.hasValue(dto.getToTime())) {
                    dto.setToTime(getCurrentDate());
                }
                if (!checkToTimeIs7Days(dto.getFromTime(), dto.getToTime())) {
                    return ResponseEntity.status(HttpStatus.ACCEPTED).body(new UnpaidDPHLOPullHeaderResponseDTO("0", "Range waktu melebihi 7 hari.", null));
                }
            } else {
                return ResponseEntity.status(HttpStatus.ACCEPTED).body(new UnpaidDPHLOPullHeaderResponseDTO("0", "Mohon isi Range Waktu mulai.", null));
            }
            UnpaidDPHLOPullResponseDTO res = null;
            if (StringUtil.hasValue(dto.getIdHLODocument())) {
                List<UnpaidHLOHeader> listHeader;
                List<UnpaidHLODetail> listDetail;
                if (StringUtil.hasValue(dto.getNoWorkOrder())) {
                    listHeader = unpaidHLORepository.getUnpaidHloByPoNumber(dto.getIdHLODocument(), dto.getNoWorkOrder());
                    listDetail = unpaidHLORepository.getDetailUnpaidHloByPoNumber(dto.getIdHLODocument(), dto.getNoWorkOrder());
                } else {
                    listHeader = unpaidHLORepository.getUnpaidHloByPoNumber(dto.getIdHLODocument(), null);
                    listDetail = unpaidHLORepository.getDetailUnpaidHloByPoNumber(dto.getIdHLODocument(), null);
                }

                if (listHeader != null && !listHeader.isEmpty()) {
                    res = populateResponseUnpaidHLO(listHeader.get(0), listDetail);
                    listResponse.add(res);
                }
            } else if (StringUtil.hasValue(dto.getNoWorkOrder())) {
                List<UnpaidHLOHeader> listHeader = unpaidHLORepository.getUnpaidHloBySoNumber(dto.getNoWorkOrder());
                List<UnpaidHLODetail> listDetail = unpaidHLORepository.getDetailUnpaidHloBySoNumber(dto.getNoWorkOrder());

                if (listHeader != null && !listHeader.isEmpty()) {
                    for (UnpaidHLOHeader head : listHeader) {
                        res = populateResponseUnpaidHLO(head, listDetail);
                        listResponse.add(res);
                    }
                }
            } else {
                List<UnpaidHLOHeader> listHeader = new ArrayList<>();
                List<UnpaidHLODetail> listDetail = new ArrayList<>();
                if (StringUtil.hasValue(dto.getDealerId())) {
                    listHeader = unpaidHLORepository.getListUnpaidHloByRangeDate(dto.getFromTime(), dto.getToTime(), dto.getDealerId());
                    listDetail = unpaidHLORepository.getDetailListUnpaidHloByRangeDate(dto.getFromTime(), dto.getToTime(), dto.getDealerId());
                } else {
                    listHeader = unpaidHLORepository.getListUnpaidHloByRangeDate(dto.getFromTime(), dto.getToTime(), null);
                    listDetail = unpaidHLORepository.getDetailListUnpaidHloByRangeDate(dto.getFromTime(), dto.getToTime(), null);
                }
                if (listHeader != null && !listHeader.isEmpty()) {
                    for (UnpaidHLOHeader head : listHeader) {
                        res = populateResponseUnpaidHLO(head, listDetail);
                        listResponse.add(res);
                    }
                }
            }
            if (res == null) {
                return ResponseEntity.status(HttpStatus.ACCEPTED).body(new UnpaidDPHLOPullHeaderResponseDTO("0", "Terdapat kesalahan, Data Tidak Dapat Ditemukan", null));
            }

            return ResponseEntity.status(HttpStatus.OK).body(new UnpaidDPHLOPullHeaderResponseDTO("1", null, listResponse));

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.ACCEPTED).body(new UnpaidDPHLOPullHeaderResponseDTO("0", "Terjadi kesalahan. " + e.getLocalizedMessage(), null));
        }
    }

    public static String getCurrentDate() throws ParseException {
        final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(new Date());
    }

    private Boolean checkToTimeIs7Days(String fromTime, String toTime) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date from = dateFormat.parse(fromTime);
        Date to = dateFormat.parse(toTime);
        LocalDateTime fromLocal = from.toInstant().atZone(ZoneId.of("Asia/Jakarta")).toLocalDateTime();
        LocalDateTime toLocal = to.toInstant().atZone(ZoneId.of("Asia/Jakarta")).toLocalDateTime();
        Duration durasi = Duration.between(fromLocal, toLocal);
        long dayDifference = Math.abs(durasi.toHours());
        if (dayDifference > (7 * 24) + 1) {  // if duration greater than 24*7 + 1 hours
            return false;
        }
        return true;
    }

    private UnpaidDPHLOPullResponseDTO populateResponseUnpaidHLO(UnpaidHLOHeader head, List<UnpaidHLODetail> listDetail) {
        UnpaidDPHLOPullResponseDTO res = new UnpaidDPHLOPullResponseDTO();
        res.setIdHLODocument(head.getIdHLODocument());
        res.setTanggalPemesananHLO(head.getTanggalPemesananHLO() == null ? "" : DateUtil.dateToString(head.getTanggalPemesananHLO(), "dd/MM/yyyy"));
        res.setNoWorkOrder(head.getNoWorkOrder());
        res.setNoBukuClaimC2(head.getNoBukuClaimC2() == null ? "" : head.getNoBukuClaimC2().toUpperCase());
        res.setNoKTP(head.getNoKTP() == null ? "" : head.getNoKTP());
        res.setNamaCustomer(head.getNamaCustomer() == null ? "" : head.getNamaCustomer().toUpperCase());
        res.setAlamat(head.getAlamat() == null ? "" : head.getAlamat().toUpperCase());
        res.setKodePropinsi(head.getKodePropinsi() == null ? "" : head.getKodePropinsi());
        res.setKodeKota(head.getKodeKota() == null ? "" : head.getKodeKota());
        res.setKodeKecamatan(head.getKodeKecamatan() == null ? "" : head.getKodeKecamatan());
        res.setKodeKelurahan(head.getKodeKelurahan() == null ? "" : head.getKodeKelurahan());
        res.setKodePos(head.getKodePos() == null ? "" : head.getKodePos());
        res.setNoKontak(head.getNoKontak() == null ? "" : head.getNoKontak());
        res.setKodeTipeUnit(head.getKodeTipeUnit());
        res.setTahunMotor(head.getTahunMotor() == null ? "" : head.getTahunMotor());
        res.setNoMesin(head.getNoMesin() == null ? "" : head.getNoMesin().replaceAll(" ", "").toUpperCase());
        res.setNoRangka(head.getNoRangka() == null ? "" : head.getNoRangka().toUpperCase());
        res.setFlagNumbering(head.getFlagNumbering() == null ? "" : head.getFlagNumbering());
        res.setVehicleOffRoad(head.getVehicleOffRoad() == null ? "" : head.getVehicleOffRoad().equalsIgnoreCase("Y") ? "1" : "0");
        res.setJobReturn(head.getJobReturn() == null ? "" : head.getJobReturn().equalsIgnoreCase("Y") ? "1" : "0");
        res.setDealerId(head.getDealerId());
        res.setCreatedTime(head.getCreatedTime());
        res.setModifiedTime(head.getModifiedTime());
        populateResponseDetail(res, head, listDetail);
        return res;
    }

    private void populateResponseDetail(UnpaidDPHLOPullResponseDTO res, UnpaidHLOHeader head, List<UnpaidHLODetail> listDetail) {
        List<UnpaidDPHLOPullPartResponseDTO> details = new ArrayList<>();
        listDetail.stream().filter(p -> Objects.equals(p.getPoDealerID(), head.getPoDealerID())).forEach(par -> {
            UnpaidDPHLOPullPartResponseDTO detail = new UnpaidDPHLOPullPartResponseDTO();
            detail.setPartsNumber(par.getPartsNumber());
            detail.setKuantitas(par.getKuantitas());
            detail.setHargaParts(par.getHargaParts());
            detail.setTotalHargaParts(par.getTotalHargaParts());
            detail.setUangMuka(par.getUangMuka() == null ? 0 : getRoundingHalfDown(par.getUangMuka()).intValue());
            detail.setSisaBayar(par.getSisaBayar() == null ? 0 : getRoundingHalfDown(par.getSisaBayar()).intValue());
            detail.setCreatedTime(par.getCreatedTime());
            detail.setModifiedTime(par.getModifiedTime());
            details.add(detail);
        });
        res.setParts(details);
    }

    private static Double getRoundingHalfDown(Double num) {
        BigDecimal bd = new BigDecimal(num).setScale(0, RoundingMode.HALF_DOWN);
        return bd.doubleValue();
    }

}