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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
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.apiservice.serviceimpl.step.method.MesWorkOrderCheckCompleteQtyStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.*;
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.MesWorkOrderCalcQtyRecord;
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.MesWorkOrderCalcQtyRecordRepository;
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 java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private MesWorkOrderCheckCompleteQtyStepService workOrderCheckCompleteQtyStepService;

    @Autowired
    private MesWorkOrderCalcQtyRecordRepository workOrderCalcQtyRecordRepository;

    @Autowired
    private IMesProductionCustomContextStepService productionCustomContextStepService;

    @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, stepResult, productionProcessContext, productionPartContextList, productionPsOutContextList);

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

    }

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

        //工位是否不累计工单完成数
        Boolean noCalcOrderQty = workOrderCheckCompleteQtyStepService.noCalcOrderQty(productionProcessContext.getWorkCell().getNoCalcOrderQty());

        //获取上下文工位扫描监控信息
        MesScanMonitorContext scanMonitorContext = productionProcessContextStepService.dispatchScanMonitorContext(reqBean, true);

        //产出零件信息根据生产工单分组
        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(o -> null != o).collect(Collectors.groupingBy(MesProductionPsOutContext::getWorkOrderNo));

        //获取上下文加工结果
        Integer productResult = productionDispatchContextStepService.getProductResultQcContext(reqBean);

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

            if (null == entry) continue;
            //获取对应的加工规则
            List<MesProductionPsOutContext> productionPsOutContextList2Order = proMap.get(entry.getKey());
            //生产数量
            Double calcCompleteQty = new Double(MesPcnExtConstWords.ZERO);
            //遍历产出物料
            for (MesProductionPsOutContext productionPsOutContext : productionPsOutContextList2Order) {
                if (null == productionPsOutContext) continue;
                //产出零件需要计算工单完成数量
                if (productionPsOutContext.getIsCalcCompleteQty() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) calcCompleteQty = MathOperation.add(calcCompleteQty, productionPsOutContext.getQty());
            }

            if (MathOperation.compareTo(calcCompleteQty, new Double(MesPcnExtConstWords.ZERO)) == 0) continue;

            // 赋值 stepAfterState, 当前工步集执行结束后会执行当前工步重写的executeStepAfterState方法
            if (StringUtils.isEmpty(stepResult.getStepAfterState())) stepResult.stepAfterState(StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()));

            //TODO 排序考虑多工位扫描可疑码; 非排序考虑自进自出可疑或报废; 可疑数/报废数是否需要增加的问题[条码+零件+质量状态 增加履历]

            //工位不累计工单完成数
            if (noCalcOrderQty) continue;

            MesWorkOrderCalcQtyRecord workOrderCalcQtyRecord = new MesWorkOrderCalcQtyRecord();
            workOrderCalcQtyRecord.setOrganizeCode(reqBean.getOrganizeCode());
            workOrderCalcQtyRecord.setWorkCenterCode(reqBean.getWorkCenterCode());
            workOrderCalcQtyRecord.setWorkCellCode(reqBean.getWorkCellCode());
            workOrderCalcQtyRecord.setWorkOrderNo(entry.getKey());
            workOrderCalcQtyRecord.setPid(entry.getValue().get(0).getId());
            workOrderCalcQtyRecord.setCompleteQty(calcCompleteQty);
            //可疑数量
            if (!StringUtils.isEmpty(productResult) && productResult.compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SUSPICIOUS.getValue()) == 0) {
                workOrderCalcQtyRecord.setSuspiciousPartQty(calcCompleteQty);
            }
            //报废数量
            if (!StringUtils.isEmpty(productResult) && productResult.compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SCRAP.getValue()) == 0) {
                workOrderCalcQtyRecord.setScrapPartQty(calcCompleteQty);
            }

            if (null != scanMonitorContext) workOrderCalcQtyRecord.setMouldRecordId(scanMonitorContext.getMouldRecordId());

            workOrderCalcQtyRecord.setDealStatus(MesExtEnumUtil.MES_LOG_DEAL_STATUS.UNDEAL.getValue());
            workOrderCalcQtyRecord.setCreateUser(reqBean.getUserInfo());
            workOrderCalcQtyRecord.setModifyUser(reqBean.getUserInfo());
            workOrderCalcQtyRecord.setCreateDatetime((new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT_SSS)).format(new Date()));
            workOrderCalcQtyRecord.setModifyDatetime(workOrderCalcQtyRecord.getCreateDatetime());
            workOrderCalcQtyRecord.setIsValid(CommonEnumUtil.IS_VAILD.VAILD.getValue());
            workOrderCalcQtyRecord.setIsDeleted(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());

            workOrderCalcQtyRecord = workOrderCalcQtyRecordRepository.insert(workOrderCalcQtyRecord);

            log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- ORDER:{} --- productResult:{} --- MesWorkOrderCalcQtyRecord:{}",
                    reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(),
                    StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), entry.getKey(), productResult, JSONObject.toJSONString(workOrderCalcQtyRecord));

        }
    }

    //当前工步集完成之后执行当前方法
    @Override
    public void executeStepAfterState(StationRequestBean reqBean, StepResult stepResult) {
        if (!stepResult.isCompleted()) return;

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

        //工位是否不累计工单完成数
        Boolean noCalcOrderQty = workOrderCheckCompleteQtyStepService.noCalcOrderQty(productionPsOutContextList.get(0).getNoCalcOrderQty());

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

        //遍历产出物料
        for (Map.Entry<String, List<MesProductionPsOutContext>> entry : proMap.entrySet()) {
            if (null == entry) continue;
            //生产数量
            Double calcCompleteQty = new Double(MesPcnExtConstWords.ZERO);
            for (MesProductionPsOutContext productionPsOutContext : entry.getValue()) {
                if (null == productionPsOutContext) continue;
                //产出零件需要计算工单完成数量
                if (productionPsOutContext.getIsCalcCompleteQty() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) calcCompleteQty = MathOperation.add(calcCompleteQty, productionPsOutContext.getQty());
            }
            if (MathOperation.compareTo(calcCompleteQty, new Double(MesPcnExtConstWords.ZERO)) == 0) continue;

            //根据noCalcOrderQty判断维度处理处理工单完成数上下文[保存]
            MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = productionCustomContextStepService.dispatchWorkOrderCompleteQtyContext(reqBean, noCalcOrderQty, entry.getKey(), calcCompleteQty);

            log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- ORDER:{} --- noCalcOrderQty:{} --- calcCompleteQty:{} --- MesWorkOrderCompleteQtyContext:{}",
                    reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(),
                    StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), entry.getKey(), noCalcOrderQty, calcCompleteQty, JSONObject.toJSONString(workOrderCompleteQtyContext));

        }

    }

    //执行execute之后根据条件判断是否执行
    @Override
    public void executeStepAfterExecute(StationRequestBean reqBean, StepResult stepResult) {
        executeStepAfterState(reqBean, stepResult);
    }
}

