package cn.estsh.i3plus.ext.mes.apiservice.serviceimpl.busi.bu3;

import cn.estsh.i3plus.ext.mes.api.busi.bu3.ISxProdDataToMonthlyStatisticsDispatchService;
import cn.estsh.i3plus.ext.mes.api.busi.bu3.ISxProdDataToStatisticsTravelService;
import cn.estsh.i3plus.ext.mes.apiservice.dao.IPartExtDao;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesOutPutStatistics;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesProdDataToStatisticsOutPut;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesWorkOrderExt;
import cn.estsh.i3plus.ext.mes.pojo.model.bu3.SxProdDataToAutoStatisticsModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesOutPutStatisticsRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesWorkOrderExtRepository;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtEnumUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SxProdDataToMonthlyStatisticsOutPutService implements ISxProdDataToMonthlyStatisticsDispatchService {

    @Autowired
    private MesOutPutStatisticsRepository outPutStatisticsRepository;

    @Autowired
    private MesWorkOrderExtRepository workOrderExtRepository;

    @Autowired
    private IPartExtDao partExtDao;

    @Autowired
    private ISxProdDataToStatisticsTravelService prodDataToStatisticsTravelService;

    @Override
    public SxProdDataToAutoStatisticsModel restock(SxProdDataToAutoStatisticsModel data) {
        return data.moduleCode("MES_OUT_PUT_STATISTICS").moduleName("产量月度统计").statisticsDate(data.getDate());
    }

    @Override
    public SxProdDataToAutoStatisticsModel doTravel(SxProdDataToAutoStatisticsModel data) {
        return data.pid(prodDataToStatisticsTravelService.doTravel(data.getTravel()).getId().toString());
    }

    public List<MesOutPutStatistics> queryOutPutStatisticsList(SxProdDataToAutoStatisticsModel data) {
        return getOutPutStatisticsList(data);
    }

    public Map<String, Double> queryPartExtStandardWorkMap(String organizeCode) {
        return partExtDao.queryPartExtStandardWorkMap(organizeCode);
    }

    public List<MesWorkOrderExt> queryWorkOrderExtList(SxProdDataToAutoStatisticsModel data) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(data.getOrganizeCode());
        DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.WORK_ORDER_TYPE.STANDARD_ORDER.getValue(), MesExtConstWords.WORK_ORDER_TYPE, packBean);
        DdlPreparedPack.timeBuilder(data.getStartTime() + MesExtConstWords.APPEND_ZERO_HMS, data.getEndTime() + MesExtConstWords.APPEND_ZERO_HMS, MesExtConstWords.START_TIME, true, false, packBean);
        return removeUnValidOrderData(workOrderExtRepository.findByHqlWhere(packBean));
    }

    private List<MesOutPutStatistics> getOutPutStatisticsList(SxProdDataToAutoStatisticsModel data) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(data.getOrganizeCode());
        DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.WORK_ORDER_TYPE.STANDARD_ORDER.getValue(), MesExtConstWords.WORK_ORDER_TYPE, packBean);
        DdlPreparedPack.timeBuilder(data.getStartTime(), data.getEndTime(), MesExtConstWords.WORK_TIME, true, false, packBean);
        return removeUnValidData(outPutStatisticsRepository.findByHqlWhere(packBean));
    }

    private List<MesWorkOrderExt> removeUnValidOrderData(List<MesWorkOrderExt> workOrderExtList) {
        return CollectionUtils.isEmpty(workOrderExtList) ? null :
                workOrderExtList.stream().filter(o -> (null != o &&
                        MesExtEnumUtil.WORK_ORDER_STATUS.CREATE.getValue() != o.getWorkOrderStatus() &&
                        MesExtEnumUtil.WORK_ORDER_STATUS.REMOVE.getValue() != o.getWorkOrderStatus()) &&
                        !StringUtils.isEmpty(o.getReserved1()) && !StringUtils.isEmpty(o.getReserved2())).collect(Collectors.toList());
    }

    private List<MesOutPutStatistics> removeUnValidData(List<MesOutPutStatistics> outPutStatisticsList) {
        return CollectionUtils.isEmpty(outPutStatisticsList) ? null :
                outPutStatisticsList.stream().filter(o -> (null != o &&
                        !StringUtils.isEmpty(o.getWorkCenterCode()) &&
                        !StringUtils.isEmpty(o.getShiftCode()) &&
                        !StringUtils.isEmpty(o.getPartNo()) &&
                        !StringUtils.isEmpty(o.getWorkOrderType()) &&
                        !StringUtils.isEmpty(o.getQty()) &&
                        !StringUtils.isEmpty(o.getCategoryCode()) &&
                        !StringUtils.isEmpty(o.getCareerCode()))).collect(Collectors.toList());
    }

    public Double getQty(List<MesOutPutStatistics> itemList) {
        return CollectionUtils.isEmpty(itemList) ? new Double(0) : itemList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getQty()))).mapToDouble(MesOutPutStatistics::getQty).sum();
    }

    private Double getRemakeQty(List<MesOutPutStatistics> itemList) {
        return CollectionUtils.isEmpty(itemList) ? new Double(0) : itemList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getRemakeQty()))).mapToDouble(MesOutPutStatistics::getRemakeQty).sum();
    }

    public List<String> getKeyList(Map<String, List<MesOutPutStatistics>> outPutDataMap, Map<String, List<MesWorkOrderExt>> orderDataMap) {
        List<String> keyList = null;
        if (!CollectionUtils.isEmpty(outPutDataMap) || !CollectionUtils.isEmpty(orderDataMap)) keyList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(outPutDataMap)) keyList.addAll(new ArrayList<>(outPutDataMap.keySet()));
        if (!CollectionUtils.isEmpty(orderDataMap)) keyList.addAll(new ArrayList<>(orderDataMap.keySet()));
        keyList = CollectionUtils.isEmpty(keyList) ? null : keyList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        return keyList;
    }

    public MesProdDataToStatisticsOutPut packItemData(SxProdDataToAutoStatisticsModel data, List<MesOutPutStatistics> itemList, Map<String, Double> partStandardWorkMap) {
        MesProdDataToStatisticsOutPut statistics = new MesProdDataToStatisticsOutPut();
        statistics.setDataKey(data.getDataKey());
        statistics.setDataType(data.getStatisticsType());
        statistics.setStatisticsDate(data.getDate());
        statistics.setPid(data.getPid());
        statistics.setWorkCenterCode(itemList.get(0).getWorkCenterCode());
        statistics.setShiftCode(itemList.get(0).getShiftCode());
        statistics.setPartNo(itemList.get(0).getPartNo());
        statistics.setPartNameRdd(itemList.get(0).getPartNameRdd());
        statistics.setWorkOrderType(itemList.get(0).getWorkOrderType());
        statistics.setCategoryCode(itemList.get(0).getCategoryCode());
        statistics.setCareerCode(itemList.get(0).getCareerCode());
        statistics.setStandardWork((!CollectionUtils.isEmpty(partStandardWorkMap) && partStandardWorkMap.containsKey(statistics.getPartNo())) ? partStandardWorkMap.get(statistics.getPartNo()) : new Double(0));
        statistics.setQty(getQty(itemList));
        statistics.setRemakeQty(getRemakeQty(itemList));
        statistics.setTotalStatistics(MathOperation.mul(statistics.getQty(), statistics.getStandardWork()));
        if (StringUtils.isEmpty(statistics.getRemakeQty()) || MathOperation.compareTo(statistics.getRemakeQty(), new Double(0)) == 0)
            statistics.setStatistics(statistics.getTotalStatistics());
        else
            statistics.setStatistics(MathOperation.mul(MathOperation.sub(statistics.getQty(), statistics.getRemakeQty()), statistics.getStandardWork()));
        statistics.setOrganizeCode(data.getOrganizeCode());
        statistics.setSystemSyncStatus(MesExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelInitialize(statistics, data.getCreateUser());
        return statistics;
    }

    public MesProdDataToStatisticsOutPut packItemData(SxProdDataToAutoStatisticsModel data, String[] keyArr, List<MesWorkOrderExt> workOrderExtList, List<MesOutPutStatistics> outPutStatisticsList) {
        MesProdDataToStatisticsOutPut statistics = new MesProdDataToStatisticsOutPut();
        statistics.setDataKey(data.getDataKey());
        statistics.setDataType(data.getStatisticsType());
        statistics.setStatisticsDate(data.getDate());
        statistics.setPid(data.getPid());
        statistics.setWorkCenterCode(keyArr[0]);
        statistics.setPartNo(keyArr[1]);
        statistics.setPartNameRdd(getPartNameRdd(outPutStatisticsList, workOrderExtList));
        statistics.setWorkOrderType(Integer.valueOf(keyArr[2]));
        statistics.setCategoryCode(keyArr[3]);
        statistics.setCareerCode(keyArr[4]);
        statistics.setQty(getQty(outPutStatisticsList));
        statistics.setRemakeQty(getRemakeQty(outPutStatisticsList));
        calcPlanData(statistics, workOrderExtList, outPutStatisticsList);
        statistics.setTotalStatistics(MathOperation.sub(statistics.getPlanQty(), statistics.getPlanRemakeQty()));
        statistics.setStatistics(MathOperation.sub(statistics.getQty(), statistics.getRemakeQty()));
        statistics.setOrganizeCode(data.getOrganizeCode());
        statistics.setSystemSyncStatus(MesExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelInitialize(statistics, data.getCreateUser());
        return statistics;
    }

    private void calcPlanData(MesProdDataToStatisticsOutPut statistics, List<MesWorkOrderExt> workOrderExtList, List<MesOutPutStatistics> outPutStatisticsList) {
        Double planQty = new Double(0);
        Double planRemakeQty = new Double(0);
        Map<String, List<MesOutPutStatistics>> outPutMap = CollectionUtils.isEmpty(outPutStatisticsList) ? null :
                outPutStatisticsList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesOutPutStatistics::getWorkOrderNo));
        Map<String, MesWorkOrderExt> orderMap = CollectionUtils.isEmpty(workOrderExtList) ? null :
                workOrderExtList.stream().filter(o -> null != o).collect(Collectors.toMap(MesWorkOrderExt::getOrderNo, o -> o));
        List<String> orderNoList = getOrderNoList(orderMap, outPutMap);
        for (String orderNo : orderNoList) {
            if (StringUtils.isEmpty(orderNo)) continue;
            MesWorkOrderExt workOrderExt = CollectionUtils.isEmpty(orderMap) ? null : orderMap.get(orderNo);
            List<MesOutPutStatistics> outPutStatisticListByOrder = CollectionUtils.isEmpty(outPutMap) ? null : outPutMap.get(orderNo);
            if (null != workOrderExt && CollectionUtils.isEmpty(outPutStatisticListByOrder)) {
                planQty = MathOperation.add(planQty, workOrderExt.getQty());
                planRemakeQty = MathOperation.add(planRemakeQty, workOrderExt.getPlanQty());
            } else if (null == workOrderExt && !CollectionUtils.isEmpty(outPutStatisticListByOrder)) {
                for (MesOutPutStatistics item : outPutStatisticListByOrder) {
                    if (null == item) continue;
                    if (getOutPutFlag(item.getOutPutFlag())) {
                        planQty = MathOperation.add(planQty, item.getQty());
                        planRemakeQty = MathOperation.add(planRemakeQty, item.getRemakeQty());
                    }
                }
            } else {
                for (MesOutPutStatistics item : outPutStatisticListByOrder) {
                    if (null == item) continue;
                    if (checkDateByDataType(statistics.getDataType(), workOrderExt.getStartTime(), item.getWorkTime())) {
                        if (getOutPutFlag(item.getOutPutFlag())) {
                            planQty = MathOperation.add(planQty, item.getQty());
                            planRemakeQty = MathOperation.add(planRemakeQty, item.getRemakeQty());
                        } else {
                            planQty = MathOperation.add(planQty, workOrderExt.getQty());
                            planRemakeQty = MathOperation.add(planRemakeQty, workOrderExt.getPlanQty());
                        }
                    } else {
                        if (getOutPutFlag(item.getOutPutFlag())) {
                            planQty = MathOperation.add(planQty, item.getQty());
                            planRemakeQty = MathOperation.add(planRemakeQty, item.getRemakeQty());
                        }
                    }
                }
            }
        }
        statistics.setPlanQty(planQty);
        statistics.setPlanRemakeQty(planRemakeQty);
    }

    private Boolean checkDateByDataType(String dataType, String startTime, String workTime) {
        if (dataType.equals(MesExtConstWords.MONTH)) return startTime.substring(0, 7).equals(workTime.substring(0, 7));
        else return startTime.substring(0, 10).equals(workTime);
    }

    private List<String> getOrderNoList(Map<String, MesWorkOrderExt> orderMap, Map<String, List<MesOutPutStatistics>> outPutMap) {
        List<String> orderNoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(orderMap)) orderNoList.addAll(new ArrayList<>(orderMap.keySet()));
        if (!CollectionUtils.isEmpty(outPutMap)) orderNoList.addAll(new ArrayList<>(outPutMap.keySet()));
        orderNoList = CollectionUtils.isEmpty(orderNoList) ? null : orderNoList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        return orderNoList;
    }

    private Boolean getOutPutFlag(String outPutFlag) {
        return !StringUtils.isEmpty(outPutFlag) && CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr().equals(outPutFlag);
    }

    private String getPartNameRdd(List<MesOutPutStatistics> outPutStatisticsList, List<MesWorkOrderExt> workOrderExtList) {
        if (!CollectionUtils.isEmpty(outPutStatisticsList)) return outPutStatisticsList.get(0).getPartNameRdd();
        return workOrderExtList.get(0).getPartNameRdd();
    }

    public Map<String, Object> getDataMap(Map<String, List<MesOutPutStatistics>> outPutDataMap, Map<String, Double> partStandardWorkMap) {
        Map<String, Object> dataMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(outPutDataMap)) dataMap.put("outPutDataMap", outPutDataMap);
        if (!CollectionUtils.isEmpty(partStandardWorkMap)) dataMap.put("partStandardWorkMap", partStandardWorkMap);
        return dataMap;
    }

    public Map<String, Object> getDataMap(List<String> keyList, Map<String, List<MesOutPutStatistics>> outPutDataMap, Map<String, List<MesWorkOrderExt>> orderDataMap) {
        if (CollectionUtils.isEmpty(keyList)) return null;
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("keyList", keyList);
        if (!CollectionUtils.isEmpty(outPutDataMap)) dataMap.put("outPutDataMap", outPutDataMap);
        if (!CollectionUtils.isEmpty(orderDataMap)) dataMap.put("orderDataMap", orderDataMap);
        return dataMap;
    }
}
