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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesConfigService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesContainerSnBindService;
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.MesProductionProcessContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesContainerSnBindModel;
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.util.MesConstWords;
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.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
import cn.estsh.i3plus.pojo.mes.repository.*;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
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.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * @Description : 零件条码绑定装配件站点容器工步
 * @Author : jason.niu
 **/
@Slf4j
@Service("mesStationFeedContainerPackageDetailStepService")
public class MesStationFeedContainerPackageDetailStepService extends BaseStepService {
    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;
    @Autowired
    private MesContainerSnStationRepository containerSnStationRDao;
    @Autowired
    private MesContainerTypePartRepository containerTypePartRDao;
    @Autowired
    private MesContainerSnPartRepository containerSnPartRDao;
    @Autowired
    private IMesContainerSnBindService containerSnBindService;
    @Autowired
    private MesContainerPackageRepository containerPackageRDao;
    @Autowired
    private MesContainerSnRepository containerSnRDao;
    @Autowired
    private MesConfigRepository mesConfigRepository;

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        StationResultBean resultBean = new StationResultBean();

        StepResult stepResult = StepResult.getSuccessComplete();
        final String organizeCode = reqBean.getOrganizeCode();

        //获取工位当前设备信息
        MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchCurCellEquipment(reqBean);

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

        //扫描信息置空
        String barcode = reqBean.resetScanInfo(reqBean.getScanInfo());
        if (StringUtils.isEmpty(barcode)) stepSendGuideAndThrowEx(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "请扫描原料条码!");

        if (containerSnRDao.isExitByProperty(new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, "containerSn"},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), barcode})) {
            return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_FEEDING), String.format("不能扫描容器条码[%s]，请重新扫描!", barcode));
        }
        final String lastFeedContainerSn = productionDispatchContextStepService.getMatchStationFeedContainerSnContext(reqBean);
        if (executeClosePackage(organizeCode, barcode, lastFeedContainerSn, reqBean.getUserInfo())) {
            return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "原料条码上料成功!");
        }

        //获取站点用于缺料时进行上料绑定
        List<MesStation> stationList = productionDispatchContextStepService.getMatchStationContext(reqBean);
        if (CollectionUtils.isEmpty(stationList)) {
            return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_FEEDING), "容器条码扣减装配件时验证设备未关联支持上料的站点");
        }

        if (!StringUtils.isEmpty(lastFeedContainerSn)) {
            int feedResult = executeFeedPartSn(reqBean, lastFeedContainerSn, barcode);
            if (feedResult == 1) {
                return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "原料条码上料成功!");
            } else if (feedResult == 2) {
                return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_FEEDING), false, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT, "原料条码上料成功，请继续扫描上料条码或扫描强制封箱条码！");
            }
        }

        stationList.sort(Comparator.comparing(MesStation::getCreateDatetime));
        for (MesStation station : stationList) {
            List<MesContainerSnStation> containerSnStations = getMesContainerSnStation(organizeCode, station.getStation());
            if (CollectionUtils.isEmpty(containerSnStations)) {
                continue;
            }
            containerSnStations.sort(Comparator.comparing(MesContainerSnStation::getContainerSn));
            for (MesContainerSnStation containerSnStation : containerSnStations) {
                final String feedContainerSn = containerSnStation.getContainerSn();
                if (Objects.equals(feedContainerSn, lastFeedContainerSn)) {
                    continue;
                }

                int feedResult = executeFeedPartSn(reqBean, feedContainerSn, barcode);
                if (feedResult == 1) {
                    return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "原料条码上料成功!");
                } else if (feedResult == 2) {
                    return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_FEEDING), false, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT, "原料条码上料成功，请继续扫描上料条码或扫描强制封箱条码！");
                }
            }
        }

        return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_FEEDING), "未匹配到可上料的容器，请重新扫描上料条码！");
    }

    private boolean executeClosePackage(String organizeCode, String barcode, String lastFeedContainerSn, String userName) {
        if (StringUtils.isEmpty(lastFeedContainerSn)) {
            return false;
        }
        MesConfig config = mesConfigRepository.getByProperty(
                new String[]{"cfgKey", "organizeCode", "isValid", "isDeleted"},
                new Object[]{"STEP_STATION_FEED_CONTAINER_PACKAGE_DETAIL", organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.IS_DEAL.NO.getValue()});
        if (config == null) {
            return false;
        }
        String closeSn = config.getCfgValue();
        if (StringUtils.isEmpty(closeSn) || !Objects.equals(closeSn, barcode)) {
            return false;
        }

        MesContainerSnBindModel model = MesContainerSnBindModel.builder()
                .organizeCode(organizeCode)
                .userName(userName)
                .containerSn(lastFeedContainerSn)
                .build();
        containerSnBindService.doClosePackage(model);
        return true;
    }

    private List<MesContainerSnStation> getMesContainerSnStation(String organizeCode, String station) {
        List<MesContainerSnStation> containerSnStations = containerSnStationRDao.findByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "station"},
                new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), station});
        containerSnStations.removeIf(temp -> !Objects.equals(temp.getContainerSn(), temp.getTopContainerSn()));
        return containerSnStations;
    }

    /**
     * 0未上料成功；1上料成功满箱自动关箱；2上料成功未满箱
     * @param reqBean
     * @param containerSn
     * @param barcode
     * @return
     */
    private int executeFeedPartSn(StationRequestBean reqBean, String containerSn, String barcode) {
        final String organizeCode = reqBean.getOrganizeCode();
        MesContainerSnBindModel model = MesContainerSnBindModel.builder()
                .organizeCode(organizeCode)
                .userName(reqBean.getUserInfo())
                .containerSn(containerSn)
                .barCode(barcode)
                .build();
        try {
            containerSnBindService.doScanBarcode(model, true);
            final String lastFeedContainerSn = hasFullPackage(organizeCode, containerSn) ? "" : containerSn;
            //加料后容器还未满，保存最近使用的站点
            productionDispatchContextStepService.dispatchMatchStationFeedContainerSnContext(reqBean, lastFeedContainerSn);
            if (StringUtils.isEmpty(lastFeedContainerSn)) {
                return 1;
            }
        } catch (Exception ignored) {
            return 0;
        }
        return 2;
    }

    private boolean hasFullPackage(String organizeCode, String containerSn) {
        MesContainerPackage containerPackage = containerPackageRDao.getByProperty(new String[]{MesConstWords.ORGANIZE_CODE, MesConstWords.IS_VALID, MesConstWords.IS_DELETED, "containerSn"},
                new Object[]{organizeCode, CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), containerSn});
        return containerPackage != null && Objects.equals(containerPackage.getPackageStatus(), MesExtEnumUtil.CONTAINER_PACKAGE_STATUS.STATUS_20.getValue());
    }
}
