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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IPartExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IProdPackExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IPackageExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProductEncodeCfgExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.ISxNumberRulePackAttributeService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.bu.IOuterPackageSnService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesOuterPackageDetailRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesOuterPackageRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesWorkOrderExtRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import cn.estsh.i3plus.mes.pcn.api.iservice.busi.ISyncFuncService;
import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum;
import cn.estsh.i3plus.pojo.base.bean.BaseResultBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesPackageDetail;
import cn.estsh.i3plus.pojo.mes.model.GenSerialNoModel;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
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.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 大包装条码查询处理service
 */
@Slf4j
@Service
public class SxOuterPackageSnService implements IOuterPackageSnService {

    @Autowired
    MesOuterPackageDetailRepository mesOuterPackageDetailRepository;

    @Autowired
    private MesWorkOrderExtRepository workOrderExtRepository;

    @Autowired
    private IPartExtService partExtService;

    @Autowired
    private IProductEncodeCfgExtService productEncodeCfgExtService;

    @Autowired
    private ISxNumberRulePackAttributeService numberRulePackAttributeService;

    @Autowired
    private ISyncFuncService syncFuncService;

    @Autowired
    private IProdPackExtService prodPackExtService;

    @Autowired
    private MesOuterPackageRepository mesOuterPackageRepository;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private IPackageExtService packageExtService;

    /**
     * 根据小包装条码查询大包装条码表
     * @param organizeCode 组织代码
     * @param packageNo 小包装条码
     * @return
     */
    @Override
    public List<MesOuterPackageDetail> getOuterPackageDetailListByPackageNo(String organizeCode, String packageNo) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(packageNo)) {
            return null;
        }
        return mesOuterPackageDetailRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.BIND_STATUS,MesPcnExtConstWords.INNER_PACKAGENO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), MesPcnExtEnumUtil.PACKAGE_BIND_STATUS.BINGDING.getValue(),packageNo});
    }

    /**
     * 生成大包装条码
     * @param workOrderNo
     * @param organizeCode
     * @param userInfo
     */
    @Override
    public String doHandCreateOuterPackageSn(List<String> packageNoList,String workOrderNo, String organizeCode, String userInfo) {
        log.info("生成大包装条码开始,执行工单号[{}]", workOrderNo);
        MesWorkOrderExt workOrder = getWorkOrderByNo(workOrderNo, organizeCode);
        log.info("生成大包装条码开始,,执行工单号[{}]",workOrder.getOrderNo());
        MesPartExt partDb = partExtService.getPartExt(workOrder.getOrganizeCode(), workOrder.getPartNo());

        if(MesPcnExtEnumUtil.ENCODE_MATCH_TYPE.getByValue(partDb.getBigPackageMatchType()) == null){
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("请维护物料[%s]大包装条码匹配类型", partDb.getPartNo())
                    .build();
        }

        //doCheckWorkOrderIsExistSn(workOrder, partDb, userInfo);
        MesProdPackExt prodPackDb = getProdPack(organizeCode, workOrder.getOrderNo(), partDb.getPartNo(), partDb.getPptCode());
        log.info("手动生成条码通过工单及物料校验,工单号[{}]", workOrder.getOrderNo());

        String outerPackageNo = doHandCreateSn(organizeCode,packageNoList,workOrder, partDb, prodPackDb, userInfo);
        return outerPackageNo;
    }



    private MesWorkOrderExt getWorkOrderByNo(String workOrderNo, String organizeCode) {
        MesWorkOrderExt workOrder = workOrderExtRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,MesPcnExtConstWords.ORDER_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),workOrderNo});
        if (null == workOrder ||
                (CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue() == workOrder.getIsDeleted() ||
                        CommonEnumUtil.IS_VAILD.INVAILD.getValue() == workOrder.getIsValid())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("工单号[%s]数据无效", workOrderNo)
                    .build();
        }
        if (!organizeCode.equals(workOrder.getOrganizeCode())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("工单号[%s]不属于[%s]工厂", workOrderNo, organizeCode)
                    .build();
        }
        if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() == workOrder.getWorkOrderType()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("工单[%s]类型为[%s],不能生成条码",
                            workOrder.getOrderNo(), MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getDescription())
                    .build();
        }
        return workOrder;
    }

    private MesProdPackExt getProdPack(String organizeCode, String orderNo, String partNo, String pptCode) {
        MesProdPackExt prodPackDb = prodPackExtService.getProdPackExt(organizeCode, partNo, pptCode);
        if (null == prodPackDb || StringUtils.isEmpty(prodPackDb.getProcessLabelTemplate())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("工单[%s]关联的物料号[%s]未在产品包装关系中维护过程标签模板", orderNo, partNo)
                    .build();
        }
        return prodPackDb;
    }

    private String doHandCreateSn(String organizeCode,List<String> packageNoList,MesWorkOrderExt workOrder, MesPartExt partDb, MesProdPackExt prodPackDb, String userInfo) {
        Integer codeType = null;
        // 通过小包装查询得到包装详细信息和条码信息
        MesPackageDetail packageDetail = packageExtService.getPackageDetailByPackNo(organizeCode, packageNoList.get(0));
        // 通过小包装条码 查询出本体条码的信息
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, packageDetail.getSerialNumber());

        switch (MesPcnExtEnumUtil.WORK_ORDER_TYPE.getByValue(workOrder.getWorkOrderType())) {
            // 试制工单类型
            case ATTEMPT_ORDER:
                codeType = MesPcnExtEnumUtil.ENCODE_CODE_TYPE.BIG_PACK_ATTEMPT_SN.getValue();
                break;
            // 正常工单类型
            case STANDARD_ORDER:
                // 通过条码类型来判断
               if(produceSnExt.getSnType() == MesPcnExtEnumUtil.PRODUCE_SN_TYPE.STANDARD_SN.getValue()){
                   codeType = MesPcnExtEnumUtil.ENCODE_CODE_TYPE.BIG_PACK_SN.getValue();
               }else if(produceSnExt.getSnType() == MesPcnExtEnumUtil.PRODUCE_SN_TYPE.REMAKE_SN.getValue()) {
                   codeType = MesPcnExtEnumUtil.ENCODE_CODE_TYPE.BIG_PACK_REWORK_SN.getValue();
               }
                break;
            default:
                break;
        }
        // 条码类型默认为大包装条码类型
        log.info("大包装条码开始创建[{}],执行工单ID[{}],工单号[{}]", MesPcnExtEnumUtil.ENCODE_CODE_TYPE.valueOfDescription(codeType), workOrder.getId(), workOrder.getOrderNo());
        String ruleCode = productEncodeCfgExtService.getRuleCodeByMatchType(workOrder.getOrganizeCode(), codeType, partDb, workOrder.getWorkCenterCode());
        Map<String, Object> map = new HashMap<>();
        map.put(MesPcnExtConstWords.ORGANIZE_CODE, workOrder.getOrganizeCode());
        map.put(MesPcnExtConstWords.RULE_CODE, ruleCode);
        map.put(MesPcnExtConstWords.PART_EXT, partDb);
        map.put(MesPcnExtConstWords.START_TIME, workOrder.getStartTime());
        GenSerialNoModel genSerialNoModel = numberRulePackAttributeService.doPackGenSerialNoModel(map);

        if (null == genSerialNoModel) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("工单[%s]编码规则封装入参属性失败", workOrder.getOrderNo())
                    .build();
        }

        log.info("大包装条码正在生成[{}]条码,数量[{}],执行工单ID[{}],工单号[{}]", MesPcnExtEnumUtil.ENCODE_CODE_TYPE.valueOfDescription(codeType), 1, workOrder.getId(), workOrder.getOrderNo());
        BaseResultBean<String> resultBean = syncFuncService.syncSerialNo(genSerialNoModel, userInfo, workOrder.getOrganizeCode(), 1);


        if (resultBean != null && resultBean.isSuccess()) {
             log.info("大包装条码生成[{}]条码成功,数量[{}],执行工单ID[{}],工单号[{}]", MesPcnExtEnumUtil.ENCODE_CODE_TYPE.valueOfDescription(codeType), 1, workOrder.getId(), workOrder.getOrderNo());
            if (CollectionUtils.isEmpty(resultBean.getResultList())) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("工单[%s]批量生成大包装条码时没有返回过程条码集合,操作失败", workOrder.getOrderNo())
                        .build();
            }
            if (StringUtils.isEmpty(resultBean.getResultList().get(0))) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("物料[%S]关联生产编码规则错误,请重新设置", workOrder.getPartNo())
                        .build();
            }
            // 返回生成好的大包装条码
            return resultBean.getResultList().get(0);
        } else {
            log.error("生成大包装条码生成[{}]条码失败,执行工单ID[{}],工单号[{}]", MesPcnExtEnumUtil.ENCODE_CODE_TYPE.valueOfDescription(codeType), workOrder.getId(), workOrder.getOrderNo());
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("工单[%s]生成大包装条码失败", workOrder.getOrderNo())
                    .build();
        }
    }

    @Override
    public List<MesOuterPackage> getOuterPackageListByPackageNo(String organizeCode, String packageNo) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(packageNo)) {
            return null;
        }
        return mesOuterPackageRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,MesPcnExtConstWords.OUTER_PACKAGE_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), packageNo});
    }

    @Override
    public List<MesOuterPackageDetail> getOuterPackageDetailListByOuterPackageNo(String organizeCode, String outerPackageNo) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(outerPackageNo)) {
            return null;
        }
        return mesOuterPackageDetailRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,MesPcnExtConstWords.BIND_STATUS,MesPcnExtConstWords.OUTER_PACKAGE_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), MesPcnExtEnumUtil.PACKAGE_BIND_STATUS.BINGDING.getValue(),outerPackageNo});
    }

    @Override
    public List<MesOuterPackageDetail> getOuterPackageDetailListByWorkOrderNo(String organizeCode, String workOrderNo) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(workOrderNo)) {
            return null;
        }
        return mesOuterPackageDetailRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,MesPcnExtConstWords.WORK_ORDER_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),workOrderNo});
    }

}
