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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesAssemblyExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesNumberRuleMatchDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionAssemblyContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionAssemblySortContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.pojo.mes.bean.MesProduceSn;
import cn.estsh.i3plus.pojo.mes.bean.MesProductionAssembly;
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.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

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

/**
 * 装配件二次确认 【排序】
 */
@Slf4j
@Service
public class MesNumberRuleMatchSortDoubleCheckService implements IMesNumberRuleMatchDispatchService {

    @Autowired
    private IMesProduceSnExtService produceSnExtService;

    @Autowired
    private IMesAssemblyExtService assemblyExtService;

    @Override
    public Map<String, Object> matchNumberRule(String organizeCode, String sn, Object... params) {

        Map<String, Object> result = new HashMap<>();
        result.put(MesPcnExtConstWords.RESULT, true);

        if (!MesProductionAssemblySortContext.class.isAssignableFrom(params[0].getClass())) {
            result.put(MesPcnExtConstWords.RESULT, false);
            result.put(MesPcnExtConstWords.MESSAGE, "参数匹配规则信息不是排序线装配件匹配规则!");
            return result;
        }

        MesProductionAssemblySortContext context =  (MesProductionAssemblySortContext) params[0];

        if (StringUtils.isEmpty(context.getMatchRule()) && StringUtils.isEmpty(context.getAssemblyPartNo())) {
            result.put(MesPcnExtConstWords.RESULT, false);
            result.put(MesPcnExtConstWords.MESSAGE, "参数匹配规则信息未维护[扫描规则]或[装配件零件编码]!");
            return result;
        }

        //校验正则表达式
        if (!StringUtils.isEmpty(context.getMatchRule())) {
            result = ((IMesNumberRuleMatchDispatchService) SpringContextsUtil.getBean(MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.MATCH_TYPE_20.getStrategyClass())).matchNumberRule(organizeCode, sn, params);
            if (!(Boolean) result.get(MesPcnExtConstWords.RESULT)) return result;
        }

        result.put(MesPcnExtConstWords.RESULT, false);

        //验证零件号
        if (!StringUtils.isEmpty(context.getAssemblyPartNo())) {

            List<MesProduceSn> produceSnList = produceSnExtService.getProduceSnList(organizeCode, sn);
            if (CollectionUtils.isEmpty(produceSnList)) {
                result.put(MesPcnExtConstWords.MESSAGE, String.format("零件条码[%s]信息不存在!", sn));
                return result;
            }

            List<MesProduceSn> standardList = produceSnList.stream()
                    .filter(o -> (null != o && !StringUtils.isEmpty(o.getSnStatus()) && o.getSnStatus().compareTo(MesExtEnumUtil.PRODUCE_SN_STATUS.UNKNOW.getValue()) != 0))
                    .sorted(Comparator.comparing(MesProduceSn::getCreateDatetime).reversed()).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(standardList)) {
                result.put(MesPcnExtConstWords.MESSAGE, String.format("零件条码[%s]信息状态[未知]!", sn));
                return result;
            }

            MesProduceSn produceSn = standardList.get(0);
            if (StringUtils.isEmpty(produceSn.getSnStatus()) || StringUtils.isEmpty(produceSn.getQcStatus()) || StringUtils.isEmpty(produceSn.getPartNo())) {
                result.put(MesPcnExtConstWords.MESSAGE, String.format("零件条码[%s]信息异常:状态[%s]质量[%s]零件号[%s]!", sn, produceSn.getSnStatus(), produceSn.getQcStatus(), produceSn.getPartNo()));
                return result;
            }

            if (produceSn.getQcStatus().compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue()) != 0 && produceSn.getQcStatus().compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SUSPICIOUS_TO_QUALIFIED.getValue()) != 0) {
                result.put(MesPcnExtConstWords.MESSAGE, String.format("零件条码[%s]信息质量状态[%s]!", sn, MesExtEnumUtil.PRODUCE_QC_STATUS.valueOfDescription(produceSn.getQcStatus())));
                return result;
            }

            if (!context.getAssemblyPartNo().toUpperCase().equals(produceSn.getPartNo().toUpperCase())) {
                result.put(MesPcnExtConstWords.MESSAGE, String.format("零件条码[%s]信息零件号[%s]!", sn, produceSn.getPartNo()));
                return result;
            }

            //非已装配情况下
            if (MesExtEnumUtil.PRODUCE_SN_STATUS.ASSEMBLY.getValue() != produceSn.getSnStatus()) {
                //创建/已完成/已拆解都可以被装配
                if (MesExtEnumUtil.PRODUCE_SN_STATUS.checkAllowAssembly(produceSn.getSnStatus())) {
                    ((MesProductionAssemblyContext) params[0]).setProductSnId(produceSn.getId());
                    result.put(MesPcnExtConstWords.RESULT, true);
                    return result;
                } else {
                    result.put(MesPcnExtConstWords.MESSAGE, String.format("零件条码[%s]信息条码状态[%s]!", sn, MesExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(produceSn.getSnStatus())));
                    return result;
                }
            }

        }

        //已装配状态或者外协件情况下 --- 自制件:验证绑定的条码是否等于当前工单   外协件:验证绑定的条码是否是当前工单 或者 没有绑定记录
        List<MesProductionAssembly> productionAssemblyList = assemblyExtService.getProductionAssemblyList(organizeCode, sn);

        Optional<MesProductionAssembly> optional = CollectionUtils.isEmpty(productionAssemblyList) ? null :
                productionAssemblyList.stream().filter(o -> (null != o && o.getAssemblyStatus().compareTo(MesExtEnumUtil.ASSEMBLY_STATUS.ASSEMBLY_STATUS_10.getValue()) == 0)).findFirst();
        if (null != optional && optional.isPresent() && !optional.get().getProductSn().toUpperCase().equals(context.getWorkOrderNo().toUpperCase())) {
            result.put(MesPcnExtConstWords.MESSAGE, String.format("装配件条码[%s]已被加工单[%s]装配!", sn, optional.get().getProductSn()));
            return result;
        }

        result.put(MesPcnExtConstWords.RESULT, true);

        return result;
    }
}
