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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.common.core.util.StringUtil;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.xrtygis.custom.entity.dto.CustomizeDto;
import com.tofly.xrtygis.custom.mapper.CustomDisplayMapper;
import com.tofly.xrtygis.custom.service.CustomizeService;
import com.tofly.xrtygis.custom.util.DateTimeUtil;
import com.tofly.xrtygis.em.Constant;
import com.tofly.xrtygis.em.IndexTypeDictEnum;
import com.tofly.xrtygis.em.IndexTypeInfoEnum;
import com.tofly.xrtygis.entity.*;
import com.tofly.xrtygis.entity.vo.DmaCalculatePramVo;
import com.tofly.xrtygis.entity.vo.DmaMinWaterSupplyVo;
import com.tofly.xrtygis.mapper.IndicatorCorrectionMapper;
import com.tofly.xrtygis.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * 指标修正记录表
 *
 * @author admin
 * @date Thu Apr 28 00:00:00 CST 2022
 */
@Service("indicatorCorrectionService")
public class IndicatorCorrectionServiceImpl extends ServiceImpl<IndicatorCorrectionMapper, IndicatorCorrection> implements IndicatorCorrectionService {

    @Autowired
    private DmaregionService dmaregionService;
    @Autowired
    private DmaUnfilledWaterService dmaUnfilledWaterService;
    @Autowired
    private DmaStatisticalService dmaStatisticalService;
    @Autowired
    private TotalStatisticalService totalStatisticalService;
    @Autowired
    private CustomizeService customizeService;
    @Autowired
    private CustomDisplayMapper customDisplayMapper;
    @Autowired
    private DmaandobserService dmaandobserService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean leakageRateCalculate(Date reviseDate) {
        // 统计值存储
        Map<Long, DmaStatistical> dmaStatisticalMap = new HashMap<>(12);

        List<Dmaregion> dmaIdList = dmaregionService.list();
        // 当天开始时间 当天结束时间
        LocalDate time = DateTimeUtil.UDateToLocalDate(reviseDate);
        Date startDate = DateTimeUtil.convertLDTToDate(DateTimeUtil.getAssignTodayBeginDate(time));
        Date endDate = DateTimeUtil.convertLDTToDate(DateTimeUtil.getAssignTodayEndDate(time));
//        Map<Long, BigDecimal> userWaterMap = new HashMap<>(12);
        // 获取当前日期
        String yearMonthDay = DateTimeUtil.getLocalDate(reviseDate, DateTimeUtil.DAY_FORMAT);
        // 获取当前日期(最大数据) 设备供水量
        List<DmaCalculatePramVo> supplyList = baseMapper.getDmaWaterSupply(yearMonthDay,
                String.valueOf(IndexTypeDictEnum.CUM_FLOW.getType()));
        // 获取当前日期(最小数据) 设备供水量
        List<DmaCalculatePramVo> lodTotalWaterSupply = baseMapper.getLostMonthWaterSupply(yearMonthDay,
                String.valueOf(IndexTypeDictEnum.CUM_FLOW.getType()));
        // 获取每个分区最小瞬时流量
        List<DmaMinWaterSupplyVo> minWaterSupplyVos = baseMapper.getDmaInstantaneousMinWaterSupply(yearMonthDay,
                String.valueOf(IndexTypeDictEnum.INSTANTANEOUS_FLOW.getType()));
        Map<Long, BigDecimal> minWaterSupply = minWaterSupplyVos.stream().collect(Collectors.toMap(DmaMinWaterSupplyVo::getDmaId, DmaMinWaterSupplyVo::getMinWaterSupply,(key1, key2) -> key2));

        // 处理供水量逻辑
        Map<Long, BigDecimal> waterSupplyMap = getWaterSupplyMap(supplyList, lodTotalWaterSupply);
        // 总供水量
        BigDecimal totalWaterSupply = waterSupplyMap.values().stream().filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 获取对应DMA分区的 远传供水量(远传表) 当日开始时间 当日结束时间
        Map<Long, BigDecimal> remoteWaterMap = baseMapper.getRemoteWaterSupply(startDate, endDate).stream().collect(Collectors.toMap(DmaCalculatePramVo::getDmaId, DmaCalculatePramVo::getRemoteWaterSupply, (key1, key2) -> key2));
        // 获取对应DMA分区的 未上盘水量(对应的DMA分区 每月只对应 一条未上盘水量)
        Map<Long, DmaUnfilledWater> unfilledWaterMap = dmaUnfilledWaterService.list(new QueryWrapper<DmaUnfilledWater>().lambda()
                .ge(DmaUnfilledWater::getWriteDate, startDate)
                .le(DmaUnfilledWater::getWriteDate, endDate)).stream().collect(Collectors.toMap(DmaUnfilledWater::getDmaId, m -> m));
        // 获取对应DMA分区的 DN75（含）以上管道长度 总长 km
        Map<Long, BigDecimal> dnLengthMap = baseMapper.getDNLength().stream().collect(Collectors.toMap(DmaCalculatePramVo::getDmaId, DmaCalculatePramVo::getDNLength, (key1, key2) -> key2));
        // 获取对应DMA分区的 年平均压力
        String year = DateTimeUtil.getLocalDate(reviseDate, DateTimeUtil.YEAR);
        Map<Long, BigDecimal> yearPressureMap = baseMapper.getDmaYearPressure(year).stream().collect(Collectors.toMap(DmaCalculatePramVo::getDmaId, DmaCalculatePramVo::getYearPressure, (key1, key2) -> key2));
        List<Map<String,Object>> yesterdayWaters = customDisplayMapper.getSomeDayWater(DateUtil.format(startDate, "yyyy-MM-dd"), IndexTypeInfoEnum.CUM_FLOW.getId());
        List<Dmaandobser> inDmaandobsersAll = dmaandobserService.list(new QueryWrapper<Dmaandobser>().lambda().eq(Dmaandobser::getIsout, "0"));
        List<Dmaandobser> outDmaandobsersAll = dmaandobserService.list(new QueryWrapper<Dmaandobser>().lambda().eq(Dmaandobser::getIsout, "1"));
        dmaIdList.forEach(dmaregion -> {
            Long dmaId = dmaregion.getId();
            DmaStatistical vo = new DmaStatistical();
            // 计算修正前漏损率
            BigDecimal waterSupply = waterSupplyMap.get(dmaId) == null ? BigDecimal.ZERO : waterSupplyMap.get(dmaId);
            BigDecimal remoteWater = remoteWaterMap.get(dmaId) == null ? BigDecimal.ZERO : remoteWaterMap.get(dmaId);
            // 供水量 (设备+远传)
            BigDecimal gsl = waterSupply.add(remoteWater);
            // 售水量 绵阳师院等于供水量
//            BigDecimal userWater = userWaterMap.get(dmaId) == null ? BigDecimal.ZERO : userWaterMap.get(dmaId);
//            BigDecimal userWater = gsl;
            // 未上盘水量 = 免费用水量+漏失水量+计量漏失水量+其他损失水量+计费用水量
//            BigDecimal wspsl = BigDecimal.ZERO;
            DmaUnfilledWater dmaUnfilledWater = unfilledWaterMap.get(dmaId) == null ? new DmaUnfilledWater() : unfilledWaterMap.get(dmaId);
            BigDecimal freeWaterVolume = dmaUnfilledWater.getFreeWaterVolume() == null ? BigDecimal.ZERO : dmaUnfilledWater.getFreeWaterVolume();
//            BigDecimal outflowWaterVolume = dmaUnfilledWater.getOutflowWaterVolume() == null ? BigDecimal.ZERO : dmaUnfilledWater.getOutflowWaterVolume();
            BigDecimal lossWaterVolume = dmaUnfilledWater.getLossWaterVolume() == null ? BigDecimal.ZERO : dmaUnfilledWater.getLossWaterVolume();
            BigDecimal otherWaterVolume = dmaUnfilledWater.getOtherWaterVolume() == null ? BigDecimal.ZERO : dmaUnfilledWater.getOtherWaterVolume();
            BigDecimal billingWaterVolume = dmaUnfilledWater.getBillingWaterVolume() == null ? BigDecimal.ZERO : dmaUnfilledWater.getBillingWaterVolume();
//            wspsl = wspsl.add(freeWaterVolume).add(outflowWaterVolume).add(lossWaterVolume).add(otherWaterVolume).add(billingWaterVolume);
            // 修正前漏损率=（供水量-售水量-未上盘水量）/供水量 (修正后同步修改该字段值)
            // 产销差（%）=【（总供水量-售水量）/总供水量】×100
//            BigDecimal poorProductionRate = BigDecimal.ZERO;
//            BigDecimal leakageRate = BigDecimal.ZERO;
//            if (BigDecimal.ZERO.compareTo(gsl) != 0) {
//                leakageRate = gsl.subtract(userWater).subtract(wspsl).divide(gsl, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
//
//                poorProductionRate = gsl.subtract(userWater).divide(gsl, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
//            }
            // DMA分区的 DN75（含）以上管道长度 总长 km
            BigDecimal dnLengthVal = dnLengthMap.get(dmaId) == null ? BigDecimal.ZERO : dnLengthMap.get(dmaId);
            // DMA分区的 年平均压力
            BigDecimal yearPressureVal = yearPressureMap.get(dmaId) == null ? BigDecimal.ZERO : yearPressureMap.get(dmaId);
            vo.setDmaId(dmaId);
            vo.setStatisticalDate(reviseDate);
            vo.setBillingWaterVolume(billingWaterVolume);
            vo.setFreeWaterVolume(freeWaterVolume);
//            vo.setOutflowWaterVolume(outflowWaterVolume);
            vo.setLossWaterVolume(lossWaterVolume);
            vo.setOtherWaterVolume(otherWaterVolume);
            vo.setRemoteWater(remoteWater);
//            vo.setWaterSupply(gsl);
            /***********************************自定义一级入口总表水量为总供水量*************************************/
            BigDecimal poorProductionRate = BigDecimal.ZERO;
            BigDecimal leakageWater = BigDecimal.ZERO;
            BigDecimal leakageRate = BigDecimal.ZERO;
            vo.setWaterSupply(BigDecimal.ZERO);
            vo.setUserWater(BigDecimal.ZERO);
            if (CollectionUtils.isNotEmpty(yesterdayWaters)) {
                List<Dmaandobser> inDmaandobsers = inDmaandobsersAll.stream().filter(e -> Objects.equals(e.getDmaId(), dmaregion.getId())).collect(Collectors.toList());
                List<Dmaandobser> outDmaandobsers = outDmaandobsersAll.stream().filter(e -> Objects.equals(e.getDmaId(), dmaregion.getId())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(inDmaandobsers)) {
                    List<Long> inDeviceIds = inDmaandobsers.stream().map(Dmaandobser::getTableId).collect(Collectors.toList());
                    List<Map<String,Object>> inYesterdayWaters = yesterdayWaters.stream()
                            .filter(e -> e.get("deviceId") != null
                                    && inDeviceIds.contains(Long.parseLong(String.valueOf(e.get("deviceId")))))
                            .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(inYesterdayWaters)) {
                        BigDecimal inWater = BigDecimal.valueOf(inYesterdayWaters.stream()
                                .filter(e -> e.get("diff") != null)
                                .mapToDouble(e -> Double.parseDouble(String.valueOf(e.get("diff")))).sum());
                        vo.setWaterSupply(inWater);
                        vo.setUserWater(inWater);
                        if (CollectionUtils.isNotEmpty(outDmaandobsers) && inWater.compareTo(BigDecimal.ZERO) != 0) {
                            List<Long> outDeviceIds = outDmaandobsers.stream().map(Dmaandobser::getTableId).collect(Collectors.toList());
                            List<Map<String,Object>> outYesterdayWaters = yesterdayWaters.stream()
                                    .filter(e -> e.get("deviceId") != null
                                            && outDeviceIds.contains(Long.parseLong(String.valueOf(e.get("deviceId")))))
                                    .collect(Collectors.toList());
                            if (CollectionUtils.isNotEmpty(outYesterdayWaters)) {
                                BigDecimal outWater = BigDecimal.valueOf(outYesterdayWaters.stream()
                                        .filter(e -> e.get("diff") != null)
                                        .mapToDouble(e -> Double.parseDouble(String.valueOf(e.get("diff")))).sum());
                                leakageWater = inWater.subtract(outWater);
                                leakageRate = inWater.subtract(outWater).divide(inWater, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
                                poorProductionRate = inWater.subtract(outWater).divide(inWater, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
                            }
                        }
                    }
                }
            }
            vo.setOutflowWaterVolume(leakageWater);
            vo.setLeakageRate(leakageRate);
            vo.setPoorProductionRate(poorProductionRate);
            /**************************************************************************************************/
//            vo.setLeakageRate(leakageRate);
//            vo.setPoorProductionRate(poorProductionRate);
//            vo.setUserWater(userWater);
            vo.setDnLengthVal(dnLengthVal);
            vo.setYearPressureVal(yearPressureVal);
            if(minWaterSupply.size()>0){
                vo.setMinWaterSupply(minWaterSupply.get(dmaId));
            }
            if(totalWaterSupply.compareTo(BigDecimal.ZERO)>0){
                vo.setWaterSupplyRate(gsl.divide(totalWaterSupply,4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
            }
            dmaStatisticalMap.put(dmaId, vo);
        });
        // 对应DMA分区 统计时间 相同 则更新 其余为新增
        if (CollUtil.isNotEmpty(dmaIdList)) {
            Map<Long, Long> collect = dmaStatisticalService.list(new QueryWrapper<DmaStatistical>().lambda()
                    .in(DmaStatistical::getDmaId, dmaIdList.stream().map(Dmaregion::getId).collect(Collectors.toList()))
                    .eq(DmaStatistical::getStatisticalDate, reviseDate)).stream()
                    .collect(Collectors.toMap(DmaStatistical::getDmaId, DmaStatistical::getId, (key1, key2) -> key2));
            collect.forEach((k, v) -> {
                DmaStatistical dmaStatistical = dmaStatisticalMap.get(k);
                if (null != dmaStatistical) {
                    dmaStatistical.setId(v);
                }
            });
            if (dmaStatisticalMap.size() > 0) {
                dmaStatisticalService.remove(new QueryWrapper<DmaStatistical>()
                        .eq("to_char(STATISTICAL_DATE, 'yyyy-mm-dd')", DateUtil.format(reviseDate, "yyyy-MM-dd")));
                this.saveDmaStatisticalMap(dmaStatisticalMap.values());
                this.saveIndicatorCorrection(dmaStatisticalMap.values());
                this.saveCustomize(dmaStatisticalMap.values(),reviseDate);
            }
        }
        return true;
    }

    private void saveDmaStatisticalMap(Collection<DmaStatistical> dmaStatisticalList) {
        dmaStatisticalList.forEach(info -> dmaStatisticalService.saveOrUpdate(info));
    }

    @Override
    public Boolean totalCalculate(Date reviseDate) {
        TotalStatistical statistical = new TotalStatistical();
        // 获取当前月份 用户售水量
        // 当天开始时间 当天结束时间
        LocalDate time = DateTimeUtil.UDateToLocalDate(reviseDate);
        Date startDate = DateTimeUtil.convertLDTToDate(DateTimeUtil.getAssignTodayBeginDate(time));
        Date endDate = DateTimeUtil.convertLDTToDate(DateTimeUtil.getAssignTodayEndDate(time));
        BigDecimal mapperTotalUserWaterConsumption;
        // 获取当前日期 设备供水量
        String newYearMonthDay = DateTimeUtil.getLocalDate(reviseDate, DateTimeUtil.DAY_FORMAT);
        List<DmaCalculatePramVo> newTotalWaterSupply = baseMapper.getTotalWaterSupply(newYearMonthDay,
                String.valueOf(IndexTypeDictEnum.CUM_FLOW.getType()));
        // 获取当前月份scada统计最小值 设备供水量

        List<DmaCalculatePramVo> lodTotalWaterSupply = baseMapper.getLostMonthTotalWaterSupply(newYearMonthDay,
                String.valueOf(IndexTypeDictEnum.CUM_FLOW.getType()));
        // 处理供水量逻辑
        BigDecimal bigDecimal = getMapperTotalWaterSupply(newTotalWaterSupply, lodTotalWaterSupply);
        BigDecimal totalWaterSupply = bigDecimal == null ? BigDecimal.ZERO : bigDecimal;

        // 获取当前月份1级分区 远传供水量(远传表) 当日开始时间 当日结束时间
        BigDecimal mapperTotalRemoteWaterSupply = baseMapper.getTotalRemoteWaterSupply(startDate, endDate);
        BigDecimal totalRemoteWaterSupply = mapperTotalRemoteWaterSupply == null ? BigDecimal.ZERO : mapperTotalRemoteWaterSupply;

        // 获取当前月份1级分区 未上盘水量(对应的DMA分区 每月只对应 一条未上盘水量)
        List<DmaUnfilledWater> list = dmaUnfilledWaterService.list(new QueryWrapper<DmaUnfilledWater>().lambda()
                .ge(DmaUnfilledWater::getWriteDate, startDate)
                .le(DmaUnfilledWater::getWriteDate, endDate));
        // 未上盘水量 = 免费用水量+漏失水量+计量漏失水量+其他损失水量+计费用水量
        if (null != list && list.size() > 0) {
            BigDecimal wspsl = BigDecimal.ZERO;
            BigDecimal freeWaterVolume = list.stream().map(DmaUnfilledWater::getFreeWaterVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal outflowWaterVolume = list.stream().map(DmaUnfilledWater::getOutflowWaterVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal lossWaterVolume = list.stream().map(DmaUnfilledWater::getLossWaterVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal otherWaterVolume = list.stream().map(DmaUnfilledWater::getOtherWaterVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal billingWaterVolume = list.stream().map(DmaUnfilledWater::getBillingWaterVolume).reduce(BigDecimal.ZERO, BigDecimal::add);
            wspsl = wspsl.add(freeWaterVolume).add(outflowWaterVolume).add(lossWaterVolume).add(otherWaterVolume);
            statistical.setFreeWaterVolume(freeWaterVolume);
            statistical.setOutflowWaterVolume(outflowWaterVolume);
            statistical.setLossWaterVolume(lossWaterVolume);
            statistical.setOtherWaterVolume(otherWaterVolume);
            statistical.setUnfilledWater(wspsl);
            statistical.setBillingWaterVolume(billingWaterVolume);
        } else {
            statistical.setUnfilledWater(BigDecimal.ZERO);
        }
        statistical.setStatisticalDate(reviseDate);


        statistical.setWaterSupply(totalWaterSupply);
        statistical.setRemoteWater(totalRemoteWaterSupply);
//        statistical.setLeakageVal(leakageVal);
//        statistical.setLeakageOverVal(leakageOverVal);
        // 供水量 (设备+远传)
        BigDecimal gsl = totalWaterSupply.add(totalRemoteWaterSupply);
        // 售水量 绵阳师院等于供水量
        mapperTotalUserWaterConsumption = gsl;
        statistical.setUserWater(mapperTotalUserWaterConsumption);
        // 修正前漏损率=（供水量-售水量-未上盘水量）/供水量
        // 产销差（%）=【（总供水量-售水量）/总供水量】×100
        BigDecimal poorProductionRate = BigDecimal.ZERO;
        BigDecimal leakageRate = BigDecimal.ZERO;
        if (BigDecimal.ZERO.compareTo(gsl) != 0) {
            leakageRate = gsl.subtract(mapperTotalUserWaterConsumption).subtract(statistical.getUnfilledWater()).divide(gsl, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));

            poorProductionRate = gsl.subtract(mapperTotalUserWaterConsumption).divide(gsl, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
        }

        statistical.setLeakageRate(leakageRate);
        statistical.setPoorProductionRate(poorProductionRate);

        // 对应 统计时间 相同 则更新 其余为新增
        List<TotalStatistical> totalStatisticals = totalStatisticalService.list(new QueryWrapper<TotalStatistical>().lambda()
                .eq(TotalStatistical::getStatisticalDate, reviseDate));
        if (null != totalStatisticals && totalStatisticals.size() > 0) {
            statistical.setId(totalStatisticals.get(0).getId());
        }

        return totalStatisticalService.saveOrUpdate(statistical);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveInfo(IndicatorCorrection indicatorCorrection, String flag) {
        Dmaregion dmaregion = dmaregionService.getById(indicatorCorrection.getDmaId());
        Integer partitionLevel = dmaregion.getPartitionLevel();
        indicatorCorrection.setDmaCode(dmaregion.getDmaCode());
        indicatorCorrection.setDmaName(dmaregion.getDmaName());
        indicatorCorrection.setDmaLevel(partitionLevel);
        if(null==SecurityUtils.getUser()){
            indicatorCorrection.setCreateUser(0L);
            indicatorCorrection.setUpdateUser(0L);
        }

        // 判断当前月份是否存在,存在则更新,不存在则新增
        Long dmaId = indicatorCorrection.getDmaId();
        Date reviseDate = indicatorCorrection.getReviseDate();

        IndicatorCorrection one = this.getOne(new QueryWrapper<IndicatorCorrection>().lambda().eq(IndicatorCorrection::getDmaId, dmaId).eq(IndicatorCorrection::getReviseDate, reviseDate));
        if (null != one) {
            indicatorCorrection.setId(one.getId());
        }

        List<DmaStatistical> list = dmaStatisticalService.list(new QueryWrapper<DmaStatistical>().lambda().eq(DmaStatistical::getStatisticalDate, reviseDate).eq(DmaStatistical::getDmaId, dmaId));
        if (null != list && list.size() > 0) {
            DmaStatistical dmaStatistical = list.get(0);
            BigDecimal r1 = getR1(indicatorCorrection.getJmcbZgsBl(), dmaStatistical);
            BigDecimal waterSupply = dmaStatistical.getWaterSupply();
            if (waterSupply.compareTo(BigDecimal.ZERO) > 0) {
                indicatorCorrection.setPipeLength(dmaStatistical.getDnLengthVal().divide(waterSupply, 4, BigDecimal.ROUND_HALF_UP));
            }

            BigDecimal r2 = getR2(dmaStatistical);
            BigDecimal r3 = getR3(dmaStatistical.getYearPressureVal());
            BigDecimal leakageRate = dmaStatistical.getLeakageRate();
            // 漏损率=修正前漏损率-(R1+R2+R3+R4)
            BigDecimal correctLeakage = leakageRate.subtract((r1.add(r2).add(r3)));
            indicatorCorrection.setJmcbXzz(r1);
            indicatorCorrection.setDwgsXzz(r2);
            indicatorCorrection.setNpjylXzz(r3);
            indicatorCorrection.setBeforLeak(leakageRate);
            if (StringUtil.isEmpty(flag)) {
                indicatorCorrection.setAfterLeak(correctLeakage);
            }

            indicatorCorrection.setDnLengthVal(dmaStatistical.getDnLengthVal());
            indicatorCorrection.setWaterSupply(waterSupply);
            if (StringUtil.isEmpty(flag)) {
                // 修改统计表各自DMA分区漏损率
                dmaStatistical.setLeakageRate(correctLeakage);
                dmaStatisticalService.updateById(dmaStatistical);
                // 判断是否为1级分区 若为一级分区修改总统计指标表漏损率
                if (1 == partitionLevel) {
                    TotalStatistical totalStatistical = totalStatisticalService.getOne(new QueryWrapper<TotalStatistical>().lambda().eq(TotalStatistical::getStatisticalDate, reviseDate));
                    if (null != totalStatistical) {
                        // 获取统计指标表中所有一级分区的漏损率 求和(除当前修正dma分区漏损率)
                        List<DmaStatistical> statisticalList = dmaStatisticalService.list(new QueryWrapper<DmaStatistical>().lambda()
                                .eq(DmaStatistical::getStatisticalDate, reviseDate)
                                .ne(DmaStatistical::getDmaId, dmaId));
                        if (null != statisticalList && statisticalList.size() > 0) {
                            BigDecimal leakTotal = statisticalList.stream()
                                    .map(DmaStatistical::getLeakageRate).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal add = leakTotal.add(correctLeakage);
                            BigDecimal leakNew = add.divide(BigDecimal.valueOf(statisticalList.size() + 1), 2, BigDecimal.ROUND_HALF_UP);
                            totalStatistical.setLeakageRate(leakNew);
                        } else {
                            totalStatistical.setLeakageRate(correctLeakage);
                        }
                        totalStatisticalService.updateById(totalStatistical);
                    }
                }
            }

        }

        return this.saveOrUpdate(indicatorCorrection);
    }


    /**
     * 处理每个分区的供水量计算
     *
     * @param supplyList
     * @param lodTotalWaterSupply
     * @return
     */
    private Map<Long, BigDecimal> getWaterSupplyMap(List<DmaCalculatePramVo> supplyList, List<DmaCalculatePramVo> lodTotalWaterSupply) {
        Map<Long, BigDecimal> map = new HashMap<>(12);
        // dma分组
        Map<Long, List<DmaCalculatePramVo>> collect = supplyList.stream().collect(Collectors.groupingBy(DmaCalculatePramVo::getDmaId));
        // 昨日dma分组
        Map<Long, List<DmaCalculatePramVo>> lodCollect = lodTotalWaterSupply.stream().collect(Collectors.groupingBy(DmaCalculatePramVo::getDmaId));
        collect.forEach((k, v) -> {

            // 存储 返回供水量/入口供水量/出口供水量
            AtomicReference<BigDecimal> value = new AtomicReference<>(BigDecimal.ZERO);
            AtomicReference<BigDecimal> enterValue = new AtomicReference<>(BigDecimal.ZERO);
            AtomicReference<BigDecimal> outValue = new AtomicReference<>(BigDecimal.ZERO);

            List<DmaCalculatePramVo> lodList = lodCollect.get(k) == null ? new ArrayList<>() : lodCollect.get(k);
            // 按照出入口分组
            Map<String, List<DmaCalculatePramVo>> newIsOutList = v.stream().collect(Collectors.groupingBy(DmaCalculatePramVo::getIsOut));
            Map<String, List<DmaCalculatePramVo>> lodIsOutList = lodList.stream().collect(Collectors.groupingBy(DmaCalculatePramVo::getIsOut));
            // 本日 与 上日 入口/出口 相减
            if (null != newIsOutList) {
                newIsOutList.forEach((z, m) -> {
                    List<DmaCalculatePramVo> dmaCalculatePramVos = lodIsOutList.get(z) == null ? new ArrayList<>() : lodIsOutList.get(z);
                    BigDecimal bigDecimal1 = m.stream().map(DmaCalculatePramVo::getWaterSupply).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal reduce = bigDecimal1 == null ? BigDecimal.ZERO : bigDecimal1;
                    BigDecimal bigDecimal2 = dmaCalculatePramVos.stream().map(DmaCalculatePramVo::getWaterSupply).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal decimal = bigDecimal2 == null ? BigDecimal.ZERO : bigDecimal2;
                    if ("0".equals(z)) {
                        enterValue.set(enterValue.get().add(reduce).subtract(decimal));
                    } else {
                        outValue.set(outValue.get().add(reduce).subtract(decimal));
                    }
                });
            }

            // 当前日内出入口相减
            value.set(enterValue.get().subtract(outValue.get()));
            map.put(k, value.get());
        });
        return map;
    }

    /**
     * 处理所有供水量计算
     *
     * @param supplyList
     * @param lodTotalWaterSupply
     * @return
     */
    private BigDecimal getMapperTotalWaterSupply(List<DmaCalculatePramVo> supplyList, List<DmaCalculatePramVo> lodTotalWaterSupply) {
        // 存储 返回供水量/入口供水量/出口供水量
        AtomicReference<BigDecimal> value = new AtomicReference<>(BigDecimal.ZERO);
        AtomicReference<BigDecimal> enterValue = new AtomicReference<>(BigDecimal.ZERO);
        AtomicReference<BigDecimal> outValue = new AtomicReference<>(BigDecimal.ZERO);

        // 按照出入口分组
        Map<String, List<DmaCalculatePramVo>> newIsOutList = supplyList.stream().collect(Collectors.groupingBy(DmaCalculatePramVo::getIsOut));
        Map<String, List<DmaCalculatePramVo>> lodIsOutList = lodTotalWaterSupply.stream().collect(Collectors.groupingBy(DmaCalculatePramVo::getIsOut));
        // 本日 与 上日 入口/出口 相减
        if (null != newIsOutList) {
            newIsOutList.forEach((z, m) -> {
                List<DmaCalculatePramVo> dmaCalculatePramVos = lodIsOutList.get(z) == null ? new ArrayList<>() : lodIsOutList.get(z);
                BigDecimal bigDecimal1 = m.stream().map(DmaCalculatePramVo::getWaterSupply).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal reduce = bigDecimal1 == null ? BigDecimal.ZERO : bigDecimal1;
                BigDecimal bigDecimal2 = dmaCalculatePramVos.stream().map(DmaCalculatePramVo::getWaterSupply).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal decimal = bigDecimal2 == null ? BigDecimal.ZERO : bigDecimal2;
                if ("0".equals(z)) {
                    enterValue.set(enterValue.get().add(reduce).subtract(decimal));
                } else {
                    outValue.set(outValue.get().add(reduce).subtract(decimal));
                }
            });
        }

        // 当前日内出入口相减
        value.set(enterValue.get().subtract(outValue.get()));


        return value.get();
    }

    /**
     * ①居民抄表到户水量的修正值应按下式计算：
     * R1＝0．08r×100％（2.9
     * 式中：R1——居民抄表到户水量的修正值（％）
     * r——居民抄表到户水量占总供水量比例。
     *
     * @param jmcbZgsBl      居民抄表到户水量的修正值
     * @param dmaStatistical 对应月份统计的指标参数对象
     * @return
     */
    private BigDecimal getR1(BigDecimal jmcbZgsBl, DmaStatistical dmaStatistical) {
        BigDecimal r1 = BigDecimal.ZERO;
        // 判断前端是否传入 居民抄表到户水量占总供水量比例
        if (null == jmcbZgsBl) {
            // 用户用水量 供水量获取
            BigDecimal userWater = dmaStatistical.getUserWater();
            BigDecimal waterSupply = dmaStatistical.getWaterSupply();
            if (userWater.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal r = userWater.divide(waterSupply, 4, BigDecimal.ROUND_HALF_UP);
                r1 = r.multiply(BigDecimal.valueOf(0.08)).multiply(BigDecimal.valueOf(100));
            }

        } else {
            r1 = BigDecimal.valueOf(0.08).multiply(jmcbZgsBl).multiply(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        return r1;
    }

    /**
     * 获取R2计算值
     * ②单位供水量管长的修正值应按下列公式计算：
     * R2＝0．99（A—0．0693）×100％（2.9.8-2）
     * （2.9.8-3）
     * 式中：R2——单位供水量管长的修正值（％）；
     * A——单位供水量管长（km／万m3）；
     * L——DN75（含）以上管道长度（km）;
     * Qs——总供水量（m3）
     * 当R2值大于3％时，应取3％；当R2值小于-3％时，应取-3％
     *
     * @param dmaStatistical 对应月份统计的指标参数对象
     * @return
     */
    private BigDecimal getR2(DmaStatistical dmaStatistical) {
        BigDecimal r2 = BigDecimal.ZERO;
        // 管网长度 供水量 获取
        BigDecimal dnLength = dmaStatistical.getDnLengthVal();
        BigDecimal waterSupply = dmaStatistical.getWaterSupply();
        if (waterSupply.compareTo(BigDecimal.ZERO) > 0) {
            r2 = dnLength.divide(waterSupply, 4, BigDecimal.ROUND_HALF_UP)
                    .subtract(BigDecimal.valueOf(0.0693))
                    .multiply(BigDecimal.valueOf(0.99))
                    .multiply(BigDecimal.valueOf(100));
        }
        BigDecimal up = new BigDecimal(3);
        BigDecimal dow = new BigDecimal(-3);
        if (r2.compareTo(up) > 0) {
            r2 = up;
        }
        if (dow.compareTo(r2) > 0) {
            r2 = dow;
        }
        return r2;
    }

    /**
     * ③年平均出厂压力修正
     * 年平均出厂压力大于0.35MPa且小于或等于0.55MPa时，修正值应为0.5％；
     * 年平均出厂压力大于0.55MPa且小于或等于0.75MPa时，修正值应为1％；
     * 年平均出厂压力大于0.75MPa时，修正值应为2％。
     *
     * @param dmaYearPressure 年平均压力
     * @return
     */
    private BigDecimal getR3(BigDecimal dmaYearPressure) {
        //   ③年平均出厂压力修正
        //  年平均出厂压力大于0.35MPa且小于或等于0.55MPa时，修正值应为0.5％；
        //  年平均出厂压力大于0.55MPa且小于或等于0.75MPa时，修正值应为1％；
        //  年平均出厂压力大于0.75MPa时，修正值应为2％。
        BigDecimal r3 = BigDecimal.ZERO;
        if (dmaYearPressure.compareTo(BigDecimal.valueOf(0.75)) > 0) {
            r3 = BigDecimal.valueOf(2);
        }
        if (dmaYearPressure.compareTo(BigDecimal.valueOf(0.55)) > 0 && dmaYearPressure.compareTo(BigDecimal.valueOf(0.75)) <= 0) {
            r3 = BigDecimal.valueOf(1);
        }
        if (dmaYearPressure.compareTo(BigDecimal.valueOf(0.35)) > 0 && dmaYearPressure.compareTo(BigDecimal.valueOf(0.55)) <= 0) {
            r3 = BigDecimal.valueOf(0.5);
        }
        return r3;
    }

    /**
     * 每日统计指标->触发国标指标修正批量新增/修改
     *
     * @param dmaStatisticalList
     */
    public void saveIndicatorCorrection(Collection<DmaStatistical> dmaStatisticalList) {
        dmaStatisticalList.forEach(info -> {
            IndicatorCorrection correction = new IndicatorCorrection();
            Long dmaId = info.getDmaId();
            Date statisticalDate = info.getStatisticalDate();
            correction.setDmaId(dmaId);
            correction.setReviseDate(statisticalDate);
            saveInfo(correction,"1");
        });
    }

    /**
     * 每日统计指标->触发自定义指标修正批量新增/修改
     * @param dmaStatisticalList
     * @param reviseDate
     */
    public void saveCustomize(Collection<DmaStatistical> dmaStatisticalList,Date reviseDate){
        CustomizeDto dto = new CustomizeDto();
        StringBuilder stringBuilder = new StringBuilder("");
        dmaStatisticalList.forEach(info->{
            stringBuilder.append(info.getDmaId()).append(Constant.CSV);
        });
        dto.setDmaIds(stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString());
        dto.setMonths(DateTimeUtil.getLocalDate(reviseDate,DateTimeUtil.DAY_FORMAT));
        dto.setLeakCoefficient(BigDecimal.ONE);
        dto.setPoorProductionCoefficient(BigDecimal.ONE);

        customizeService.saveInfo(dto,"1");
    }


}
