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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProduceSnExtService;
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.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.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesProductionAssembly;
import cn.estsh.i3plus.pojo.mes.bean.MesProductionAssemblyUnique;
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.MesProductionAssemblyRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesProductionAssemblyUniqueRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
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.*;
import java.util.stream.Collectors;

/**
 * @Description : 保存装配记录工步 【非排序】
 * @Author : wangjie
 **/
@Slf4j
@Service("mesAssemblySaveStepService")
public class MesAssemblySaveStepService extends BaseStepService {

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private IMesProductionCustomContextStepService productionCustomContextStepService;

    @Autowired
    private MesProductionAssemblyRepository productionAssemblyRepository;

    @Autowired
    private MesProductionAssemblyUniqueRepository productionAssemblyUniqueRepository;

    @Autowired
    private IMesProduceSnExtService produceSnExtService;

    @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<MesProdRuleContext> prodRuleContextList = productionDispatchContextStepService.getProdRuleDataContext(reqBean);

        if (CollectionUtils.isEmpty(prodRuleContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在非排序加工规则数据,请重置工序!");

        //判断是否存在装配件清单
        if (!checkIsNeedScanAssembly(prodRuleContextList)) {
            return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, true,
                    MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT, "当前加工规则无装配件清单,当前无需保存装配件记录!");
        }

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

        if (CollectionUtils.isEmpty(productionPsOutContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在产出零件条码信息,请重置工序解决!");

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

        //从上下文中取出工位当前要使用的设备
        MesCellEquipContext cellEquipContext = productionProcessContext.getCurCellEquip();

        Map<Integer, MesProductionPsOutContext> ppMap = CollectionUtils.isEmpty(productionPsOutContextList) ? null : productionPsOutContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.toMap(MesProductionPsOutContext::getForeignKey, o -> o));

        List<Long> productSnIdList = new ArrayList<>();

        //保存装配记录
        prodRuleContextList.stream().filter(o -> null != o).forEach(o -> saveProductionAssemblyData(reqBean, productSnIdList, productionProcessContext, o, ppMap, cellEquipContext, scanMonitorContext));

        if (!CollectionUtils.isEmpty(productSnIdList)) produceSnExtService.saveProduceSnList(reqBean, MesExtEnumUtil.PRODUCE_SN_STATUS.ASSEMBLY.getValue(), productSnIdList);

        return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存装配记录成功!");

    }

    //判断是否存在装配件清单
    private Boolean checkIsNeedScanAssembly(List<MesProdRuleContext> prodRuleContextList) {
        Optional<MesProdRuleContext> optional = prodRuleContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getAssemblyDataJson()))).findFirst();
        return (null == optional || !optional.isPresent()) ? false : true;
    }

    private void saveProductionAssemblyData(StationRequestBean reqBean, List<Long> productSnIdList, MesProductionProcessContext productionProcessContext, MesProdRuleContext prodRuleContext,
                                            Map<Integer, MesProductionPsOutContext> ppMap, MesCellEquipContext cellEquipContext, MesScanMonitorContext scanMonitorContext) {

        if (StringUtils.isEmpty(prodRuleContext.getAssemblyDataJson())) return;

        List<MesProductionAssemblyNosortContext> productionAssemblyNosortContextList = prodRuleContext.getNosortAssemblyDataContext();

        MesProductionPsOutContext productionPsOutContext = CollectionUtils.isEmpty(ppMap) ? null : ppMap.get(prodRuleContext.getForeignKey());

        for (MesProductionAssemblyNosortContext productionAssemblyNosortContext : productionAssemblyNosortContextList) {

            if (null == productionAssemblyNosortContext) continue;

            MesProductionAssembly productionAssembly = new MesProductionAssembly();
            BeanUtils.copyProperties(productionAssemblyNosortContext, productionAssembly);

            productionAssembly.setIsOrigSn(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());

            productionAssembly.setAreaCode(reqBean.getAreaCode());
            productionAssembly.setWorkCenterCode(reqBean.getWorkCenterCode());
            productionAssembly.setWorkCellCode(reqBean.getWorkCellCode());
            productionAssembly.setProcessCode(reqBean.getProcessCode());

            productionAssembly.setProcessName(productionProcessContext.getProcessName());
            productionAssembly.setCraftCode(productionProcessContext.getCraftCode());
            productionAssembly.setCraftName(productionProcessContext.getCraftName());

            productionAssembly.setEquipmentCode(cellEquipContext.getEquipmentCode());

            productionAssembly.setProductionRecordId(prodRuleContext.getProductionRecordId());
            productionAssembly.setMouldNo(prodRuleContext.getMouldNo());

            if (null != productionPsOutContext) {
                productionAssembly.setPartNo(productionPsOutContext.getPartNo());
                productionAssembly.setPartName(productionPsOutContext.getPartName());
                productionAssembly.setSerialNumber(productionPsOutContext.getSerialNumber());
                productionAssembly.setProductSn(productionPsOutContext.getProductSn());
                productionAssembly.setCustSn(productionPsOutContext.getCustSn());
            }

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

            productionAssembly.setFid(UUID.randomUUID().toString());
            productionAssembly.setOrganizeCode(reqBean.getOrganizeCode());
            ConvertBean.serviceModelInitialize(productionAssembly, reqBean.getUserInfo());

            productionAssembly = productionAssemblyRepository.insert(productionAssembly);

            saveProductionAssemblyUnique(productionAssembly);

            if (!StringUtils.isEmpty(productionAssemblyNosortContext.getProductSnId())) productSnIdList.add(productionAssemblyNosortContext.getProductSnId());

            if (productionAssemblyNosortContext.getIsRepeat().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0 && productionAssemblyNosortContext.getIsRepeat2Cache().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0)
                productionCustomContextStepService.dispatchRepeatAssemblySn(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), productionAssemblyNosortContext);

        }

    }

    private void saveProductionAssemblyUnique(MesProductionAssembly productionAssembly) {
        if (productionAssembly.getMatchType().compareTo(MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_30.getValue()) != 0 || StringUtils.isEmpty(productionAssembly.getAssemblySn())) return;
        MesProductionAssemblyUnique productionAssemblyUnique = new MesProductionAssemblyUnique();
        BeanUtils.copyProperties(productionAssembly, productionAssemblyUnique, MesPcnExtConstWords.ID);
        productionAssemblyUnique.setPid(productionAssembly.getId());
        productionAssemblyUniqueRepository.insert(productionAssemblyUnique);
    }

}
