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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IMesProdShiftRecordService;
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.IMesQueueOrderPushService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.util.MesPcnException;
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.model.MesQueueOrderModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseModuleService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.IStepService;
import cn.estsh.i3plus.mes.pcn.util.PojoAttrUtil;
import cn.estsh.i3plus.platform.common.tool.CheckTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrder;
import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrderPush;
import cn.estsh.i3plus.pojo.mes.bean.MesStateMachineStatus;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter;
import cn.estsh.i3plus.pojo.mes.model.AttrBean;
import cn.estsh.i3plus.pojo.mes.model.StationKvBean;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.i3plus.pojo.mes.repository.MesQueueOrderRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
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.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description : 展示组件：排序生产
 * @Author :wangjie
 **/
@Slf4j
@Service("mesProductionSortModuleService")
public class MesProductionSortModuleService extends BaseModuleService {

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private IMesProdShiftRecordService prodShiftRecordService;

    @Autowired
    private MesQueueOrderRepository queueOrderRepository;

    @Autowired
    private IMesQueueOrderPushService queueOrderPushService;

    @Override
    public void init(StationRequestBean reqBean) {

        //获取上下文信息
        MesProductionProcessContext productionProcessContext = productionProcessContextStepService.getProductionProcessContext(reqBean, false);
        //配置错误 抛出异常
        if (!productionProcessContext.getSuccess()) {
            this.sendMessage(reqBean, new StationResultBean()
                    .busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.BUSI_LIST.getValue())
                    .addStationResultBeans(new StationResultBean().resultObj(MesPcnExtConstWords.STEP_DISABLE_SCAN)
                            .busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.STEP_TITLE.getValue()).dataType(MesPcnEnumUtil.STATION_DATA_TYPE.TITLE.getValue()).message(String.format("信息: %s!", productionProcessContext.getMessage())))
                    .addStationResultBeans(new StationResultBean().writeDbLog()
                            .busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE.getValue()).dataType(MesPcnEnumUtil.STATION_DATA_TYPE.TEXT.getValue()).message(productionProcessContext.getMessage()))
            );

            MesPcnException.throwBusiException(productionProcessContext.getMessage());
        }

        //获取班次信息，先查询缓存，缓存没有在查询数据库
        List<StationKvBean> prodShiftDataContext = prodShiftRecordService.getShiftRecordStationKvBeans(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode());
        if (CollectionUtils.isEmpty(prodShiftDataContext)) {
            this.sendMessage(reqBean, new StationResultBean()
                    .busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.BUSI_LIST.getValue())
                    .addStationResultBeans(new StationResultBean().resultObj(MesPcnExtConstWords.STEP_DISABLE_SCAN)
                            .busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.STEP_TITLE.getValue()).dataType(MesPcnEnumUtil.STATION_DATA_TYPE.TITLE.getValue()).message("信息: 请先开班!"))
                    .addStationResultBeans(new StationResultBean().writeDbLog()
                            .busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE.getValue()).dataType(MesPcnEnumUtil.STATION_DATA_TYPE.TEXT.getValue()).message("请先开班!"))
            );

            MesPcnException.throwBusiException("请先开班!");
        }

        // 获取工单信息
        List<List<StationKvBean>> moduleContentContext = productionDispatchContextStepService.getModuleContentContext(reqBean);

        // 发送班次班组和工单
        StationResultBean resultBean = getStationResultBean(reqBean, moduleContentContext, prodShiftDataContext);

        //生产线是否推单
        MesWorkCenter workCenter = productionProcessContext.getWorkCenter();
        Boolean isPushQueue = (StringUtils.isEmpty(workCenter.getIsPushQueue()) || workCenter.getIsPushQueue().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) != 0) ? false : true;

        //获取队列信息
        //非推单【获取当前工位最新修改的完成状态的队列单据数据 并根据其零件生产组代码按生产序号倒序前50条】
        List<MesQueueOrderModel> queueOrderModelList = !isPushQueue
                ? queryQueueOrderTopFiftyProductSeq(reqBean, getNewPartProdGroupCode(reqBean, moduleContentContext))
                : queryQueueOrderPush(reqBean);

        //封装工位展示的客制化信息
        StationResultBean resultBeanCustom = getStationResultBean(queueOrderModelList);

        if (null == resultBeanCustom) this.sendMessage(reqBean, resultBean);
        else this.sendMessage(reqBean, new StationResultBean().busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.BUSI_LIST.getValue()).addStationResultBeans(resultBean).addStationResultBeans(resultBeanCustom));

        //验证工位是否锁定
        reqBean.getDataMap().put(MesPcnEnumUtil.ACTOR_RECEIVE_STRATEGY.WS_CMD_INIT_MODULE.getCode(), CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
        ((IStepService) SpringContextsUtil.getBean("mesCountDownShowStepService")).executeInState(reqBean);

    }



    private StationResultBean getStationResultBean(List<MesQueueOrderModel> mesQueueOrderModelList) {
        if (CollectionUtils.isEmpty(mesQueueOrderModelList)) return null;
        return new StationResultBean().busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.MODULE_CUSTOM_CONTENT.getValue())
                .dataType(MesPcnEnumUtil.STATION_DATA_TYPE.TABLE.getValue()).customPageName(MesPcnExtConstWords.CUSTOM_PAGE_NAME_WORK_CELL)
                .dataAttrList(dataAttrList()).resultList(mesQueueOrderModelList);
    }

    //队列工单清单列表标题
    public List<AttrBean> dataAttrList() {
        List<AttrBean> attrBeanList = new ArrayList<>();
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.WORK_ORDER_SEQ, "工单序号");
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.CAR_MODEL_CODE, "车型配置");
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.CUST_ORDER_NO, "客户订单号");
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.PART_NO, "零件号");
        return attrBeanList;
    }

    //获取当前工位最新修改的完成状态的队列单据数据 并根据其零件生产组代码按生产序号倒序前50条
    private List<MesQueueOrderModel> queryQueueOrderTopFiftyProductSeq(StationRequestBean reqBean, List<String> partProdGroupCodeList) {

        if (CollectionUtils.isEmpty(partProdGroupCodeList)) return null;

        List<MesQueueOrderModel> queueOrderModelList = null;
        for (String partProdGroupCode : partProdGroupCodeList) {
            Pager pager = new Pager();
            pager.setStartRow(MesPcnExtConstWords.ONE);
            pager.setCurrentPage(MesPcnExtConstWords.ONE);
            pager.setPageSize(MesPcnExtConstWords.FIFTY);
            DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
            DdlPreparedPack.getStringEqualPack(reqBean.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
            DdlPreparedPack.getStringEqualPack(reqBean.getWorkCellCode(), MesPcnExtConstWords.WORK_CELL_CODE, packBean);
            DdlPreparedPack.getStringEqualPack(partProdGroupCode, MesPcnExtConstWords.PART_PROD_GROUP_CODE, packBean);
            DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesPcnExtConstWords.PRODUCT_SEQ}, packBean);
            List<MesQueueOrder> queueOrderList = queueOrderRepository.findByHqlWherePage(packBean, pager);

            if (!CollectionUtils.isEmpty(queueOrderList)) {
                Integer index = MesPcnExtConstWords.ONE;
                for (MesQueueOrder mesQueueOrder : queueOrderList) {
                    MesQueueOrderModel queueOrderModel = new MesQueueOrderModel();
                    BeanUtils.copyProperties(mesQueueOrder, queueOrderModel);

                    //默认绿色【完成状态或关闭状态】
                    String color = MesExtEnumUtil.COLOR.GREEN.getValue();
                    //创建状态标白色
                    if (queueOrderModel.getStatus() == MesExtEnumUtil.QUEUE_ORDER_STATUS.CREATE.getValue()) color = MesExtEnumUtil.COLOR.WHITE.getValue();
                    //跳号标黄色
                    if (index < queueOrderList.size() && checkJumpNumber(queueOrderList.get(index).getWorkOrderSeq(), mesQueueOrder.getWorkOrderSeq())) color = MesExtEnumUtil.COLOR.YELLOW.getValue();

                    queueOrderModel.setColor(color);

                    if (CollectionUtils.isEmpty(queueOrderModelList)) queueOrderModelList = new ArrayList<>();
                    queueOrderModelList.add(queueOrderModel);
                    index ++;
                }
            }
        }

        return queueOrderModelList;
    }

    //获取零件生产组代码
    private List<String> getNewPartProdGroupCode(StationRequestBean reqBean, List<List<StationKvBean>> moduleContentContext) {

        // 获取产成零件信息
        List<MesProductionPartContext> productionPartContext = productionDispatchContextStepService.getProductionPartContext(reqBean);
        // 排除掉空腔的产成零件
        productionPartContext = CollectionUtils.isEmpty(productionPartContext) ? null : productionPartContext.stream().filter(o -> !StringUtils.isEmpty(o.getForeignKey())).collect(Collectors.toList());

        // 扫描验证完加工单才能拿到产成零件信息
        if (!CollectionUtils.isEmpty(productionPartContext)) {
            return (productionPartContext.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPartProdGroupCode())))
                    .map(MesProductionPartContext::getPartProdGroupCode).collect(Collectors.toList())).stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        }

        //工序开始前可能会拿到页面顶部展示单加工单信息
        if (!CollectionUtils.isEmpty(moduleContentContext)) {
            return (moduleContentContext.stream()
                    .filter(o -> (null != o && o.stream().filter(i -> i.getKey().equals(MesPcnExtConstWords.PART_PROD_GROUP_CODE)).findFirst().isPresent()))
                    .map(o -> o.stream().filter(i -> i.getKey().equals(MesPcnExtConstWords.PART_PROD_GROUP_CODE)).findFirst().get().getValue()).collect(Collectors.toList())
            ).stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        }

        MesQueueOrder queueOrder = getNewQueueOrder(reqBean);
        return queueOrder == null ? null : Stream.of(queueOrder.getPartProdGroupCode()).collect(Collectors.toList());
    }

    //查询推单队列
    private List<MesQueueOrderModel> queryQueueOrderPush(StationRequestBean reqBean) {
        //处理排序线推单上下文, 返回推送工位类型对应的配置信息 【来源工位】;
        //再根据配置查询生产队列工位推送信息 : 根据生产线代码,推送来源代码集合查询创建状态的生产队列工位推送信息【创建时间正序】
        List<MesQueueOrderPush> queueOrderPushList = queueOrderPushService.getQueueOrderPushList(reqBean.getOrganizeCode(),
                productionProcessContextStepService.dispatchQueueOrderPushCellCfgContext(reqBean, MesExtEnumUtil.QUEUE_ORDER_CELL_PUSH_TYPE.TARGET.getValue()));

        //列表做多展示50条队列; 超过49条,进行截取
        if (!CollectionUtils.isEmpty(queueOrderPushList) && queueOrderPushList.size() > MesPcnExtConstWords.FORTY_NINE) queueOrderPushList = queueOrderPushList.subList(MesPcnExtConstWords.ZERO, MesPcnExtConstWords.FORTY_NINE);

        //查询最多50条当前工位修改时间最新的队列记录
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkCellCode(), MesPcnExtConstWords.WORK_CELL_CODE, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesPcnExtConstWords.MODIFY_DATE_TIME}, packBean);
        Integer topNum = CollectionUtils.isEmpty(queueOrderPushList) ? MesPcnExtConstWords.FIFTY : (MesPcnExtConstWords.FIFTY - queueOrderPushList.size());
        List<MesQueueOrder> queueOrderList = queueOrderRepository.findByHqlTopWhere(packBean, topNum);

        if (CollectionUtils.isEmpty(queueOrderPushList) && CollectionUtils.isEmpty(queueOrderList)) return null;

        //推送队列根据创建时间倒序
        if (!CollectionUtils.isEmpty(queueOrderPushList)) queueOrderPushList = queueOrderPushList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesQueueOrderPush::getCreateDatetime).reversed()).collect(Collectors.toList());

        List<MesQueueOrderModel> queueOrderModelList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(queueOrderPushList)) {
            for (MesQueueOrderPush queueOrderPush : queueOrderPushList) {
                if (null == queueOrderPush) continue;
                MesQueueOrderModel queueOrderModel = new MesQueueOrderModel();
                BeanUtils.copyProperties(queueOrderPush, queueOrderModel);
                queueOrderModel.setWorkCellCode(reqBean.getWorkCellCode());
                queueOrderModel.setStatus(MesExtEnumUtil.QUEUE_ORDER_STATUS.CREATE.getValue());
                queueOrderModelList.add(queueOrderModel);
            }
        }
        if (!CollectionUtils.isEmpty(queueOrderList)) {
            for (MesQueueOrder queueOrder : queueOrderList) {
                if (null == queueOrder) continue;
                MesQueueOrderModel queueOrderModel = new MesQueueOrderModel();
                BeanUtils.copyProperties(queueOrder, queueOrderModel);
                queueOrderModelList.add(queueOrderModel);
            }
        }

        Integer index = MesPcnExtConstWords.ONE;
        for (MesQueueOrderModel queueOrderModel : queueOrderModelList) {
            if (null == queueOrderModel) continue;
            //默认绿色【完成状态】
            String color = MesExtEnumUtil.COLOR.GREEN.getValue();
            if (queueOrderModel.getStatus() == MesExtEnumUtil.QUEUE_ORDER_STATUS.CREATE.getValue()) color = MesExtEnumUtil.COLOR.WHITE.getValue();
            //跳号标黄色
            if (index < queueOrderList.size() && checkSamePartProdGroupCode(queueOrderModelList.get(index).getPartProdGroupCode(), queueOrderModel.getPartProdGroupCode()) && checkJumpNumber(queueOrderModelList.get(index).getWorkOrderSeq(), queueOrderModel.getWorkOrderSeq())) color = MesExtEnumUtil.COLOR.YELLOW.getValue();
            queueOrderModel.setColor(color);
            index ++;
        }

        return queueOrderModelList;
    }

    //验证生成
    private Boolean checkSamePartProdGroupCode(String nextPartProdGroupCode, String partProdGroupCode) {
        if (StringUtils.isEmpty(nextPartProdGroupCode) || StringUtils.isEmpty(partProdGroupCode)) return false;
        return nextPartProdGroupCode.equals(partProdGroupCode);
    }

    //标黄是跳号的工单, 不是跳过的工单
    private Boolean checkJumpNumber(String nextWorkOrderSeq, String currentWorkOrderSeq) {
        if (StringUtils.isEmpty(nextWorkOrderSeq) || StringUtils.isEmpty(currentWorkOrderSeq) || !CheckTool.isNumber(nextWorkOrderSeq) || !CheckTool.isNumber(currentWorkOrderSeq)) return false;
        return Integer.parseInt(currentWorkOrderSeq) != Integer.parseInt(nextWorkOrderSeq) + MesPcnExtConstWords.ONE;
    }

    //查询当前工位完成状态最新的一笔队列记录
    private MesQueueOrder getNewQueueOrder(StationRequestBean reqBean) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkCellCode(), MesPcnExtConstWords.WORK_CELL_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.QUEUE_ORDER_STATUS.FINISH.getValue(), MesPcnExtConstWords.STATUS, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesPcnExtConstWords.MODIFY_DATE_TIME}, packBean);
        return queueOrderRepository.getByProperty(packBean);
    }

    private StationResultBean getStationResultBean(StationRequestBean reqBean, List<List<StationKvBean>> moduleContentContext, List<StationKvBean> prodShiftDataContext) {
        StationResultBean resultBean = new StationResultBean();
        resultBean.setBusiType(MesPcnEnumUtil.STATION_BUSI_TYPE.MODULE_CONTENT.getValue());
        resultBean.setDataType(MesPcnEnumUtil.STATION_DATA_TYPE.CUSTOM.getValue());
        resultBean.setCustomPageName(MesPcnExtConstWords.CUSTOM_PAGE_NAME_DEFAULT);
        resultBean.setSpecialDisplayData(getStepColIndent(reqBean));

        resultBean.setResultObj(prodShiftDataContext);
        resultBean.setResultList(moduleContentContext);
        return resultBean;
    }

    @Override
    public boolean execStateModule(StationRequestBean reqBean, List<MesStateMachineStatus> states, Map<String, String> wcpcMap) {
        init(reqBean);
        return true;
    }

}
