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.pojo.context.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesWorkOrderCutDetailModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmRouteDataService;
import cn.estsh.i3plus.mes.pcn.api.iservice.busi.ISyncFuncService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.*;
import cn.estsh.i3plus.pojo.mes.model.GenSerialNoModel;
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.MesWorkOrderCutPackageRepository;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
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 java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Description : 保存裁片工单包装条码工步
 * @Author : wangjie
 **/
@Slf4j
@Service("mesWorkOrderCutPackageSnSaveStepService")
public class MesWorkOrderCutPackageSnSaveStepService extends BaseStepService {

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private ISyncFuncService syncFuncService;

    @Autowired
    private IFsmRouteDataService fsmRouteDataService;

    @Autowired
    private MesWorkOrderCutPackageRepository workOrderCutPackageRepository;

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        StationResultBean resultBean = new StationResultBean();

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

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

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

        // 获取产成零件信息
        Map<String, MesPartContext> partDataContext = productionProcessContextStepService.getPartDataExtContext(reqBean);

        //从上下文中取出工位对象
        MesWorkCell workCell = productionProcessContext.getWorkCell();

        // 重新收集打印裁片箱条码
        List<MesWorkOrderCutDetailModel> newWorkOrderCutFgDataContextList = new ArrayList<>();

        // 最后一个工位才生成箱条码
        if (workCell.getIsEndWorkCell() != null && workCell.getIsEndWorkCell() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) {
            // 从上下文中取出成品列表
            List<MesWorkOrderCutDetailModel> workOrderCutFgDataContextList = productionDispatchContextStepService.getMesWorkOrderCutFgDataContext(reqBean);

            //搜集裁片工单号
            //List<String> filterList = equipVariableCollectContextList.stream().filter(o -> (null != o)).map(MesEquipVariableCollectContext::getEquipVariableValue).collect(Collectors.toList());
            //List<String> workOrderCutNoList = filterList.stream().filter(o -> (!StringUtils.isEmpty(o) && !o.equals(productionProcessContext.getFinishCode()))).distinct().collect(Collectors.toList());
            //String cutWorkOrderNo = workOrderCutNoList.stream().findFirst().get();

            if (CollectionUtils.isEmpty(workOrderCutFgDataContextList))
                stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "缺失裁片工单箱条码配置信息!");

            for (MesWorkOrderCutDetailModel workOrderCutDetailModel : workOrderCutFgDataContextList) {
                BigDecimal[] bigDecimals = divideAndRemainder(workOrderCutDetailModel);

                // 获取 商 根据商的决定生成条码次数
                double num = bigDecimals[0].doubleValue();

                /* 如果余数 大于0 则 分为两种情况
                    1、产成数量 不大于 标包数量
                    2、剩余产成数量 生成尾数箱条码
                 */
                double remainder = bigDecimals[1].doubleValue();

                List<MesWorkOrderCutPackage> workOrderCutPackages = new ArrayList<>();

                // 商大于 0 则
                while (num > 0) {
                    // 满箱直接取标包数量
                    packWorkOrderPackageList(reqBean, resultBean, workOrderCutDetailModel, partDataContext,
                            workOrderCutDetailModel.getPackageQty(), workOrderCutPackages, newWorkOrderCutFgDataContextList);
                    num--;
                }

                if (remainder > 0) {
                    // 尾数箱取剩余产成数量
                    packWorkOrderPackageList(reqBean, resultBean, workOrderCutDetailModel, partDataContext,
                            remainder, workOrderCutPackages, newWorkOrderCutFgDataContextList);
                }

                // 保存条码数据
                workOrderCutPackageRepository.saveAll(workOrderCutPackages);

            }

            productionDispatchContextStepService.dispatchMesWorkOrderCutFgDataContext(reqBean, newWorkOrderCutFgDataContextList);

        }

        return stepSuccessCompleteAndSendMsgReturn(reqBean, new StationResultBean().writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "保存裁片工单箱条码成功!");

    }

    private void packWorkOrderPackageList(StationRequestBean reqBean, StationResultBean resultBean,
                                          MesWorkOrderCutDetailModel workOrderCutDetailModel,
                                          Map<String, MesPartContext> partDataContext,
                                          Double qty, List<MesWorkOrderCutPackage> workOrderCutPackages,
                                          List<MesWorkOrderCutDetailModel> newWorkOrderCutFgDataContextList) {

        MesPartContext mesPartContext = partDataContext.get(workOrderCutDetailModel.getPartNo());
        String nowTime = TimeTool.getNowTime(false);
        MesWorkOrderCutPackage cutPackage = new MesWorkOrderCutPackage();
        ConvertBean.serviceModelInitialize(cutPackage, reqBean.getUserInfo());
        cutPackage.setOrganizeCode(reqBean.getOrganizeCode());
        BeanUtils.copyProperties(workOrderCutDetailModel, cutPackage);
        cutPackage.setQty(qty);
        cutPackage.setLotNo(nowTime.substring(0,10));
        cutPackage.setSn(doGenerateSerialNo(reqBean, resultBean, mesPartContext.getPackageSnRule(), mesPartContext));

        MesWorkOrderCutDetailModel newWorkOrderCutDetailModel = new MesWorkOrderCutDetailModel();
        BeanUtils.copyProperties(workOrderCutDetailModel, newWorkOrderCutDetailModel);
        newWorkOrderCutDetailModel.setCutWorkOrderNo(cutPackage.getCutWorkOrderNo());
        newWorkOrderCutDetailModel.setPackageNo(cutPackage.getSn());
        newWorkOrderCutDetailModel.setQty(qty);
        newWorkOrderCutDetailModel.setCreateDatetime(cutPackage.getCreateDatetime());
        newWorkOrderCutDetailModel.setLotNo(cutPackage.getLotNo());
        newWorkOrderCutDetailModel.setCopies(mesPartContext.getCopies());
        newWorkOrderCutDetailModel.setPackageSnRule(mesPartContext.getPackageSnRule());
        newWorkOrderCutDetailModel.setPrinter(mesPartContext.getPrinter());
        newWorkOrderCutDetailModel.setCustPartNo(mesPartContext.getCustPartNo());
        newWorkOrderCutDetailModel.setLabelTemplate(mesPartContext.getLabelTemplate());
        newWorkOrderCutDetailModel.setOrganizeCode(mesPartContext.getOrganizeCode());

        workOrderCutPackages.add(cutPackage);
        newWorkOrderCutFgDataContextList.add(newWorkOrderCutDetailModel);
    }

    private BigDecimal[] divideAndRemainder(MesWorkOrderCutDetailModel workOrderCutDetailModel) {
        BigDecimal dividend  = new BigDecimal(workOrderCutDetailModel.getQty().toString());
        BigDecimal divisor = new BigDecimal(workOrderCutDetailModel.getPackageQty().toString());
        return dividend.divideAndRemainder(divisor);
    }

    private String doGenerateSerialNo(StationRequestBean reqBean, StationResultBean resultBean, String ruleCode, MesPart part) {
        try {
            return syncFuncService.syncSerialNo(
                    new GenSerialNoModel(ruleCode).prodLocation(reqBean.getWorkCenterCode()).partNo(part.getPartNo()).putDataMap(MesPart.class.getSimpleName(), part).year(TimeTool.pareDateToString(MesPcnExtConstWords.DATE_FORMAT_YY, new Date())).organizeCode(reqBean.getOrganizeCode()),
                    reqBean.getUserInfo(), reqBean.getOrganizeCode(), 1).getResultList().get(0).toString();
        } catch (ImppBusiException e) {
            stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), e.getErrorDetail());
        } catch (Exception e) {
            String webMsg = String.format("零件编码[%s]编码规则代码[%s]生成零件条码%s", part.getPartNo(), ruleCode, fsmRouteDataService.handleFsmCfgOrDefault(reqBean, MesPcnEnumUtil.FSM_CFG.FSM_EXCEPTION_MSG.getCode()));
            this.sendMessage(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.ERROR.getValue()), webMsg, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            this.cacheException(reqBean, reqBean.getStepName(), webMsg, e, true);
            foundExThrowNoShowMsg();
        }
        return null;
    }

}
