/*
 * Author: wangjian
 * 生成ServiceImpl
 */
package com.tofly.watermeter.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.common.core.util.StringUtil;
import com.tofly.watermeter.config.ComConstans;
import com.tofly.watermeter.config.ForeignConfig;
import com.tofly.watermeter.custom.dto.ForeignReadFarDo;
import com.tofly.watermeter.custom.dto.ReadFarDo;
import com.tofly.watermeter.custom.entity.enums.CbfsEnum;
import com.tofly.watermeter.custom.entity.enums.ReadData;
import com.tofly.watermeter.custom.util.SnowflakeUtils;
import com.tofly.watermeter.em.AbnormalEnum;
import com.tofly.watermeter.entity.Readabnormal;
import com.tofly.watermeter.entity.Readmetereashis;
import com.tofly.watermeter.mapper.ReadmetereashisMapper;
import com.tofly.watermeter.service.ReadabnormalService;
import com.tofly.watermeter.service.ReadmetereashisService;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 抄表历史数据（有本系统自己管理的）
 *
 * @author xqf
 * @date Tue Dec 28 00:00:00 CST 2021
 */
@Service("readmetereashisService")
@AllArgsConstructor
public class ReadmetereashisServiceImpl extends ServiceImpl<ReadmetereashisMapper, Readmetereashis> implements ReadmetereashisService {

    private final ReadabnormalService readabnormalService;

    private final ForeignConfig foreignConfig;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatchReadFar(ForeignReadFarDo dto) {
        List<Readmetereashis> lists = new ArrayList<>();
        List<ReadFarDo> datas = dto.getDatas();

        if (!datas.isEmpty()) {
            String months = datas.stream().filter(Objects::nonNull).map(ReadFarDo::getCbyf).collect(Collectors.joining(","));
            List<ReadFarDo> readInfo = baseMapper.readmetereashisInfo(months);

            List<ReadFarDo> infoList = datas.stream().filter(Objects::nonNull).filter(r -> !readInfo.contains(r)).collect(Collectors.toList());

            for (ReadFarDo farDo : infoList) {
//            for (ReadFarDo farDo : datas) {
                String yhbh = farDo.getYhbh();
                String cbyf = farDo.getCbyf();
                Readmetereashis readmetereashis = new Readmetereashis();
                BeanUtils.copyProperties(farDo, readmetereashis);
                readmetereashis.setSoleSign(SnowflakeUtils.getId(foreignConfig.getDate(), foreignConfig.getWorkerId(), ComConstans.SNOWFLAKE_READ_TYPE).toString());
                readmetereashis.setBcjjl(farDo.getBczl());
                readmetereashis.setCbsl(farDo.getBczl());
                readmetereashis.setMonth1(baseMapper.getLastWaterVal(yhbh, cbyf, -1L));
                readmetereashis.setMonth2(baseMapper.getLastWaterVal(yhbh, cbyf, -2L));
                readmetereashis.setMonth3(baseMapper.getLastWaterVal(yhbh, cbyf, -3L));
                Map number = baseMapper.getNumber(yhbh, cbyf, -1L);
                if (number != null && !number.isEmpty()) {
                    readmetereashis.setContinuityUp(Integer.parseInt(number.get("up").toString()));
                    readmetereashis.setContinuityDown(Integer.parseInt(number.get("down").toString()));
                    readmetereashis.setContinuityEqual(Integer.parseInt(number.get("equal").toString()));
                    readmetereashis.setZeroCount(Integer.parseInt(number.get("zero").toString()));
                }
                readmetereashis.setCbfsCode(CbfsEnum.SC.getCbfsId());
                readmetereashis.setIsGeneral("2");
                lists.add(readmetereashis);
            }
            this.saveBatch(lists);
            handleData(lists);
        }
        return true;
    }

    private void handleData(List<Readmetereashis> list) {


        for (Readmetereashis his : list) {
            Long bcsl = his.getBcjjl();
            String yhbh = his.getYhbh();
            String cbyf = his.getCbyf();

            //后期新增的用唯一标识查询，同时可以在数据库添加一个唯一索引（暂未添加）；查询抄表用户信息
            Readmetereashis readmeterhis = getOne(Wrappers.<Readmetereashis>lambdaQuery()
                    .eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf));

            Integer continuityUp = readmeterhis.getContinuityUp();
            Integer continuityDown = readmeterhis.getContinuityDown();
            Integer continuityEqual = readmeterhis.getContinuityEqual();
            Integer zeroCount1 = readmeterhis.getZeroCount();
            //上次抄表水量
            Long lastCbsl = baseMapper.getLastWaterVal(yhbh, cbyf, -1L);
            //升降水量
            readmeterhis.setSjsl(bcsl);
            readmeterhis.setIsfirst("1");
            //只要没有上次读数，则表示第一次抄表
            if (StringUtil.isNotNull(lastCbsl)) {
                readmeterhis.setSjsl(bcsl - lastCbsl);
                readmeterhis.setIsfirst("0");
                //比较本次抄表水量与上一次抄表水量
                int compareTo = bcsl.compareTo(lastCbsl);
                //如果有上一次记录（0水量次数、水量连续上升/下降/相同次数）的情况
                //本次上升
                if (compareTo > 0) {
                    readmeterhis.setContinuityUp(continuityUp + 1);
                }
                //本次下降
                else if (compareTo < 0) {
                    readmeterhis.setContinuityDown(continuityDown + 1);
                }
                //本次相同
                else {
                    readmeterhis.setContinuityEqual(continuityEqual + 1);
                }
            }
            //0水量
            if (bcsl.equals(0L)) {
                readmeterhis.setZeroCount(zeroCount1 + 1);
            }
            update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                    .set(Readmetereashis::getIsfirst, readmeterhis.getIsfirst())
                    .set(Readmetereashis::getContinuityUp, readmeterhis.getContinuityUp())
                    .set(Readmetereashis::getContinuityDown, readmeterhis.getContinuityDown())
                    .set(Readmetereashis::getContinuityEqual, readmeterhis.getContinuityEqual())
                    .set(Readmetereashis::getSjsl, readmeterhis.getSjsl()));
            abnormalReadDataCheck(readmeterhis);
        }
    }

    public void abnormalReadDataCheck(Readmetereashis his) {
        Integer zeroCount = his.getZeroCount();
        Integer upCount = his.getContinuityUp();
        java.lang.Integer downCount = his.getContinuityDown();
        java.lang.Integer equalCount = his.getContinuityEqual();
        String isFirst = his.getIsfirst();
        Long yearonyear1 = his.getYearonyear1();
        Long yearonyear2 = his.getYearonyear2();
        Long yearonyear3 = his.getYearonyear3();
        String ysxz = his.getYsxz();
        //本次增量让APP端传递，要不然又要去走一次数据库查询上次读数再相减
        Long bczl = his.getBcjjl();
        String sbkj = his.getSbkj();
        String yhbh = his.getYhbh();
        String cbyf = his.getCbyf();
        Long cbfsCode = his.getCbfsCode();
        //估水、换表、首次查抄均默认配置
        //估水模型
        if (cbfsCode.equals(CbfsEnum.GC.getCbfsId())) {
            //说明
            String describe = "估水信息模型：因各种原因进行估水方式抄表";
            //修改抄表类型原因
            Long typeId = AbnormalEnum.GSMX.getTypeId();
            update(Wrappers.<Readmetereashis>lambdaUpdate()
                    .eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                    .set(Readmetereashis::getAbnomalId, typeId)
                    .set(Readmetereashis::getShbz, "0")
                    .set(Readmetereashis::getAuditReason, describe));
        }
        //换表模型
        if (cbfsCode.equals(CbfsEnum.BMDZJHB.getCbfsId()) || cbfsCode.equals(CbfsEnum.ZCZJHB.getCbfsId()) || cbfsCode.equals(CbfsEnum.YHBRQGZHB.getCbfsId()) || cbfsCode.equals(CbfsEnum.WHBRQGZHB.getCbfsId())) {
            //说明
            String describe = "换表信息模型：在上次抄表后，本次抄表前，水表进行了更换操作";
            //修改抄表类型原因
            Long typeId = AbnormalEnum.HBMX.getTypeId();
            update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                    .set(Readmetereashis::getAbnomalId, typeId)
                    .set(Readmetereashis::getShbz, "0")
                    .set(Readmetereashis::getAuditReason, describe));
        }
        //首次查抄水量
        if ("1".equals(isFirst)) {
            Long typeId = AbnormalEnum.SCSLMX.getTypeId();
            //首次抄表水量为0
            if (!bczl.equals(0L)) {

                if (!cbfsCode.equals(66L)) {
                    String describe = "首次水量模型：首次非正常抄表方式";
                    //修改抄表类型原因
                    update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                            .set(Readmetereashis::getAbnomalId, typeId)
                            .set(Readmetereashis::getShbz, "0")
                            .set(Readmetereashis::getAuditReason, describe));
                }
            }
        }
        //前三次水量数据
        BigDecimal month1 = null;
        if (StringUtil.isNotNull(his.getMonth1())) {
            month1 = new BigDecimal(his.getMonth1());
        }
        BigDecimal month2 = null;
        if (StringUtil.isNotNull(his.getMonth2())) {
            month2 = new BigDecimal(his.getMonth2());
        }
        BigDecimal month3 = null;
        if (StringUtil.isNotNull(his.getMonth3())) {
            month3 = new BigDecimal(his.getMonth3());
        }

        //0水量模型
        Readabnormal readabnormal = readabnormalService.getOne(Wrappers.<Readabnormal>lambdaQuery().isNotNull(Readabnormal::getCount)
                .eq(Readabnormal::getTypeCode, AbnormalEnum.LSLMX.getTypeCode()).eq(Readabnormal::getYsxzBm, ysxz)
                .eq(Readabnormal::getSbkjBm, sbkj));
        if (StringUtil.isNotNull(readabnormal)) {
            String describe = readabnormal.getDescribe();
            Integer count = readabnormal.getCount();
            if (zeroCount > count) {
                //修改抄表类型原因
                Long typeId = readabnormal.getType();
                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                        .set(Readmetereashis::getAbnomalId, typeId)
                        .set(Readmetereashis::getShbz, "0")
                        .set(Readmetereashis::getAuditReason, describe + "，现有：" + zeroCount + "次0水量抄表"));
            }
        }
        //水量上升
        readabnormal = readabnormalService.getOne(Wrappers.<Readabnormal>lambdaQuery().isNotNull(Readabnormal::getCount)
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj)
                .eq(Readabnormal::getTypeCode, AbnormalEnum.SLLXSSMX.getTypeCode()));
        if (StringUtil.isNotNull(readabnormal)) {
            String describe = readabnormal.getDescribe();
            Integer count = readabnormal.getCount();
            if (upCount >= count) {
                //修改抄表类型原因
                Long typeId = readabnormal.getType();
                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                        .set(Readmetereashis::getAbnomalId, typeId)
                        .set(Readmetereashis::getShbz, "0")
                        .set(Readmetereashis::getAuditReason, describe + "，现有：" + upCount + "次连续上升水量"));
            }
        }
        //水量下降
        readabnormal = readabnormalService.getOne(Wrappers.<Readabnormal>lambdaQuery().isNotNull(Readabnormal::getCount)
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj)
                .eq(Readabnormal::getTypeCode, AbnormalEnum.SLLXXJMX.getTypeCode()));
        if (StringUtil.isNotNull(readabnormal)) {
            String describe = readabnormal.getDescribe();
            Integer count = readabnormal.getCount();
            if (downCount >= count) {
                //修改抄表类型原因
                Long typeId = readabnormal.getType();
                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                        .set(Readmetereashis::getAbnomalId, typeId)
                        .set(Readmetereashis::getShbz, "0")
                        .set(Readmetereashis::getAuditReason, describe + "，现有：" + downCount + "次连续下降水量"));
            }
        }
        //水量相同，水量相同排除0水量情况
        if (!bczl.equals(0L)) {
            readabnormal = readabnormalService.getOne(Wrappers.<Readabnormal>lambdaQuery().isNotNull(Readabnormal::getCount)
                    .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj)
                    .eq(Readabnormal::getTypeCode, AbnormalEnum.LXSLXTMX.getTypeCode()));
            if (StringUtil.isNotNull(readabnormal)) {
                String describe = readabnormal.getDescribe();
                Integer count = readabnormal.getCount();
                if (equalCount >= count) {
                    //修改抄表类型原因
                    Long typeId = readabnormal.getType();
                    update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                            .set(Readmetereashis::getAbnomalId, typeId)
                            .set(Readmetereashis::getShbz, "0")
                            .set(Readmetereashis::getAuditReason, describe + "，现有：" + equalCount + "次水量相同"));
                }
            }
        }
        BigDecimal bigBcsl = new BigDecimal(bczl);
        List<Readabnormal> readabnormalList;
        //水量突降模型
        readabnormalList = readabnormalService.list(Wrappers.<Readabnormal>lambdaQuery()
                .and(v -> v.eq(Readabnormal::getTypeCode, AbnormalEnum.SLTJMX.getTypeCode())
                        .or().eq(Readabnormal::getTypeCode, AbnormalEnum.SLTSMX.getTypeCode()))
                .isNotNull(Readabnormal::getMinAverageValue).isNotNull(Readabnormal::getRatio)
                .eq(Readabnormal::getYsxzBm, ysxz)
                .eq(Readabnormal::getSbkjBm, sbkj));
        if (readabnormalList.size() > 0) {
            for (Readabnormal readab : readabnormalList) {
                String describe = readab.getDescribe();
                BigDecimal ratio = new BigDecimal(readab.getRatio());
                BigDecimal minAverageValue = new BigDecimal(readab.getMinAverageValue());
                String typeCode = readab.getTypeCode();
                BigDecimal average = null;
                //前三次平均水量
                if (StringUtil.isNotNull(month1) && StringUtil.isNotNull(month2) && StringUtil.isNotNull(month3)) {
                    average = month1.add(month2).add(month3).divide(ReadData.CALCULATE_THREE.getYield(), 2, BigDecimal.ROUND_UP);
                } else if (StringUtil.isNotNull(month1) && StringUtil.isNotNull(month2)) {
                    average = month1.add(month2).divide(ReadData.CALCULATE_TWO.getYield(), 2, BigDecimal.ROUND_UP);
                } else if (StringUtil.isNotNull(month1)) {
                    average = month1;
                }
                if (StringUtil.isNotNull(average)) {
                    //前三次平均水量是否大于基准值 如果是则进入筛选，如果本次水量小于等于突降值则异常，
                    // 这里定义的突降值居然是本次水量小于突降值就异常，我觉得正常的理解应该是和上次水量的比较只差，这个差值突降的比较
                    if (average.compareTo(minAverageValue) != -1) {
                        if (AbnormalEnum.SLTJMX.getTypeCode().equals(typeCode)) {
                            BigDecimal tjDiff = month1.subtract(bigBcsl).divide(month1, 3, BigDecimal.ROUND_UP)
                                    .multiply(ReadData.CALCULATE_HUNDRED.getYield());
                            //百分比
                            if (ratio.compareTo(tjDiff) == -1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                        .set(Readmetereashis::getAbnomalId, typeId)
                                        .set(Readmetereashis::getShbz, "0")
                                        .set(Readmetereashis::getAuditReason, describe + "，本次突降比例为：" + tjDiff + "%"));
                            }
                        }
                        if (AbnormalEnum.SLTSMX.getTypeCode().equals(typeCode)) {
                            BigDecimal tsDiff = bigBcsl.subtract(month1).divide(month1, 3, BigDecimal.ROUND_UP)
                                    .multiply(ReadData.CALCULATE_HUNDRED.getYield());
                            //百分比
                            if (ratio.compareTo(tsDiff) == -1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                        .set(Readmetereashis::getAbnomalId, typeId)
                                        .set(Readmetereashis::getShbz, "0")
                                        .set(Readmetereashis::getAuditReason, describe + "，本次突升比例为：" + tsDiff + "%"));
                            }
                        }
                    }
                }
            }
        }
        //环比升 、环比降
        readabnormalList = readabnormalService.list(Wrappers.<Readabnormal>lambdaQuery()
                .and(v -> v.eq(Readabnormal::getTypeCode, AbnormalEnum.HBSMX.getTypeCode())
                        .or().eq(Readabnormal::getTypeCode, AbnormalEnum.HBJMX.getTypeCode()))
                .isNotNull(Readabnormal::getRatio).isNotNull(Readabnormal::getMinAverageValue)
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj));
        if (readabnormalList.size() > 0) {
            //只要其中有一个为null，那么就不满足算法条件
            if (StringUtil.isNotNull(month1) && StringUtil.isNotNull(month2) && StringUtil.isNotNull(month3)) {
                //前三次水量平均值
                BigDecimal average = getAverage(month1, month2, month3);
                for (Readabnormal readab : readabnormalList) {
                    String describe = readab.getDescribe();
                    String typeCode = readab.getTypeCode();
                    BigDecimal ratio = new BigDecimal(readab.getRatio());
                    BigDecimal minAverageValue = new BigDecimal(readab.getMinAverageValue());
                    if (AbnormalEnum.HBSMX.getTypeCode().equals(typeCode)) {
                        //水量平均值必须大于等于最小基准值 才进入算法筛选
                        if (average.compareTo(minAverageValue) != -1) {
                            //升百分比
                            BigDecimal upRatio = getUpRatio(average, bigBcsl);
                            if (upRatio.compareTo(ratio) == 1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                        .set(Readmetereashis::getAbnomalId, typeId)
                                        .set(Readmetereashis::getShbz, "0")
                                        .set(Readmetereashis::getAuditReason, describe + "，本次环比升比例为：" + upRatio + "%"));
                            }
                        }
                    } else if (AbnormalEnum.HBJMX.getTypeCode().equals(typeCode)) {
                        if (average.compareTo(minAverageValue) != -1) {
                            //降百分比
                            BigDecimal downRatio = getDownRatio(average, bigBcsl);
                            if (downRatio.compareTo(ratio) == 1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                        .set(Readmetereashis::getAbnomalId, typeId)
                                        .set(Readmetereashis::getShbz, "0")
                                        .set(Readmetereashis::getAuditReason, describe + "，本次环比降比例为：" + downRatio + "%"));
                            }
                        }
                    }
                }
            }
        }
        //同比升 、同比降
        readabnormalList = readabnormalService.list(Wrappers.<Readabnormal>lambdaQuery()
                .and(v -> v.eq(Readabnormal::getTypeCode, AbnormalEnum.TBSMX.getTypeCode())
                        .or().eq(Readabnormal::getTypeCode, AbnormalEnum.TBJMX.getTypeCode()))
                .isNotNull(Readabnormal::getRatio).isNotNull(Readabnormal::getMinAverageValue)
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj));
        if (readabnormalList.size() > 0) {
            //只要其中有一个为null，那么就不满足算法条件
            if (StringUtil.isNotNull(yearonyear1) && StringUtil.isNotNull(yearonyear2) && StringUtil.isNotNull(yearonyear3)) {
                BigDecimal yearSl1 = new BigDecimal(yearonyear1);
                BigDecimal yearSl2 = new BigDecimal(yearonyear2);
                BigDecimal yearSl3 = new BigDecimal(yearonyear3);
                //前三年同月水量平均值
                BigDecimal average = getAverage(yearSl1, yearSl2, yearSl3);
                for (Readabnormal readab : readabnormalList) {
                    String describe = readab.getDescribe();
                    String typeCode = readab.getTypeCode();
                    BigDecimal ratio = new BigDecimal(readab.getRatio());
                    BigDecimal minAverageValue = new BigDecimal(readab.getMinAverageValue());
//                    Integer minAverageValue = readab.getMinAverageValue();
//                    Float ratio = readab.getRatio();
                    if (AbnormalEnum.TBSMX.getTypeCode().equals(typeCode)) {
                        //水量平均值必须大于等于最小基准值 才进入算法筛选
                        if (average.compareTo(minAverageValue) != -1) {
                            //升比例
                            BigDecimal upRatio = getUpRatio(average, bigBcsl);
                            if (upRatio.compareTo(ratio) == 1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                        .set(Readmetereashis::getAbnomalId, typeId)
                                        .set(Readmetereashis::getShbz, "0")
                                        .set(Readmetereashis::getAuditReason, describe + "，本次同比升比例为：" + upRatio + "%"));
                            }
                        }
                    } else if (AbnormalEnum.TBJMX.getTypeCode().equals(typeCode)) {
                        if (average.compareTo(minAverageValue) != -1) {
                            //降比例
                            BigDecimal downRatio = getDownRatio(average, bigBcsl);
                            if (downRatio.compareTo(ratio) == 1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                        .set(Readmetereashis::getAbnomalId, typeId)
                                        .set(Readmetereashis::getShbz, "0")
                                        .set(Readmetereashis::getAuditReason, describe + "，本次同比降比例为：" + downRatio + "%"));
                            }
                        }
                    }
                }
            }
        }
        //水量微幅波动
        readabnormalList = readabnormalService.list(Wrappers.<Readabnormal>lambdaQuery()
                .isNotNull(Readabnormal::getRatio).isNotNull(Readabnormal::getFiducialValue)
                .eq(Readabnormal::getTypeCode, AbnormalEnum.SLWFBDMX.getTypeCode())
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj));
        if (readabnormalList.size() > 0) {
            for (Readabnormal readab : readabnormalList) {
                String describe = readab.getDescribe();
                BigDecimal ratio = new BigDecimal(readab.getRatio());
                //同比环比
                String isYearorchain = readab.getIsYearorchain();
                //升降比例
                String isUpordown = readab.getIsUpordown();
                //基准值
                BigDecimal fiducialValue = new BigDecimal(readab.getFiducialValue());
                //当月水量大于基准值纳入筛选
                if (bigBcsl.compareTo(fiducialValue) == 1) {
                    //同比
                    if ("0".equals(isYearorchain)) {
                        //只要其中有一个为null，那么就不满足算法条件
                        if (StringUtil.isNotNull(yearonyear1) && StringUtil.isNotNull(yearonyear2) && StringUtil.isNotNull(yearonyear3)) {
                            BigDecimal yearSl1 = new BigDecimal(yearonyear1);
                            BigDecimal yearSl2 = new BigDecimal(yearonyear2);
                            BigDecimal yearSl3 = new BigDecimal(yearonyear3);
                            //前三年同月水量平均值
                            BigDecimal average = getAverage(yearSl1, yearSl2, yearSl3);
                            //升
                            if ("0".equals(isUpordown)) {
                                BigDecimal upRatio = getUpRatio(average, bigBcsl);
                                if (upRatio.compareTo(ratio) != 1) {
                                    //修改抄表类型原因
                                    Long typeId = readab.getType();
                                    update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                            .set(Readmetereashis::getAbnomalId, typeId)
                                            .set(Readmetereashis::getShbz, "0")
                                            .set(Readmetereashis::getAuditReason, describe + "，本次同比升比例为：" + upRatio + "%"));
                                }
                            }
                            //降
                            else if ("1".equals(isUpordown)) {
                                BigDecimal downRatio = getDownRatio(average, bigBcsl);
                                if (downRatio.compareTo(ratio) != 1) {
                                    //修改抄表类型原因
                                    Long typeId = readab.getType();
                                    update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                            .set(Readmetereashis::getAbnomalId, typeId)
                                            .set(Readmetereashis::getShbz, "0")
                                            .set(Readmetereashis::getAuditReason, describe + "，本次同比降比例为：" + downRatio + "%"));
                                }
                            }
                        }
                    }
                    //环比
                    else if ("1".equals(isYearorchain)) {
                        if (StringUtil.isNotNull(month1) && StringUtil.isNotNull(month2) && StringUtil.isNotNull(month3)) {
                            //前三次水量平均值
                            BigDecimal average = getAverage(month1, month2, month3);
                            //升
                            if ("0".equals(isUpordown)) {
                                BigDecimal upRatio = getUpRatio(average, bigBcsl);
                                if (upRatio.compareTo(ratio) != 1) {
                                    //修改抄表类型原因
                                    Long typeId = readab.getType();
                                    update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                            .set(Readmetereashis::getAbnomalId, typeId)
                                            .set(Readmetereashis::getShbz, "0")
                                            .set(Readmetereashis::getAuditReason, describe + "，本次环比升比例为：" + upRatio + "%"));
                                }
                            }
                            //降
                            else if ("1".equals(isUpordown)) {
                                BigDecimal downRatio = getDownRatio(average, bigBcsl);
                                if (downRatio.compareTo(ratio) != 1) {
                                    //修改抄表类型原因
                                    Long typeId = readab.getType();
                                    update(Wrappers.<Readmetereashis>lambdaUpdate().eq(Readmetereashis::getYhbh, yhbh).eq(Readmetereashis::getCbyf, cbyf)
                                            .set(Readmetereashis::getAbnomalId, typeId)
                                            .set(Readmetereashis::getShbz, "0")
                                            .set(Readmetereashis::getAuditReason, describe + "，本次环比降比例为：" + downRatio + "%"));
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private BigDecimal getAverage(BigDecimal sl1, BigDecimal sl2, BigDecimal sl3) {
        //三次水量数据之和
        BigDecimal sum = sl1.add(sl2).add(sl3);
        //除以 3 求平均值用的
        BigDecimal three = ReadData.CALCULATE_THREE.getYield();
        //平均值
        BigDecimal average = sum.divide(three, 2, BigDecimal.ROUND_HALF_UP);
        return average;
    }

    private BigDecimal getDownRatio(BigDecimal average, BigDecimal bcsl) {
        BigDecimal zero = ReadData.CALCULATE_ZERO.getYield();
        //平均值与本次水量的差 可以得到降值
        BigDecimal diff = average.subtract(bcsl);
        if (diff.compareTo(zero) == 0) {
            return zero;
        }
        //百分比
        BigDecimal percent = diff.divide(average, 2, BigDecimal.ROUND_HALF_UP);
        return percent;
    }

    private BigDecimal getUpRatio(BigDecimal average, BigDecimal bcsl) {
        BigDecimal zero = ReadData.CALCULATE_ZERO.getYield();
        //本次水量与平均值的差 可以得到升值
        BigDecimal diff = bcsl.subtract(average);
        if (diff.compareTo(zero) == 0) {
            return zero;
        }
        //百分比
        BigDecimal percent = diff.divide(average, 2, BigDecimal.ROUND_HALF_UP);
        return percent;
    }
}
