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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesNumberRuleMatchDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesRawPartChargingService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.util.MesPcnException;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesRawPackageModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesRawPartChargingModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.*;
import cn.estsh.i3plus.pojo.mes.repository.*;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import cn.estsh.impp.framework.boot.util.ValidatorBean;
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.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @Description : 加料防错
 * @Reference :
 * @Author : junsheng.li
 * @CreateDate 2024/6/30 12:20
 * @Modify:
 **/
@Service
@Slf4j
public class MesRawPartChargingServiceImpl implements IMesRawPartChargingService {
    @Autowired
    private MesRawPackageRepository mesRawPackageRepository;

    @Autowired
    private MesRawPackageDetailRepository mesRawPackageDetailRepository;

    @Autowired
    private MesRawPackagePartRepository mesRawPackagePartRepository;

    @Autowired
    private MesRawPartChargingRepository mesRawPartChargingRepository;

    @Autowired
    private MesRawPartChargingLogRepository mesRawPartChargingLogRepository;

    @Autowired
    private MesPartSapRepository mesPartSapRDao;

    @Autowired
    private MesProduceSnRepository mesProduceSnRDao;

    @Override
    public MesRawPartChargingModel findMesRawPackagePart(MesRawPartChargingModel mesRawPartChargingModel) {
        MesRawPackageModel mesRawPackageDetailModel = new MesRawPackageModel();
        //原材料容器明细
        MesRawPackageDetail packageDetail = getMesRawPackageDetail(mesRawPartChargingModel);
        //原材料容器
        mesRawPackageDetailModel.setMesRawPackage(getRawPackage(mesRawPartChargingModel, packageDetail));
        mesRawPackageDetailModel.setMesRawPackageDetail(packageDetail);
        //原材料容器零件关系表
        mesRawPackageDetailModel.setMesRawPackagePartList(getMesRawPackagePartList(mesRawPartChargingModel, packageDetail));
        mesRawPartChargingModel.setMesRawPackageModel(mesRawPackageDetailModel);
        return mesRawPartChargingModel;
    }

    @Override
    public MesRawPartChargingModel doAction(MesRawPartChargingModel mesRawPartChargingModel) {
        //10扫描原料条码 20提交 30初始化料筒
        switch (mesRawPartChargingModel.getType()) {
            case 10:
                doScanSn(mesRawPartChargingModel);
                break;
            case 20:
                doSubmit(mesRawPartChargingModel);
                break;
            case 30:
                doMesRawPartChargingInit(mesRawPartChargingModel);
                break;
            default:
                MesPcnException.throwMesBusiException("扫描类型【%s】不存在", mesRawPartChargingModel.getType());
                break;
        }
        return mesRawPartChargingModel;
    }

    public void doScanSn(MesRawPartChargingModel mesRawPartChargingModel) {
        //属性校验
        checkNotNull(mesRawPartChargingModel);
        ValidatorBean.checkNotNull(mesRawPartChargingModel.getMesRawPackagePart(), "原材料容器零件关系不能为空");
        ValidatorBean.checkNotNull(mesRawPartChargingModel.getSn(), "原料条码不能为空");
        //校验是否已扫描
        List<MesRawPartCharging> mesRawPartCharging = findMesRawPartCharging(mesRawPartChargingModel);
        if (!CollectionUtils.isEmpty(mesRawPartCharging)) {
            //已绑定，再次扫描料筒条码自动初始化
            doMesRawPartChargingInit(mesRawPartChargingModel);
        }
        if (Objects.isNull(MesExtEnumUtil.RAW_SCAN_TYPE.valueOfDescription(mesRawPartChargingModel.getMesRawPackagePart().getScanType()))) {
            MesPcnException.throwMesBusiException("料筒条码【%s】物料【%s】扫描类型信息不存在", mesRawPartChargingModel.getPackageSn(), mesRawPartChargingModel.getMesRawPackagePart().getPartNo());
        }
        //自制件
        if (MesExtEnumUtil.RAW_SCAN_TYPE.HOMEMADE_SN.getValue() == mesRawPartChargingModel.getMesRawPackagePart().getScanType()) {
            checkHomeMadeSn(mesRawPartChargingModel);
            //非自制件
        } else {
            checkHomeRuleSn(mesRawPartChargingModel);
        }
    }

    public void doSubmit(MesRawPartChargingModel mesRawPartChargingModel) {
        //属性校验
        checkNotNull(mesRawPartChargingModel);
        ValidatorBean.checkNotNull(mesRawPartChargingModel.getMesRawPackagePart(), "原材料容器零件关系不能为空");
        ValidatorBean.checkNotNull(mesRawPartChargingModel.getSn(), "原料条码不能为空");
//        ValidatorBean.checkNotNull(mesRawPartChargingModel.getLotNo(), "批次号不能为空");
        //校验是否已扫描
        List<MesRawPartCharging> mesRawPartCharging = findMesRawPartCharging(mesRawPartChargingModel);
        if (!CollectionUtils.isEmpty(mesRawPartCharging)) {
            MesPcnException.throwMesBusiException("料筒条码【%s】与原料条码【%s】已绑定", mesRawPartChargingModel.getPackageSn(), mesRawPartCharging.iterator().next().getSn());
        }
        //保存生产控制加料 43302 加料防错扫码流程优化
        String[] split = mesRawPartChargingModel.getSn().split(",");
        for (String sn : split) {
            mesRawPartChargingModel.setSn(sn);
            MesRawPartCharging charging = insertRawPartCharging(mesRawPartChargingModel);
            //保存日志
            saveLog(mesRawPartChargingModel, charging, MesExtEnumUtil.CHARGING_LOG_STATUS.FEEDING);
        }
    }


    public void doMesRawPartChargingInit(MesRawPartChargingModel mesRawPartChargingModel) {
        //属性校验
        checkNotNull(mesRawPartChargingModel);

        List<MesRawPartCharging> mesRawPartChargingList = findMesRawPartCharging(mesRawPartChargingModel);
        if(!CollectionUtils.isEmpty(mesRawPartChargingList)){
            for (MesRawPartCharging mesRawPartCharging : mesRawPartChargingList) {
                //删除绑定信息
                mesRawPartCharging.setIsDeleted(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
                ConvertBean.serviceModelUpdate(mesRawPartCharging,mesRawPartChargingModel.getUserName());
                mesRawPartChargingRepository.update(mesRawPartCharging);
                //保存日志
                saveLog(mesRawPartChargingModel, mesRawPartCharging, MesExtEnumUtil.CHARGING_LOG_STATUS.CLEAR);
            }
//            MesPcnException.throwMesBusiException("料筒条码【%s】未绑定，无需初始化", mesRawPartChargingModel.getPackageSn());
        }


    }

    private List<MesRawPackagePart> getMesRawPackagePartList(MesRawPartChargingModel mesRawPartChargingModel, MesRawPackageDetail packageDetail) {
        DdlPackBean packBean;
        packBean = DdlPackBean.getDdlPackBean(mesRawPartChargingModel.getOrganizeCode());
        DdlPreparedPack.getNumEqualPack(packageDetail.getId(), "packageDetailId", packBean);
        List<MesRawPackagePart> packagePartList = mesRawPackagePartRepository.findByHqlWhere(packBean);
        if (CollectionUtils.isEmpty(packagePartList)) {
            MesPcnException.throwMesBusiException("料筒条码【%s】原材料容器零件关系未维护", mesRawPartChargingModel.getPackageSn());
        }
        //查询物料名称
        Map<String, MesPartSap> partSapMap = getMesPartSapMap(mesRawPartChargingModel, packagePartList);
        for (MesRawPackagePart mesRawPackagePart : packagePartList) {
            if (!Objects.isNull(partSapMap) && partSapMap.containsKey(mesRawPackagePart.getPartNo())) {
                mesRawPackagePart.setPartName(partSapMap.get(mesRawPackagePart.getPartNo()).getPartName());
            }
        }
        return packagePartList;
    }

    private Map<String, MesPartSap> getMesPartSapMap(MesRawPartChargingModel mesRawPartChargingModel, List<MesRawPackagePart> packagePartList) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(mesRawPartChargingModel.getOrganizeCode());
        DdlPreparedPack.getInPackList(packagePartList.stream().map(MesRawPackagePart::getPartNo).collect(Collectors.toList()), "partNo", packBean);
        List<MesPartSap> partSapList = mesPartSapRDao.findByHqlWhere(packBean);
        Map<String, MesPartSap> partSapMap = null;
        if (!CollectionUtils.isEmpty(partSapList)) {
            partSapMap = partSapList.stream().collect(Collectors.toMap(MesPartSap::getPartNo, t -> t));
        }
        return partSapMap;
    }

    private MesRawPackage getRawPackage(MesRawPartChargingModel mesRawPartChargingModel, MesRawPackageDetail packageDetail) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(mesRawPartChargingModel.getOrganizeCode());
        DdlPreparedPack.getNumEqualPack(packageDetail.getPid(), "id", packBean);
        MesRawPackage mesRawPackage = mesRawPackageRepository.getByProperty(packBean);
        if (Objects.isNull(mesRawPackage)) {
            MesPcnException.throwMesBusiException("料筒条码【%s】信息不存在", mesRawPartChargingModel.getPackageSn());
        }
        return mesRawPackage;
    }

    private MesRawPackageDetail getMesRawPackageDetail(MesRawPartChargingModel mesRawPartChargingModel) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(mesRawPartChargingModel.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(mesRawPartChargingModel.getPackageSn(), "packageSn", packBean);
        MesRawPackageDetail packageDetail = mesRawPackageDetailRepository.getByProperty(packBean);
        if (Objects.isNull(packageDetail)) {
            MesPcnException.throwMesBusiException("料筒条码【%s】信息不存在", mesRawPartChargingModel.getPackageSn());
        }
        return packageDetail;
    }

    private List<MesRawPartCharging> findMesRawPartCharging(MesRawPartChargingModel mesRawPartChargingModel) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(mesRawPartChargingModel.getOrganizeCode());
        DdlPreparedPack.getNumEqualPack(mesRawPartChargingModel.getMesRawPackageModel().getMesRawPackageDetail().getId(), "packageDetailId", packBean);
        return mesRawPartChargingRepository.findByHqlWhere(packBean);
    }

    private void checkHomeMadeSn(MesRawPartChargingModel mesRawPartChargingModel) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(mesRawPartChargingModel.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(mesRawPartChargingModel.getSn(), "productSn", packBean);
        MesProduceSn produceSn = mesProduceSnRDao.getByProperty(packBean);
        if (Objects.isNull(produceSn)) {
            MesPcnException.throwMesBusiException("自制件条码【%s】信息不存在", mesRawPartChargingModel.getSn());
        }
        if (!mesRawPartChargingModel.getMesRawPackagePart().getPartNo().equals(produceSn.getPartNo())) {
            MesPcnException.throwMesBusiException("自制件条码【%s】物料【%s】与选择物料【%s】物料号不匹配", mesRawPartChargingModel.getSn(), produceSn.getPartNo(), mesRawPartChargingModel.getMesRawPackagePart().getPartNo());
        }
        mesRawPartChargingModel.setMesProduceSn(produceSn);
    }

    private void checkHomeRuleSn(MesRawPartChargingModel mesRawPartChargingModel) {
        if(!(Boolean) ((IMesNumberRuleMatchDispatchService) SpringContextsUtil.getBean(MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_20.getStrategyClass())).matchNumberRule(mesRawPartChargingModel.getOrganizeCode(), mesRawPartChargingModel.getSn(), mesRawPartChargingModel.getMesRawPackagePart().getBarcodeRule(), mesRawPartChargingModel.getMesRawPackagePart().getBarcodeRule()).get(MesPcnExtConstWords.RESULT)){
            MesPcnException.throwMesBusiException("原料条码【%s】校验条码规则【%s】失败", mesRawPartChargingModel.getSn(), mesRawPartChargingModel.getMesRawPackagePart().getBarcodeRule());
        }
    }

    private MesRawPartCharging insertRawPartCharging(MesRawPartChargingModel mesRawPartChargingModel) {
        MesRawPartCharging mesRawPartCharging = new MesRawPartCharging();
        mesRawPartCharging.setOrganizeCode(mesRawPartChargingModel.getOrganizeCode());
        mesRawPartCharging.setPackageDetailId(mesRawPartChargingModel.getMesRawPackageModel().getMesRawPackageDetail().getId());
        mesRawPartCharging.setParentPackageDetailId(mesRawPartChargingModel.getMesRawPackageModel().getMesRawPackageDetail().getId());
        mesRawPartCharging.setPackagePartId(mesRawPartChargingModel.getMesRawPackagePart().getId());
        mesRawPartCharging.setEquipmentCode(mesRawPartChargingModel.getMesRawPackageModel().getMesRawPackageDetail().getEquipCode());
        mesRawPartCharging.setPartNo(mesRawPartChargingModel.getMesRawPackagePart().getPartNo());
        mesRawPartCharging.setSn(mesRawPartChargingModel.getSn());
        mesRawPartCharging.setUnit(mesRawPartChargingModel.getMesRawPackagePart().getUnit());
        if (!Objects.isNull(mesRawPartChargingModel.getMesProduceSn())) {
            mesRawPartCharging.setQty(mesRawPartChargingModel.getMesProduceSn().getQty());
        } else {
            mesRawPartCharging.setQty(mesRawPartChargingModel.getMesRawPackagePart().getQty());
        }
        mesRawPartCharging.setLoadPartTime(TimeTool.getNowTime(true));
        mesRawPartCharging.setLotNo(StringUtils.isEmpty(mesRawPartChargingModel.getLotNo())?"":mesRawPartChargingModel.getLotNo());
        mesRawPartCharging.setParentPackageSn(mesRawPartChargingModel.getPackageSn());
        mesRawPartCharging.setPackageId(mesRawPartChargingModel.getMesRawPackageModel().getMesRawPackage().getId());
        mesRawPartCharging.setFid(UUID.randomUUID().toString());
        ConvertBean.serviceModelInitialize(mesRawPartCharging, mesRawPartChargingModel.getUserName());
        return mesRawPartChargingRepository.insert(mesRawPartCharging);
    }

    private void saveLog(MesRawPartChargingModel mesRawPartChargingModel, MesRawPartCharging charging, MesExtEnumUtil.CHARGING_LOG_STATUS status) {
        MesRawPartChargingLog mesRawPartChargingLog = new MesRawPartChargingLog();
        BeanUtils.copyProperties(charging, mesRawPartChargingLog,"id");
        mesRawPartChargingLog.setCharingId(charging.getId());
        mesRawPartChargingLog.setPackageSn(mesRawPartChargingModel.getPackageSn());
        mesRawPartChargingLog.setPackageName(mesRawPartChargingModel.getMesRawPackageModel().getMesRawPackage().getName());
        mesRawPartChargingLog.setStatus(status.getValue());
        ConvertBean.serviceModelInitialize(mesRawPartChargingLog,mesRawPartChargingModel.getUserName());
        mesRawPartChargingLogRepository.insert(mesRawPartChargingLog);
    }

    private void checkNotNull(MesRawPartChargingModel mesRawPartChargingModel) {
        ValidatorBean.checkNotNull(mesRawPartChargingModel.getPackageSn(), "料筒条码不能为空");
        ValidatorBean.checkNotNull(mesRawPartChargingModel.getMesRawPackageModel(), "原材料容器不能为空");
    }
}
