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

import cn.estsh.i3plus.ext.mes.api.busi.jx.IJxCenterWorkingBoardService;
import cn.estsh.i3plus.ext.mes.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pojo.model.jx.JxCenterWorkingBoardBusiModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesOrderJobRepository;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtEnumUtil;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesShift;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.repository.MesShiftRepository;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author : wangjie
 * @CreateDate : 2022-02-15
 * @Modify:
 **/
@Slf4j
public class JxCenterWorkingBoardCenterTwoService extends JxCenterWorkingBoardCommonService implements IJxCenterWorkingBoardService {

    private IJxCenterWorkingBoardService proxyService0;

    private IJxCenterWorkingBoardService proxyService1;

    private IJxCenterWorkingBoardService proxyService;

    private MesShiftRepository shiftRepository;

    private MesOrderJobRepository orderJobRepository;

    public JxCenterWorkingBoardCenterTwoService(IJxCenterWorkingBoardService proxyService0, IJxCenterWorkingBoardService proxyService1, IJxCenterWorkingBoardService proxyService) {
        this.proxyService0 = proxyService0;
        this.proxyService1 = proxyService1;
        this.proxyService = proxyService;
        this.shiftRepository = (MesShiftRepository) SpringContextsUtil.getBean("mesShiftRepository");
        this.orderJobRepository = (MesOrderJobRepository) SpringContextsUtil.getBean("mesOrderJobRepository");
    }

    @Override
    public Map<String, Object> queryCenterWorkingBoardData(Map<String, Object> dataMap) {

        dataMap = proxyService0.queryCenterWorkingBoardData(dataMap);

        dataMap = proxyService1.queryCenterWorkingBoardData(dataMap);

        MesWorkCenterExt workCenterExtDb = (MesWorkCenterExt) dataMap.get(MesWorkCenterExt.class.getSimpleName());

        packProxyCondition(dataMap, workCenterExtDb);

        dataMap = proxyService.queryCenterWorkingBoardData(dataMap);

        List<MesWorkOrder> workOrderList = (List<MesWorkOrder>) dataMap.get(MesWorkOrder.class.getSimpleName());

        List<MesOutPutStatistics> outPutStatisticsList = (List<MesOutPutStatistics>) dataMap.get(MesOutPutStatistics.class.getSimpleName());

        List<MesRepairTask> repairTaskList = (List<MesRepairTask>) dataMap.get(MesRepairTask.class.getSimpleName());

        dataMap.put("当前班次", getShiftName(workCenterExtDb));

        dataMap.put("出勤人数", workCenterExtDb.getWorkerQty());

        dataMap.put("点检作业", getOrderJobStatistics(workCenterExtDb));

        dataMap.put("当日计划台数", getTodayOrderPlanQty(workOrderList, workCenterExtDb, dataMap));

        dataMap.put("当日实绩台数", getWorkTimeQty(outPutStatisticsList, dataMap));

        dataMap.put("当日生产进度", getBigDecimalPercent(divThenMul100Format1RoundHalfUp((Double) dataMap.get(MesExtConstWords.COMPLET_QTY), (Double) dataMap.get(MesExtConstWords.QTY))));

        dataMap.put("当班作业稼动率", getBigDecimalPercent(divThenMul100Format1RoundHalfUp((Double) dataMap.get("workingTime"), (Double) dataMap.get("serviceTime"))));

        dataMap.put("当班作业能率", getBigDecimalPercent(divThenMul100Format1RoundHalfUp((Double) dataMap.get("standardTime"), (Double) dataMap.get("workingTime"))));

        dataMap.put("当前产品直通率", getBigDecimalPercent(getCurProdPassthroughRate(outPutStatisticsList, repairTaskList)));

        dataMap.put("当班产品直通率", getBigDecimalPercent(getShiftProdPassthroughRate(outPutStatisticsList, repairTaskList, workCenterExtDb)));

        dataMap.put("综合能率", getBigDecimalPercent(divThenMul100Format1RoundHalfUp((Double) dataMap.get("standardTime"), (Double) dataMap.get("serviceTime"))));

        dataMap.put("生产计划进度", getProductionSchedule(workOrderList, outPutStatisticsList, workCenterExtDb));

        return clearUselessData(dataMap);
    }

    @Override
    public Map<String, Object> clearUselessData(Map<String, Object> dataMap) {
        dataMap.remove(MesWorkCenterExt.class.getSimpleName());
        dataMap.remove(MesShiftProdCenterRecord.class.getSimpleName());
        dataMap.remove(MesWorkOrder.class.getSimpleName());
        dataMap.remove(MesOutPutStatistics.class.getSimpleName());
        dataMap.remove(MesExtConstWords.QTY);
        dataMap.remove(MesExtConstWords.COMPLET_QTY);
        dataMap.remove(MesExtConstWords.START_TIME);
        dataMap.remove(MesExtConstWords.END_TIME);
        dataMap.remove(MesExtConstWords.WORK_TIME);
        dataMap.remove(MesExtConstWords.SHIFT_CODE);
        dataMap.remove(MesExtConstWords.WORK_CENTER_CODE);
        dataMap.remove(MesExtConstWords.STANDARD_WORK);
        dataMap.remove("serviceTime");
        dataMap.remove("nonWorkingTime");
        dataMap.remove("standardTime");
        dataMap.remove("workingTime");
        dataMap.remove("curTime");
        return dataMap;
    }

    private void packProxyCondition(Map<String, Object> dataMap, MesWorkCenterExt workCenterExtDb) {
        if (StringUtils.isEmpty(workCenterExtDb.getWorkTime()) || StringUtils.isEmpty(workCenterExtDb.getShiftCode())) return;
        dataMap.put(MesExtConstWords.START_TIME, TimeTool.timeCalc(TimeTool.stringParseToDate(workCenterExtDb.getWorkTime(), MesExtConstWords.DATE_FORMAT), Calendar.DATE, -1, MesExtConstWords.DATE_FORMAT));
        dataMap.put(MesExtConstWords.END_TIME, workCenterExtDb.getWorkTime());
        dataMap.put(MesExtConstWords.WORK_TIME, workCenterExtDb.getWorkTime());
        dataMap.put(MesExtConstWords.SHIFT_CODE, workCenterExtDb.getShiftCode());
        dataMap.put(MesExtConstWords.WORK_CENTER_CODE, workCenterExtDb.getWorkCenterCode());
        dataMap.put("curTime", TimeTool.getNowTime(true));
    }

    private String getShiftName(MesWorkCenterExt workCenterExtDb) {
        if (StringUtils.isEmpty(workCenterExtDb.getShiftCode())) return MesExtConstWords.EMPTY;
        String item = new StringJoiner(MesExtConstWords.AND).add("SHIFT").add(workCenterExtDb.getWorkCenterCode()).add(workCenterExtDb.getShiftCode()).toString();
        String shift4Cached = (String) execCachedCenterWorkingBoardData(workCenterExtDb.getOrganizeCode(), MesExtConstWords.ZERO_STR, item, null);
        MesShift shift = !StringUtils.isEmpty(shift4Cached) ? JSONObject.parseObject(shift4Cached, MesShift.class) : execShift(workCenterExtDb, item);
        return null == shift ? MesExtConstWords.EMPTY : shift.getShiftName();
    }

    private MesShift execShift(MesWorkCenterExt workCenterExtDb, String item) {
        MesShift shiftDb = shiftRepository.getByProperty(
                new String[]{MesExtConstWords.ORGANIZE_CODE, MesExtConstWords.IS_DELETED, MesExtConstWords.IS_VALID, MesExtConstWords.WORK_CENTER_CODE, MesExtConstWords.SHIFT_CODE},
                new Object[]{workCenterExtDb.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workCenterExtDb.getWorkCenterCode(), workCenterExtDb.getShiftCode()});
        if (null != shiftDb) execCachedCenterWorkingBoardData(workCenterExtDb.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr(), item, JSONObject.toJSONString(shiftDb));
        return shiftDb;
    }

    private String getOrderJobStatistics(MesWorkCenterExt workCenterExtDb) {
        List<MesOrderJob> orderJobList = (StringUtils.isEmpty(workCenterExtDb.getWorkTime()) || StringUtils.isEmpty(workCenterExtDb.getShiftCode())) ? null :
                orderJobRepository.findByProperty(
                        new String[]{MesExtConstWords.ORGANIZE_CODE, MesExtConstWords.IS_DELETED, MesExtConstWords.IS_VALID, MesExtConstWords.WORK_CENTER_CODE, MesExtConstWords.WORK_TIME, MesExtConstWords.SHIFT_CODE},
                        new Object[]{workCenterExtDb.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workCenterExtDb.getWorkCenterCode(), workCenterExtDb.getWorkTime(), workCenterExtDb.getShiftCode()});
        orderJobList = CollectionUtils.isEmpty(orderJobList)? null :
                orderJobList.stream().filter(o -> (null != o && MesExtEnumUtil.MES_ORJ_ORDER_STATUS.CLOSE.getValue() != o.getOrderStatus())).collect(Collectors.toList());
        List<MesOrderJob> orderJobList4Complete = CollectionUtils.isEmpty(orderJobList)? null :
                orderJobList.stream().filter(o -> (null != o && MesExtEnumUtil.MES_ORJ_ORDER_STATUS.CHECK_COMPLETE.getValue() == o.getOrderStatus())).collect(Collectors.toList());
        return new StringJoiner(MesExtConstWords.SINGLE_SLASH).add(getListSizeStr(orderJobList4Complete)).add(getListSizeStr(orderJobList)).toString();
    }

    private String getTodayOrderPlanQty(List<MesWorkOrder> workOrderList, MesWorkCenterExt workCenterExtDb, Map<String, Object> dataMap) {
        Double qty = CollectionUtils.isEmpty(workOrderList) ? new Double(0) : workOrderList.stream().filter(o -> (null != o && o.getStartTime().contains(workCenterExtDb.getWorkTime()))).mapToDouble(MesWorkOrder::getQty).sum();
        dataMap.put(MesExtConstWords.QTY, qty);
        return getQtyStr(qty);
    }

    private String getWorkTimeQty(List<MesOutPutStatistics> outPutStatisticsList, Map<String, Object> dataMap) {
        Double completeQty = getOutPutStatisticsList2AmountQty(outPutStatisticsList);
        dataMap.put(MesExtConstWords.COMPLET_QTY, completeQty);
        return getQtyStr(completeQty);
    }

    private BigDecimal getCurProdPassthroughRate(List<MesOutPutStatistics> outPutStatisticsList, List<MesRepairTask> repairTaskList) {
        if (CollectionUtils.isEmpty(outPutStatisticsList)) return new BigDecimal(0);
        List<MesOutPutStatistics> filterList = outPutStatisticsList.stream().filter(o -> (null != o && o.getWorkOrderNo().equals(outPutStatisticsList.get(0).getWorkOrderNo()))).collect(Collectors.toList());
        Double repairQty = CollectionUtils.isEmpty(repairTaskList) ? new Double(0) : getListSizeD(repairTaskList.stream().filter(o -> (null != o && o.getWorkOrderNo().equals(outPutStatisticsList.get(0).getWorkOrderNo()))).collect(Collectors.toList()));
        Double qty = getOutPutStatisticsList2AmountQty(filterList);
        return divThenMul100Format1RoundHalfUp(qty, MathOperation.add(qty, repairQty));
    }

    private BigDecimal getShiftProdPassthroughRate(List<MesOutPutStatistics> outPutStatisticsList, List<MesRepairTask> repairTaskList, MesWorkCenterExt workCenterExtDb) {
        List<MesOutPutStatistics> filterList = CollectionUtils.isEmpty(outPutStatisticsList) ? null : outPutStatisticsList.stream().filter(o -> (null != o && o.getShiftCode().equals(workCenterExtDb.getShiftCode()))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(filterList)) return new BigDecimal(0);
        Double repairQty = CollectionUtils.isEmpty(repairTaskList) ? new Double(0) : getListSizeD(repairTaskList.stream().filter(o -> (null != o && o.getShiftCode().equals(workCenterExtDb.getShiftCode()))).collect(Collectors.toList()));
        Double qty = getOutPutStatisticsList2AmountQty(filterList);
        return divThenMul100Format1RoundHalfUp(qty, MathOperation.add(qty, repairQty));
    }

    private JxCenterWorkingBoardBusiModel getProductionSchedule(List<MesWorkOrder> workOrderList, List<MesOutPutStatistics> outPutStatisticsList, MesWorkCenterExt workCenterExtDb) {

        JxCenterWorkingBoardBusiModel psData = new JxCenterWorkingBoardBusiModel().title("生产计划进度");

        List<MesWorkOrder> workOrderList2Sort = getWorkOrderList2Sort(workOrderList, outPutStatisticsList, workCenterExtDb);

        Set<String> partNoList = new TreeSet<>();
        if (!CollectionUtils.isEmpty(outPutStatisticsList)) partNoList.add(outPutStatisticsList.get(0).getPartNo());
        if (!CollectionUtils.isEmpty(workOrderList2Sort)) workOrderList2Sort.stream().filter(o -> null != o).forEach(o -> partNoList.add(o.getPartNo()));
        if (!CollectionUtils.isEmpty(outPutStatisticsList)) outPutStatisticsList.stream().filter(o -> null != o).forEach(o -> partNoList.add(o.getPartNo()));
        if (CollectionUtils.isEmpty(partNoList)) return psData;

        Map<String, List<MesWorkOrder>> orderMap = CollectionUtils.isEmpty(workOrderList2Sort) ? null : workOrderList2Sort.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesWorkOrder::getPartNo));
        Map<String, List<MesOutPutStatistics>> outPutMap = CollectionUtils.isEmpty(outPutStatisticsList) ? null : outPutStatisticsList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesOutPutStatistics::getPartNo));

        for (String partNo : partNoList) {
            if (StringUtils.isEmpty(partNo)) continue;

            List<MesWorkOrder> orderList = CollectionUtils.isEmpty(orderMap) ? null : orderMap.get(partNo);
            List<MesOutPutStatistics> outPutList = CollectionUtils.isEmpty(outPutMap) ? null : outPutMap.get(partNo);

            Map<String, List<MesOutPutStatistics>> itemMap2OutPut = getOutPutStatisticsMapByOrderNo(outPutList);

            psData.addChartData2ChartDataLists(5, partNo, statisticsPlanQty(orderList, itemMap2OutPut, workCenterExtDb), getOutPutStatisticsList2AmountQty(outPutList), !CollectionUtils.isEmpty(psData.getChartDataList()) ? "#ffffff" : "#00ff00");

        }

        return psData;

    }

    private Double statisticsPlanQty(List<MesWorkOrder> orderList, Map<String, List<MesOutPutStatistics>> itemMap2OutPut, MesWorkCenterExt workCenterExtDb) {
        return CollectionUtils.isEmpty(orderList) ? new Double(0) :
                orderList.stream().filter(o -> null != o).mapToDouble(o -> o.getStartTime().contains(workCenterExtDb.getWorkTime()) ? o.getQty() : MathOperation.add(MathOperation.sub(o.getQty(), o.getCompleteQty()), getOutPutQty(o.getOrderNo(), itemMap2OutPut))).sum();
    }

    private Double getOutPutQty(String workOrderNo, Map<String, List<MesOutPutStatistics>> itemMap2OutPut) {
        List<MesOutPutStatistics> outPutStatisticsList = CollectionUtils.isEmpty(itemMap2OutPut) ? null : itemMap2OutPut.get(workOrderNo);
        return getOutPutStatisticsList2AmountQty(outPutStatisticsList);
    }

}
