package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionDispatchContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPartContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.mes.pcn.util.StringUtil;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import com.alibaba.fastjson.JSONObject;
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 javax.persistence.EntityManager;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 保存加工单信息工步 【非排序】
 * @Reference :
 * @Author : wangjie
 * @CreateDate : 2024/6/11 18:50
 * @Modify:
 **/
@Slf4j
@Service("mesWorkOrderSaveNosortStepServiceBak")
public class MesWorkOrderSaveNosortStepServiceBak extends BaseStepService {

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private IMesWorkOrderExtService workOrderExtService;

    @Autowired
    private MesWorkOrderRepository workOrderRepository;

    @Autowired
    private EntityManager entityManager;

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        StationResultBean resultBean = new StationResultBean();

        StepResult stepResult = StepResult.getSuccessComplete();

        //获取上下文信息
        MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchCurCellEquipment(reqBean);

        //配置错误 抛出异常
        if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage());

        //存储生产过程上下文对象
        productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext);

        //获取上下文产出零件数据信息集合
        List<MesProductionPartContext> productionPartContextList = productionDispatchContextStepService.getProductionPartContext(reqBean);

        //没有产出零件或者没有工单
        if (CollectionUtils.isEmpty(productionPartContextList) || StringUtils.isEmpty(
                productionPartContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).findFirst().get().getWorkOrderNo())) return stepResult;

        //获取上下文产出零件数据信息集合
        List<MesProductionPsOutContext> productionPsOutContextList = productionDispatchContextStepService.getProductionPsOutContext(reqBean);

        //保存生产工单数据
        doHandleWorkOrderData(reqBean, resultBean, productionPartContextList, productionPsOutContextList);

        return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存加工单信息成功!");

    }

    //保存生产工单数据
    private void doHandleWorkOrderData(StationRequestBean reqBean, StationResultBean resultBean, List<MesProductionPartContext> productionPartContextList, List<MesProductionPsOutContext> productionPsOutContextList) {

        //产出零件信息根据生产工单分组
        Map<String, List<MesProductionPartContext>> ppMap = productionPartContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.groupingBy(MesProductionPartContext::getWorkOrderNo));

        //产出条码 根据生产工单分组
        Map<String, List<MesProductionPsOutContext>> proMap = productionPsOutContextList.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(MesProductionPsOutContext::getWorkOrderNo));

        String productResult = productionDispatchContextStepService.getProductResultContext(reqBean);

        //遍历产出零件信息
        for(Map.Entry<String, List<MesProductionPartContext>> entry : ppMap.entrySet()) {

            if (null == entry) continue;
            //获取对应的加工规则
            List<MesProductionPsOutContext> produceSnContextList = proMap.get(entry.getKey());
            //生产数量
            Integer calcCompleteQty = 0;
            //遍历产出物料
            for (MesProductionPsOutContext productionPsOutContext : produceSnContextList) {
                if (null == productionPsOutContext) continue;
                //产出零件是否是
                if (productionPsOutContext.getIsCalcCompleteQty() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) calcCompleteQty += 1;
            }

            if (calcCompleteQty.compareTo(MesPcnExtConstWords.ZERO) == 0) continue;

            MesWorkOrder workOrder = workOrderExtService.getWorkOrder(reqBean.getOrganizeCode(), entry.getValue().get(0).getId());

            if (null == workOrder) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息不存在!", entry.getKey()));

            //工单状态分 排序工单 和非排序工单; 现在必须是非排序工单
            if (!MesExtEnumUtil.ORDER_STATUS.checkNosortAllowStatus(workOrder.getWorkOrderStatus()))
                stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息工单状态[%s]!", entry.getKey(), MesExtEnumUtil.ORDER_STATUS.valueOfDescription(workOrder.getWorkOrderStatus())));
            //工单产线要和当前产线一致
            if (!workOrder.getWorkCenterCode().equals(reqBean.getWorkCenterCode()))
                stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息所属生产线[%s]与当前生产线[%s]不一致!", entry.getKey(), workOrder.getWorkCenterCode(), reqBean.getWorkCenterCode()));

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

            //修改完成数量
            propertyMap.put(MesPcnExtConstWords.COMPLETE_QTY, MathOperation.add(workOrder.getCompleteQty(), calcCompleteQty));

            //修改未完成数量
            if (workOrder.getUnCompleteQty().compareTo(new Double(0)) > 0 && MathOperation.compareTo(MathOperation.sub(workOrder.getUnCompleteQty(), new Double(calcCompleteQty)), new Double(0)) >= 0) {
                propertyMap.put(MesPcnExtConstWords.UN_COMPLETE_QTY, MathOperation.sub(workOrder.getUnCompleteQty(), new Double(calcCompleteQty)));
            }

            /**
             * 可疑品、报废数量、上下线时间；
             * sql改成修改固定字段
             * 在上下文中获取busi中获取prodResult上下文  是数字  （标志着条码质量状态，与条码质量状态枚举一致）
             * 上下文中 已经按照工单分组了，因为有一模多腔问题
             */

            if (!StringUtils.isEmpty(productResult)) {
                //可疑品
                if (Integer.valueOf(productResult).compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SUSPICIOUS.getValue()) == 0 && !CollectionUtils.isEmpty(productionPsOutContextList)){
                    propertyMap.put(MesPcnExtConstWords.SUSPICIOUS_PART_QTY, MathOperation.add(workOrder.getSuspiciousPartQty(), new Double(productionPsOutContextList.size())));
                }
                //报废数量
                if (Integer.valueOf(productResult).compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SCRAP.getValue()) == 0 && !CollectionUtils.isEmpty(productionPsOutContextList)){
                    propertyMap.put(MesPcnExtConstWords.SCRAP_PART_QTY, MathOperation.add(workOrder.getScrapPartQty(), new Double(productionPsOutContextList.size())));
                }
            }

            if (MathOperation.compareTo(MathOperation.add(workOrder.getCompleteQty(), calcCompleteQty), workOrder.getQty()) >= 0 && workOrder.getWorkOrderStatus().compareTo(MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue()) != 0) {
                propertyMap.put(MesPcnExtConstWords.WORK_ORDER_STATUS, MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue());
            } else if (workOrder.getCompleteQty() >= 0 && workOrder.getWorkOrderStatus() == MesExtEnumUtil.ORDER_STATUS.RELEASE.getValue()) {
                propertyMap.put(MesPcnExtConstWords.WORK_ORDER_STATUS, MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue());
            }

            if (CollectionUtils.isEmpty(propertyMap)) continue;

            propertyMap.put(MesPcnExtConstWords.MODIFY_DATE_TIME, (new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT_SSS)).format(new Date()));
            propertyMap.put(MesPcnExtConstWords.MODIFY_USER, reqBean.getUserInfo());
            propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_STATUS, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
            propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.EMPTY);

            String[] propertyName = new String[propertyMap.size()];
            Object[] propertyValue = new Object[propertyMap.size()];

            Integer index = 0;
            for (Map.Entry<String, Object> innerEntry : propertyMap.entrySet()) {
                if (null == innerEntry) continue;
                propertyName[index] = innerEntry.getKey();
                propertyValue[index] = innerEntry.getValue();
                index ++;
            }

            workOrderRepository.updateByPropertiesNoSync(new String[]{MesPcnExtConstWords.ID, MesPcnExtConstWords.ORGANIZE_CODE}, new Object[]{workOrder.getId(), reqBean.getOrganizeCode()}, propertyName, propertyValue);

            log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- ORDER:{} --- QUERY:{} --- calcCompleteQty:{} --- productResult:{} --- UPDATE:{}",
                    reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(),
                    StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), workOrder.getWorkOrderNo(), JSONObject.toJSONString(workOrder), calcCompleteQty, productResult, JSONObject.toJSONString(propertyMap));

        }
    }

}

