package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.station.function;

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step.method.IMesPackageNoGenerateStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesPackageDataContext;
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.serviceimpl.fsm.BaseSwsService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.function.IFsmModuleFunctionService;
import cn.estsh.i3plus.mes.pcn.util.StringUtil;
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.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesPackage;
import cn.estsh.i3plus.pojo.mes.model.ButtonDynamicModel;
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.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import com.alibaba.fastjson.JSONObject;
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.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

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

/**
 * @Description : 工位参数按钮事件接口实现【打包进度】
 **/
@Slf4j
@Service
public class MesFunctionPackageProgressService extends BaseSwsService implements IFsmModuleFunctionService {

    @Autowired
    private IMesProductionCustomContextStepService productionCustomContextStepService;

    @Autowired
    private IMesPackageNoGenerateStepService packageNoGenerateStepService;

    @Autowired
    private IFsmRouteDataService fsmRouteDataService;

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Object doCustomApiDispatch(StationRequestBean reqBean, StationResultBean resultBean, ButtonDynamicModel buttonDynamicModel) {

        //页面渲染数据集
        Map<String, Object> resultMap = new HashMap<>();

        //获取打包数据
        Map<String, String> packageDataContextMap = productionCustomContextStepService.getPackageDataContext(reqBean);

        if (CollectionUtils.isEmpty(packageDataContextMap)) {
            resultMap.put(MesPcnExtConstWords.DATA_TYPE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT.getValue());
            resultMap.put(MesPcnExtConstWords.MESSAGE, "当前无包装信息!");
            return resultMap;
        }

        //封装返回列表
        List<MesPackageDataContext> resultList = new ArrayList<>();

        //封装页面数据
        for (String partNo : packageDataContextMap.keySet()) {
            if (StringUtils.isEmpty(partNo)) continue;

            List<MesPackageDataContext> packageDataContextList = JSONObject.parseArray(packageDataContextMap.get(partNo), MesPackageDataContext.class);
            packageDataContextList = packageDataContextList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesPackageDataContext::getModifyDatetime).reversed()).collect(Collectors.toList());

            //列表展示: 包装条码, 装箱个数, 包装规格数量, 装箱开始时间, 装箱结束时间
            resultList.add(new MesPackageDataContext(
                    packageDataContextList.get(0).getPartNo(), packageDataContextList.get(0).getPartName(),
                    packageDataContextList.get(0).getPackageNo(), new Double(packageDataContextList.size()), packageDataContextList.get(0).getPackSpecQty(),
                    packageDataContextList.get(0).getCreateDatetime(), packageDataContextList.get(0).getModifyDatetime(), packageDataContextList.get(0).getGenerateType())
            );
        }

        //页面数据更新时间倒序
        resultList = resultList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesPackageDataContext::getModifyDatetime).reversed()).collect(Collectors.toList());

        resultMap.put(MesPcnExtConstWords.DATA, resultList);
        //打包进度页面业务操作[查询]
        if (StringUtils.isEmpty(buttonDynamicModel.getFunctionValue())) return resultMap;

        resultMap.put(MesPcnExtConstWords.DATA_TYPE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT.getValue());

        //打包进度页面业务操作的当前数据
        MesPackageDataContext packageDataContext = JSONObject.parseObject(buttonDynamicModel.getFunctionValue(), MesPackageDataContext.class);

        resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PICK.getValue()).scanInfo(packageDataContext.getPackageNo());

        if (null == packageDataContext || StringUtils.isEmpty(packageDataContext.getBusiType())) {
            return packResultMap(reqBean, resultBean, resultMap,
                    String.format("生产线[%s]工位[%s]打包进度操作按钮执行失败,参数异常!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode()));
        }

        if (CollectionUtils.isEmpty(packageDataContextMap) || !packageDataContextMap.containsKey(packageDataContext.getPartNo())) {
            return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]打包进度[%s]失败,当前已无零件号[%s]未封箱状态的包装信息!",
                    reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPartNo()));
        }

        //打包进度页面业务操作的当前数据对应的实际包装数据
        List<MesPackageDataContext> packageDataContextList = JSONObject.parseArray(packageDataContextMap.get(packageDataContext.getPartNo()), MesPackageDataContext.class);
        if (CollectionUtils.isEmpty(packageDataContextList) || !packageDataContextList.get(0).getPackageNo().equals(packageDataContext.getPackageNo())) {
            return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]打包进度[%s]失败,打包进度列表中已经不存在包装条码[%s],请刷新重试!",
                    reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPackageNo()));
        }

        //根据包装ID查询包装信息
        MesPackage packageDb = packageNoGenerateStepService.getMesPackage(reqBean.getOrganizeCode(), packageDataContextList.get(0).getPackageId());
        if (null == packageDb) {
            return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]打包进度[%s]失败,包装条码[%s]信息已经不存在,请刷新重试!",
                    reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPackageNo()));
        }
        if (packageDb.getIsSealed().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) {
            return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]打包进度[%s]失败,包装条码[%s]信息当前状态[已封箱],请刷新重试!",
                    reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPackageNo()));
        }

        String suffix;
        //修改数量
        if (BUSI_TYPE.THREE.getValue().equals(packageDataContext.getBusiType())) {
            //仅统计包装才支持修改数量
            if (packageDataContextList.get(0).getGenerateType().compareTo(MesExtEnumUtil.PACKING_RULE_GENERATE_TYPE.PACKAGE.getValue()) != 0) {
                return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]包装条码[%s]不支持修改数量,请刷新重试!",
                        reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), packageDataContext.getPackageNo()));
            }
            if (packageDataContextList.size() == packageDataContext.getQty()) {
                return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]包装条码[%s]修改数量操作无效,请刷新重试!",
                        reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), packageDataContext.getPackageNo()));
            }
            if (MathOperation.compareTo(packageDataContext.getQty(), packageDataContext.getPackSpecQty()) > 0) {
                return packResultMap(reqBean, resultBean, resultMap, String.format("生产线[%s]工位[%s]包装条码[%s]修改数量[%s]不能超过包装规格数量[%s],请刷新重试!",
                        reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), packageDataContext.getPackageNo(), packageDataContext.getQty(), packageDataContext.getPackSpecQty()));
            }

            suffix = String.format("包装条码ID[%s]原数量[%s]修改为[%s]", packageDb.getId(), packageDb.getQty(), packageDataContext.getQty());

            //修改包装信息的数量
            packageNoGenerateStepService.savePackageData(reqBean, packageDb, packageDataContext.getQty());
            //打包数据更新数量(判断是增加还是减少数量)
            if (MathOperation.compareTo(packageDataContext.getQty(), new Double(packageDataContextList.size())) < 0) {
                packageDataContextList = packageDataContextList.subList(0, packageDataContext.getQty().intValue());
            } else {
                Integer loopTimes = packageDataContext.getQty().intValue() - packageDataContextList.size();
                for (int i = 0; i < loopTimes; i ++) {
                    MesPackageDataContext addPackageDataContext = new MesPackageDataContext();
                    BeanUtils.copyProperties(packageDataContextList.get(0), addPackageDataContext);
                    addPackageDataContext.setModifyDatetime(TimeTool.getNowTime(true));
                    packageDataContextList.add(addPackageDataContext);
                }
            }
            //打包数据更新数量
            packageDataContextMap.put(packageDataContext.getPartNo(), JSONObject.toJSONString(packageDataContextList));
            //页面数据更新数量
            resultList.stream().filter(o -> (null != o && o.getPackageNo().equals(packageDataContext.getPackageNo()))).findFirst().get().qty(packageDataContext.getQty(), TimeTool.getNowTime(true));
        } else {
            //强制打包
            if (BUSI_TYPE.ONE.getValue().equals(packageDataContext.getBusiType())) {
                StepResult stepResult = StepResult.getSuccessComplete();
                try {
                    //强制打包业务处理
                    packageNoGenerateStepService.doForcePrint(reqBean, resultBean, stepResult, packageDataContextList, packageDb);
                } catch (ImppBusiException e) {
                    stepResult.msg(e.getErrorDetail());
                } catch (Exception e) {
                    String error = String.format("生产线[%s]工位[%s]强制打包%s", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), fsmRouteDataService.handleFsmCfgOrDefault(reqBean, MesPcnEnumUtil.FSM_CFG.FSM_EXCEPTION_MSG.getCode()));
                    this.cacheException(reqBean, StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), error, e, false);
                    stepResult.msg(error);
                }
                //判断强制打包的执行结果
                if (!StringUtils.isEmpty(stepResult.getMsg())) {
                    return packResultMap(reqBean, resultBean, resultMap,
                            String.format("生产线[%s]工位[%s]强制打包失败,%s", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), stepResult.getMsg()));
                }
            } else {
                //删除包装信息
                packageNoGenerateStepService.deletePackageData(reqBean, packageDb, packageDataContextList.get(0).getGenerateType());
            }

            suffix = String.format("包装条码ID[%s]", packageDb.getId());

            //打包数据移除当前零件的包装信息
            packageDataContextMap.remove(packageDataContext.getPartNo());

            //页面数据移除当前零件的包装信息
            resultList = resultList.stream().filter(o -> (null != o && !o.getPackageNo().equals(packageDataContext.getPackageNo()))).collect(Collectors.toList());
        }

        //保存打包数据
        productionCustomContextStepService.dispatchPackageDataContext(reqBean, packageDataContextMap);

        //重载页面数据
        if (CollectionUtils.isEmpty(resultList)) resultMap.remove(MesPcnExtConstWords.DATA);
        else resultMap.put(MesPcnExtConstWords.DATA, resultList);

        resultMap.put(MesPcnExtConstWords.DATA_TYPE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT.getValue());
        return packResultMap(reqBean, resultBean, resultMap, String.format("%s成功!零件号[%s]%s", BUSI_TYPE.valueOfDescription(packageDataContext.getBusiType()), packageDataContext.getPartNo(), suffix));

    }

    //返回提示信息
    private Map<String, Object> packResultMap(StationRequestBean reqBean, StationResultBean resultBean, Map<String, Object> resultMap, String message) {
        this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
        resultMap.put(MesPcnExtConstWords.MESSAGE, message);
        return resultMap;
    }


    //打包进度页面业务操作
    enum BUSI_TYPE {

        ONE("1", "强制打包"),

        TWO("2", "删除包装"),

        THREE("3", "修改数量");

        private String value;

        private String description;

        BUSI_TYPE(String value, String description) {

            this.value = value;

            this.description = description;

        }

        public String getValue() {
            return value;
        }

        public String getDescription() {
            return description;
        }

        public static String valueOfDescription(String val) {
            String tmp = null;
            for (int i = 0; i < values().length; i++) {
                if (val.equals(values()[i].value)) {
                    tmp = values()[i].description;
                }
            }
            return tmp;
        }

    }
}
