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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionRecordService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesTimeEfficientCfgMatchService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesTimeEfficientCfgService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesContainerPackageDetailContext;
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.MesProductionRecord;
import cn.estsh.i3plus.pojo.mes.bean.MesTimeEfficientCfg;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MesTimeEfficientCfgMatchService implements IMesTimeEfficientCfgMatchService {

    @Autowired
    private IMesTimeEfficientCfgService timeEfficientCfgService;

    @Autowired
    private IMesProductionRecordService productionRecordService;

    @Autowired
    private IMesProduceSnExtService produceSnExtService;

    /**
     * 逻辑:
     * 0.根据加工规则可以查询 主条码时效性规则
     * 1.校验主条码时效性
     *      1.1 查询条码的所有加工记录，条件 条码相等且工序不相等; 没有不需要校验，直接返回true
     *      1.2 如果有前道工序,遍历时效性规则
     *         1.2.1 如果维护了零件号，则需要首先匹配零件号 相等，然后校验时间 和 时效性规则
     *         1.2.2 如果维护了工序，则需要校验生产记录中当前工序的主条码生成时间 与 时效性校验
     * 2.主条码装配件校验
     *   2.1 首先校验主条码规则--同上
     *   2.2 查找主条码的装配件条码（在装配件记录表中）
     *   2.3 遍历获取道的装配件条码, 去校验装配件 的时效性，有零件 和 工序 两种情况
     *
     *         可以根据如下timeDataSource + sourceId 可以查询 MES_TIME_EFFICIENT_CFG 需要校验的 时效性规则
     *         DATA_SOURCE10(10, "排序加工规则"),
     *         DATA_SOURCE20(20, "非排序加工规则"),
     *         DATA_SOURCE30(30, "非排序装配件");
     * 排除未知的零件号生产记录
     * @param productSn 条码 用于查询生产加工记录
     * @param sourceId 用于获取时效性记录
     * @param organizeCode
     * @return
     */
    @Override
    public Map<String, Object> checkSnTimeliness(String organizeCode, String productSn, Long sourceId, Integer dataSource) {

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put(MesPcnExtConstWords.RESULT, true);//校验成功

        try {

            //1.根据prodRuleNoSortId 获取 非排序加工规则的 时效性数据  --- 当前的条码需要完全匹配查询的规则
            List<MesTimeEfficientCfg> timelinessList = timeEfficientCfgService.getTimeEfficientCfgList(organizeCode, sourceId);

            //2.如果timelinessList为空 且 非装配件校验 直接返回true
            if (CollectionUtils.isEmpty(timelinessList)) return resultMap;

            //3.根据条码获取生产加工记录结果
            List<MesProductionRecord> productionRecordList = null;
            Optional<MesTimeEfficientCfg> optional = timelinessList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getCraftCode()))).findFirst();
            if (null != optional && optional.isPresent()) {
                productionRecordList = productionRecordService.findProductionRecordList(organizeCode, productSn);
                if (CollectionUtils.isEmpty(productionRecordList)) return backResultMap(resultMap, String.format("零件条码[%s]时效性验证失败,未查询到加工记录信息!", productSn));
            }

            List<MesProduceSn> produceSnList = null;
            optional = timelinessList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getCraftCode()))).findFirst();
            if (null != optional && optional.isPresent()) {
                produceSnList = produceSnExtService.getProduceSnList(organizeCode, productSn);
                if (CollectionUtils.isEmpty(produceSnList)) return backResultMap(resultMap, String.format("零件条码[%s]时效性验证失败,未查询到零件条码信息!", productSn));
            }

            Date now = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT);
            for (MesTimeEfficientCfg timeliness : timelinessList) {

                if (null == timeliness || (StringUtils.isEmpty(timeliness.getPartNo()) && StringUtils.isEmpty(timeliness.getCraftCode()))) continue;

                List<Object> filterList;
                //时效性规则 零件号不为空或者为空 过滤数据
                if (!StringUtils.isEmpty(timeliness.getPartNo()) && !StringUtils.isEmpty(timeliness.getCraftCode()))
                    filterList = productionRecordList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPartNo()) && !StringUtils.isEmpty(o.getCraftCode()) && !StringUtils.isEmpty(o.getCreateDatetime())
                            && o.getPartNo().toUpperCase().equals(timeliness.getPartNo().toUpperCase()) && o.getCraftCode().toUpperCase().equals(timeliness.getCraftCode().toUpperCase())))
                            .sorted(Comparator.comparing(MesProductionRecord::getCreateDatetime).reversed()).collect(Collectors.toList());
                else if (!StringUtils.isEmpty(timeliness.getCraftCode()))
                    filterList = productionRecordList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getCraftCode()) && !StringUtils.isEmpty(o.getCreateDatetime())
                            && o.getCraftCode().toUpperCase().equals(timeliness.getCraftCode().toUpperCase())))
                            .sorted(Comparator.comparing(MesProductionRecord::getCreateDatetime).reversed()).collect(Collectors.toList());
                else
                    filterList = produceSnList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPartNo()) && !StringUtils.isEmpty(o.getCreateDatetime())
                            && o.getPartNo().toUpperCase().equals(timeliness.getPartNo().toUpperCase())))
                            .sorted(Comparator.comparing(MesProduceSn::getCreateDatetime).reversed()).collect(Collectors.toList());

                if (CollectionUtils.isEmpty(filterList)) return backResultMap(resultMap, String.format("零件条码[%s]时效性零件号[%s]工艺[%s]验证失败,未查询到%s!",
                        productSn, timeliness.getPartNo(), !StringUtils.isEmpty(timeliness.getCraftCode()) ? timeliness.getCraftCode() : MesPcnExtConstWords.EMPTY, !StringUtils.isEmpty(timeliness.getCraftCode()) ? "加工记录信息" : "零件条码信息"));

                //不为空 则 需要校验时效性
                String completeDateTime = !StringUtils.isEmpty(timeliness.getCraftCode()) ? ((MesProductionRecord) filterList.get(0)).getCompleteDateTime() : ((MesProduceSn) filterList.get(0)).getCreateDatetime();
                Date productDateTime = sdf.parse(completeDateTime);
                //时差
                int minDiff = (int) ((now.getTime() - productDateTime.getTime())/(60 * 1000));
                if (!checkTimeliness(timeliness, minDiff)) return backResultMap(resultMap, String.format("零件条码[%s]时效性零件号[%s]工艺[%s]验证失败!",
                        productSn, timeliness.getPartNo(), !StringUtils.isEmpty(timeliness.getCraftCode()) ? timeliness.getCraftCode() : MesPcnExtConstWords.EMPTY));
            }

            return resultMap;

        } catch (Exception e) {
            return backResultMap(resultMap, String.format("零件条码[%s]时效性验证异常:%s!", productSn, e.toString()));
        }

    }

    private Map<String, Object> backResultMap(Map<String, Object> resultMap, String message) {
        resultMap.put(MesPcnExtConstWords.RESULT, false);
        resultMap.put(MesPcnExtConstWords.MESSAGE, message);
        return resultMap;
    }

    /**
     *         MATCH_RULE_10("10", "生产时间小于装配件有效期"),
     *         MATCH_RULE_20("20", "小于最小时差有效"),
     *         MATCH_RULE_30("30", "大于最大时差有效"),
     *         MATCH_RULE_40("40", "最大最小时差有效"),
     *         MATCH_RULE_50("50", "最大外或最小内有效");
     * 用于校验主条码时效性
     * 加工记录 和 时效性校验
     *
     * 时效性规则 零件号可以为空 、工艺一定不为空
     * @param
     * @return
     */
    private boolean checkTimeliness(MesTimeEfficientCfg timeliness, int minDiff) {
        String matchRule = timeliness.getMatchRule();
        Double minValue = timeliness.getMinValue();
        Double maxValue = timeliness.getMaxValue();
        if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_20.getValue().equals(matchRule)) {
            //差值  小于最小时差有效
            if (minDiff >= minValue){
                return false;
            }
        } else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_30.getValue().equals(matchRule)) {
            // 差值 大于最大时差有效
            if (minDiff <=  maxValue){
                return false;
            }
        } else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_40.getValue().equals(matchRule)) {
            // 差值  最大最小时差有效  在 最大值 最小值之间
            if (minDiff <= minValue || minDiff >= maxValue){
                return false;
            }
        } else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_50.getValue().equals(matchRule)) {
            // 差值 最大外或最小内有效
            if (minDiff >= minValue && minDiff <= maxValue){
                return false;
            }
        }

        return true;
    }

    public static void main(String[] args) {
        try {
            Double minValue = 1d;
            Double maxValue = 240d;
            SimpleDateFormat sdf = new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT);
//            Date now = new Date();
            Date now = sdf.parse("2025-03-21 11:19:06");
            Date productDateTime = sdf.parse("2025-03-21 11:15:06");
            int minDiff = (int) ((now.getTime() - productDateTime.getTime())/(60 * 1000));
            Integer matchRule = 40;
            if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_20.getValue().equals(matchRule)) {
                //差值  小于最小时差有效
                if (minDiff >= minValue){
                    System.out.println(false);
                }
            } else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_30.getValue().equals(matchRule)) {
                // 差值 大于最大时差有效
                if (minDiff <=  maxValue){
                    System.out.println(false);
                }
            } else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_40.getValue().equals(matchRule)) {
                // 差值  最大最小时差有效  在 最大值 最小值之间
                if (minDiff <= minValue || minDiff >= maxValue){
                    System.out.println(false);
                }
            } else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_50.getValue().equals(matchRule)) {
                // 差值 最大外或最小内有效
                if (minDiff >= minValue && minDiff <= maxValue){
                    System.out.println(false);
                }
            }
            System.out.println("执行完成");
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Map<String, Object> checkSnTimelinessContainerMatch(String organizeCode, MesContainerPackageDetailContext containerPackageDetailContext, Long sourceId) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put(MesPcnExtConstWords.RESULT, true);//校验成功

        try {

            //1.根据prodRuleNoSortId 获取 非排序加工规则的 时效性数据  --- 当前的条码需要完全匹配查询的规则
            List<MesTimeEfficientCfg> timelinessList = timeEfficientCfgService.getTimeEfficientCfgList(organizeCode, sourceId);

            //2.如果timelinessList为空 且 非装配件校验 直接返回true
            if (CollectionUtils.isEmpty(timelinessList)) return resultMap;

            Date now = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT);
            for (MesTimeEfficientCfg timeliness : timelinessList) {

                if (null == timeliness || StringUtils.isEmpty(timeliness.getPartNo()) || !timeliness.getPartNo().equals(containerPackageDetailContext.getPartNo())) continue;

                Date productDateTime = sdf.parse(containerPackageDetailContext.getCreateDatetime());
                //时差
                int minDiff = (int) ((now.getTime() - productDateTime.getTime())/(60 * 1000));
                if (!checkTimeliness(timeliness, minDiff)) return backResultMap(resultMap, String.format("原材料条码[%s]时效性零件号[%s]验证失败!", containerPackageDetailContext.getBarCode(), timeliness.getPartNo()));
            }

            return resultMap;

        } catch (Exception e) {
            return backResultMap(resultMap, String.format("原材料条码[%s]时效性验证异常:%s!", containerPackageDetailContext.getBarCode(), e.toString()));
        }
    }

}
