package com.zcxk.charge.web.service.impl;

import com.zcxk.charge.api.dto.MonitorDataChartReportAttributeDto;
import com.zcxk.charge.api.dto.MonitorDataChartReportValueDto;
import com.zcxk.charge.api.dto.generalview.*;
import com.zcxk.charge.api.dto.query.ChartReportDto;
import com.zcxk.charge.api.dto.query.DeviceWaterDto;
import com.zcxk.charge.api.dto.query.MonitorDataChartQueryDto;
import com.zcxk.charge.api.dto.query.MonitorDataCompareQueryDto;
import com.zcxk.charge.api.enums.DeviceParamTypeEnum;
import com.zcxk.charge.api.enums.ReportTypeEnum;
import com.zcxk.charge.api.enums.SceneTypeEnum;
import com.zcxk.charge.api.vo.*;
import com.zcxk.charge.core.dao.DeviceSceneMapper;
import com.zcxk.charge.core.dao.MonitorDataReportMapper;
import com.zcxk.charge.core.entity.DeviceEntity;
import com.zcxk.charge.core.entity.MonitorDataEntity;
import com.zcxk.charge.core.entity.MonitorDataValueEntity;
import com.zcxk.charge.web.service.MonitorDataReportService;
import com.zcxk.charge.web.service.SceneService;
import com.zcxk.core.common.pojo.UserCondition;
import com.zcxk.core.oauth2.pojo.LoginUser;
import com.zcxk.core.oauth2.util.UserUtil;
import com.zcxk.core.utils.BigDecimalUtils;
import com.zcxk.core.utils.ByteArrayUtils;
import com.zcxk.core.utils.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description
 * @author  wangli
 * @data 2020/12/7 20:23
 */
@Service
public class MonitorDataReportServiceImpl implements MonitorDataReportService {

    @Resource
    private MonitorDataReportMapper monitorDataReportMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SceneService sceneService;

    @Resource
    private DeviceSceneMapper deviceSceneMapper;

    @Override
    public List<MonitorDataChartReportDeviceVo> monitorDataChartReportByDay(ChartReportDto chartDto) {
        List<MonitorDataChartReportDeviceVo> data =  monitorDataReportMapper.monitorDataChartReportByDay(chartDto,
                UserUtil.getCurrentUser().getUserCondition());
        fillLoseData(data,3, chartDto.getYear(), chartDto.getMonth(), chartDto.getDay());
        return data;
    }

    @Override
    public List<MonitorDataChartReportDeviceVo> monitorDataChartReportByMonth(ChartReportDto chartDto ) {
        List<MonitorDataChartReportDeviceVo> data = monitorDataReportMapper.monitorDataChartReportByMonth(chartDto, UserUtil.getCurrentUser().getUserCondition());
        fillLoseData(data,2,chartDto.getYear(),chartDto.getMonth(),1);
        return data;
    }

    @Override
    public List<MonitorDataChartReportDeviceVo> monthMonitorData(ChartReportDto chartDto) {
        List<MonitorDataChartReportDeviceVo> data = monitorDataReportMapper.monthMonitorData(chartDto, UserUtil.getCurrentUser().getUserCondition());
        fillLoseData(chartDto.getStartTime(), chartDto.getEndTime(), data);
        return data;
    }

    @Override
    public List<MonitorDataChartReportDeviceVo> monitorDataChartReportByYear(ChartReportDto chartDto) {
        List<MonitorDataChartReportDeviceVo> data = monitorDataReportMapper.monitorDataChartReportByYear(chartDto, UserUtil.getCurrentUser().getUserCondition());
        fillLoseData(data,1,chartDto.getYear(),1,1);
        return data;
    }

    @Override
    public List<MonitorDataChartReportDeviceVo> deviceAlarmReport(MonitorDataCompareQueryDto queryDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        LocalDate beginDate = null;
        LocalDate endDate   = null;
        String dateType     = null;
        if (queryDto.getReportType() == null){
            return new ArrayList<>();
        }
        if (ReportTypeEnum.YEAR.getCode().equals(queryDto.getReportType())) {
            beginDate = LocalDate.of(queryDto.getYear(),1,1);
            endDate   = beginDate.plusYears(1);
            dateType  = "month";
        }else  if(ReportTypeEnum.MONTH.getCode().equals(queryDto.getReportType())) {
            beginDate = LocalDate.of(queryDto.getYear(),queryDto.getMonth(),1);
            endDate   = beginDate.plusMonths(1);
            dateType  = "day";
        } else if(ReportTypeEnum.DAY.getCode().equals(queryDto.getReportType() )) {
            beginDate = LocalDate.of(queryDto.getYear(),queryDto.getMonth(),queryDto.getDay());
            endDate   = beginDate.plusDays(1);
            dateType  = "hour";
        } else if (ReportTypeEnum.CUSTOM.getCode().equals(queryDto.getReportType())){
            beginDate = LocalDate.parse(queryDto.getStartTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            endDate   = LocalDate.parse(queryDto.getEndTime(),   DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            dateType  = "day";
        }
        if (beginDate == null || endDate == null){
            return new ArrayList<>();
        }
        List<MonitorDataChartReportDeviceVo> data = monitorDataReportMapper.deviceAlarmReport(dateType, queryDto, loginUser.getUserCondition());
        if (data != null && ReportTypeEnum.CUSTOM.getCode().equals(queryDto.getReportType())){
            fillLoseData(queryDto.getStartTime(), queryDto.getEndTime(), data);
        } else if (data != null){
            fillLoseData(data,queryDto.getReportType(),queryDto.getYear(),queryDto.getMonth(),queryDto.getDay());
        }
        return data;
    }

    @Override
    public List<MonitorDataChartReportDeviceVo> monitorDataQualityReport(MonitorDataCompareQueryDto queryDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        List<MonitorDataChartReportDeviceVo> data = null;
        if (queryDto.getReportType() == null) {
            return null;
        }
        if (ReportTypeEnum.DAY.getCode().equals(queryDto.getReportType())) {
            data = monitorDataReportMapper.monitorDataQualityReportByDay(queryDto, loginUser.getUserCondition());
        } else if(ReportTypeEnum.MONTH.getCode().equals(queryDto.getReportType())){
            data = monitorDataReportMapper.monitorDataQualityReportByMonth(queryDto, loginUser.getUserCondition());
        } else if(ReportTypeEnum.YEAR.getCode().equals(queryDto.getReportType())){
            data = monitorDataReportMapper.monitorDataQualityReportByYear(queryDto, loginUser.getUserCondition());
        } else if (ReportTypeEnum.CUSTOM.getCode().equals(queryDto.getReportType())) {
            data = monitorDataReportMapper.monitorDataQualityReport(queryDto, loginUser.getUserCondition());
        }
        if (data != null && ReportTypeEnum.CUSTOM.getCode().equals(queryDto.getReportType())){
            fillLoseData(queryDto.getStartTime(), queryDto.getEndTime(), data);
        } else  if (data != null){
            fillLoseData(data,queryDto.getReportType(),queryDto.getYear(),queryDto.getMonth(),queryDto.getDay());
        }
        return data;
    }

    @Override
    public List<MonitorDataChartReportDeviceVo> monitorDataEnergyReport(MonitorDataCompareQueryDto dto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        List<MonitorDataChartReportDeviceVo> data = null;
        if (dto.getReportType() == null) {
            return null;
        }
        String startTime = dto.getStartTime();
        String endTime   = dto.getEndTime();
        dto.setSceneType(dto.getSceneType() == 2 || dto.getSceneType() == 3 ? 0 : dto.getSceneType());
        if(dto.getReportType().equals(ReportTypeEnum.DAY.getCode())){
            data = monitorDataReportMapper.monitorDataEnergyReportByDay(dto, loginUser.getUserCondition());
        } else if(dto.getReportType().equals(ReportTypeEnum.MONTH.getCode())){
            data = monitorDataReportMapper.monitorDataEnergyReportByMonth(dto, loginUser.getUserCondition());
        } else if(dto.getReportType().equals(ReportTypeEnum.YEAR.getCode())){
            data = monitorDataReportMapper.monitorDataEnergyReportByYear(dto, loginUser.getUserCondition());
        } else if (dto.getReportType().equals(ReportTypeEnum.CUSTOM.getCode())) {
            data = monitorDataReportMapper.monitorDataEnergyReport(dto, loginUser.getUserCondition());
        }
        if (data != null && dto.getReportType().equals(ReportTypeEnum.CUSTOM.getCode())) {
            fillLoseData(startTime, endTime, data);
        } else if (data != null){
            fillLoseData(data, dto.getReportType(), dto.getYear(), dto.getMonth(), dto.getDay());
        }
        // 场景类型为泵站的不需要转换
        if (dto.getSceneType() == 3){
            return data;
        }
        // 其他场景需要转换为单位“万”
        for(MonitorDataChartReportDeviceVo monitorDataChartReportDeviceDto : data){
            for(MonitorDataChartReportAttributeDto monitorDataChartReportAttributeDto:monitorDataChartReportDeviceDto.getAttributeData()){
                String unit = monitorDataChartReportAttributeDto.getUnit() == null ? "" : monitorDataChartReportAttributeDto.getUnit();
                monitorDataChartReportAttributeDto.setUnit("万"+ unit);
                for(MonitorDataChartReportValueDto monitorDataChartReportValueDto: monitorDataChartReportAttributeDto.getMonitorDataChartReportValue()){
                    monitorDataChartReportValueDto.setData(new BigDecimal(monitorDataChartReportValueDto.getData()).divide(BigDecimal.valueOf(10000),3, RoundingMode.HALF_UP).doubleValue());
                    monitorDataChartReportValueDto.setMonitorData(monitorDataChartReportValueDto.getData()+monitorDataChartReportAttributeDto.getUnit());
                }
            }
        }
        return data;
    }


    @Override
    public List<MonitorDataChartReportDeviceVo> monitorWaterPowerConsumptionReport(MonitorDataCompareQueryDto queryDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        List<MonitorDataChartReportDeviceVo> data = null;
        if (queryDto.getReportType() == null) {
            return null;
        }
        Integer sType = queryDto.getSceneType() == 2 || queryDto.getSceneType() == 3 ? 0 : queryDto.getSceneType() ;
        queryDto.setSceneType(sType);
        if ( ReportTypeEnum.DAY.getCode().equals(queryDto.getReportType())){
            data = monitorDataReportMapper.monitorDataEnergyReportByDay(queryDto, loginUser.getUserCondition());
        } else if(ReportTypeEnum.MONTH.getCode().equals(queryDto.getReportType())){
            data = monitorDataReportMapper.monitorDataEnergyReportByMonth(queryDto, loginUser.getUserCondition());
        } else if(ReportTypeEnum.YEAR.getCode().equals(queryDto.getReportType())){
            data = monitorDataReportMapper.monitorDataEnergyReportByYear(queryDto, loginUser.getUserCondition());
        } else if (ReportTypeEnum.DAY.getCode().equals(queryDto.getReportType())) {
            data = monitorDataReportMapper.monitorDataEnergyReport(queryDto, loginUser.getUserCondition());
        }
        if (data != null && ReportTypeEnum.DAY.getCode().equals(queryDto.getReportType())){
            fillLoseData(queryDto.getStartTime(), queryDto.getEndTime(), data);
        } else if (data != null) {
            fillLoseData(data, queryDto.getReportType(),queryDto.getYear(),queryDto.getMonth(),queryDto.getDay());
        }
        for (MonitorDataChartReportDeviceVo water: data) {
            List<MonitorDataChartReportAttributeDto> newAttrDataList  = new ArrayList();
            MonitorDataChartReportAttributeDto newAttrData = new MonitorDataChartReportAttributeDto();
            List<MonitorDataChartReportAttributeDto> attributeDtos =  water.getAttributeData();
            newAttrData.setAttributeName("水电耗");
            newAttrData.setUnit("kwh/m³");
            newAttrData.setAttributeType("99");
            // 计算水电耗=每日电量/每日用水量*100
            // 缺失每日电量或者每日水量将不进行计算
            if (attributeDtos.size()  == 2) {
                // 获取每日电量和每日水量
                MonitorDataChartReportAttributeDto attributeDto1 = attributeDtos.get(0);
                MonitorDataChartReportAttributeDto attributeDto2 = attributeDtos.get(1);
                // attributeType ==  5 --> 每日电量
                // attributeType ==  4 --> 每日用水量
                if ("5".equals(attributeDto1.getAttributeType())) {
                    Map<Integer,MonitorDataChartReportValueDto> map2 = attributeDto2.getMonitorDataChartReportValue().stream().collect(Collectors.toMap(MonitorDataChartReportValueDto::getDateLabel, a -> a,(k1, k2)->k1));
                    calculation(attributeDto1, map2);
                    newAttrData.setMonitorDataChartReportValue(attributeDto1.getMonitorDataChartReportValue());
                } else {
                    Map<Integer,MonitorDataChartReportValueDto> map1 = attributeDto1.getMonitorDataChartReportValue().stream().collect(Collectors.toMap(MonitorDataChartReportValueDto::getDateLabel, a -> a,(k1, k2)->k1));
                    calculation(attributeDto2, map1);
                    newAttrData.setMonitorDataChartReportValue(attributeDto2.getMonitorDataChartReportValue());
                }
            }
            newAttrDataList.add(newAttrData);
            water.setAttributeData(newAttrDataList);
        }
        return data;
    }


    @Override
    public List<DeviceEntity> getDeviceBySceneTypeName(String sceneTypeName){
        LoginUser loginUser = UserUtil.getCurrentUser();
        return monitorDataReportMapper.getDeviceBySceneTypeName(sceneTypeName,loginUser.getTenantId(),loginUser.getType(),loginUser.getPermissonType(),loginUser.getProgramItemList());
    }

    @Override
    public List<MonitorDataChartReportDeviceVo> monitorDataDeviceReport(MonitorDataChartQueryDto dto){
        List<MonitorDataChartReportDeviceVo> result = null;
        String name = dto.getSearchType() == 1 ? "压力" : ((dto.getSearchType() == 2) ?  "流量" : "水质");
        SceneIdVo sceneIdDto = deviceSceneMapper.findSceneId("管网", name, dto.getDeviceIds().get(0));
        if (sceneIdDto != null) {
            dto.setSceneId(sceneIdDto.getSceneId());
        }
        UserCondition userCondition = UserUtil.getCurrentUser().getUserCondition();
        switch (dto.getReportType()) {
            case 1 :
                result = monitorDataReportMapper.monitorDataDeviceReportByYear(dto, userCondition);
                break;
            case 2 :
                result = monitorDataReportMapper.monitorDataDeviceReportByMonth(dto, userCondition);
                break;
            case 3 :
                result = monitorDataReportMapper.monitorDataDeviceReportByDay(dto, userCondition);
                break;
            case 4 :
                result = monitorDataReportMapper.monitorDataDeviceReport(dto, userCondition);
                break;
            default:
                break;
        }
        if (result != null && ReportTypeEnum.CUSTOM.getCode().equals(dto.getReportType())){
            fillLoseData(dto.getStartTime(), dto.getEndTime(), result);
        } else if (result != null){
            fillLoseData(result, dto.getReportType(), dto.getYear(), dto.getMonth(), dto.getDay());
        }
        return result;
    }



    @Override
    public GeneralViewResults monitorDataGeneralView() {
        GeneralViewResults generalViewResults = new GeneralViewResults();
        return generalViewResults;
    }

    @Override
    public List<DeviceWaterSupplyVo> deviceWaterSupplie() {
        LoginUser loginUser = UserUtil.getCurrentUser();
        String tenantId = loginUser.getTenantId();
        List<DeviceWaterSupplyVo> deviceWaterSupplies = monitorDataReportMapper.getDeviceWaterFor30Day(tenantId,loginUser.getType(),loginUser.getPermissonType(),loginUser.getProgramItemList());

        LocalDate localDate = LocalDate.now();
        BigDecimal amountCountDay  =  getAmountCount(null,null,"水厂",3,1);
        DeviceWaterSupplyVo deviceWaterSupplyDay = new DeviceWaterSupplyVo();
        deviceWaterSupplyDay.setOrderNo( 1);
        deviceWaterSupplyDay.setAmount(amountCountDay != null?amountCountDay.divide(BigDecimal.valueOf(10000),3, RoundingMode.HALF_UP):BigDecimal.ZERO);
        deviceWaterSupplyDay.setYear(localDate.getYear());
        deviceWaterSupplyDay.setMonth(localDate.getMonthValue());
        deviceWaterSupplyDay.setDay(localDate.getDayOfMonth());
        deviceWaterSupplyDay.setDate(localDate);
        deviceWaterSupplies.add(0, deviceWaterSupplyDay);

        int length = 15;
        for (int i = 0; i < length; i++) {
            LocalDate newLocalDate = localDate.plusDays(-i);
            if (i == deviceWaterSupplies.size()
                    || !newLocalDate.isEqual(LocalDate.of(deviceWaterSupplies.get(i).getYear(),
                    deviceWaterSupplies.get(i).getMonth(),
                    deviceWaterSupplies.get(i).getDay()))) {
                DeviceWaterSupplyVo deviceWaterSupply = new DeviceWaterSupplyVo();
                deviceWaterSupply.setOrderNo(i + 1);
                deviceWaterSupply.setAmount(BigDecimal.ZERO);
                deviceWaterSupply.setYear(newLocalDate.getYear());
                deviceWaterSupply.setMonth(newLocalDate.getMonthValue());
                deviceWaterSupply.setDay(newLocalDate.getDayOfMonth());
                deviceWaterSupply.setDate(newLocalDate);
                deviceWaterSupplies.add(i, deviceWaterSupply);
            } else {
                deviceWaterSupplies.get(i).setOrderNo(i + 1);
                deviceWaterSupplies.get(i).setDate(newLocalDate);
            }
        }
        deviceWaterSupplies.sort(Comparator.comparing(DeviceWaterSupplyVo::getOrderNo).reversed());
        return deviceWaterSupplies;
    }

    @Override
    public DeviceWaterAmount deviceWaterAmount() {
        LoginUser loginUser = UserUtil.getCurrentUser();
        LocalDate localDate = LocalDate.now();
        Map<Integer, MonitorDataEntity> monitorDataMap = getIntegerMonitorDataEntityMap(loginUser);
        DeviceWaterAmount deviceWaterAmount = new DeviceWaterAmount();
        // 水厂获取实时流量
        addWaterSupplyAmountForNow(deviceWaterAmount, monitorDataMap);
        // 水源累计瞬时流量
        addWaterIntakeAmountForNow(deviceWaterAmount, monitorDataMap);
        // 3供水 4取水
        addWaterSupplyAmountForDay(deviceWaterAmount, monitorDataMap, localDate);
        addWaterIntakeAmountForDay(deviceWaterAmount, monitorDataMap, localDate);

        DeviceWaterDto dto = convertDeviceWaterDto(3,  SceneTypeEnum.WATER_WORKS.getMessage(), localDate);
        BigDecimal waterSupplyAmountForMonth = waterSupplyAmountForMonth(dto);
        BigDecimal waterSupplyAmountForYear  = waterSupplyAmountForYear(dto);
        // 水厂当月流量
        if (deviceWaterAmount.getWaterSupplyAmountForDay() == null) {
            deviceWaterAmount.setWaterSupplyAmountForMonth(waterSupplyAmountForMonth);
        } else {
            deviceWaterAmount.setWaterSupplyAmountForMonth(waterSupplyAmountForMonth.add(deviceWaterAmount.getWaterSupplyAmountForDay()));
        }
        // 水厂当年流量
        if (deviceWaterAmount.getWaterSupplyAmountForMonth() == null) {
            deviceWaterAmount.setWaterSupplyAmountForYear(waterSupplyAmountForYear);
        } else {
            deviceWaterAmount.setWaterSupplyAmountForYear(waterSupplyAmountForYear.add(deviceWaterAmount.getWaterSupplyAmountForMonth()));
        }

        DeviceWaterDto queryDto = convertDeviceWaterDto(4,  SceneTypeEnum.WATER_SOURCE.getMessage(), localDate);
        BigDecimal waterIntakeAmountForMonth = waterSupplyAmountForMonth(queryDto);
        BigDecimal waterIntakeAmountForYear  = waterSupplyAmountForYear(queryDto);

        // 水源当月流量
        if (deviceWaterAmount.getWaterIntakeAmountForDay() == null) {
            deviceWaterAmount.setWaterIntakeAmountForMonth(waterIntakeAmountForMonth);
        } else {
            deviceWaterAmount.setWaterIntakeAmountForMonth(waterIntakeAmountForMonth.add(deviceWaterAmount.getWaterIntakeAmountForDay()));
        }
        // 水源当年流量
        if (deviceWaterAmount.getWaterIntakeAmountForMonth() == null) {
            deviceWaterAmount.setWaterIntakeAmountForYear(waterIntakeAmountForYear);
        } else {
            deviceWaterAmount.setWaterIntakeAmountForYear(waterIntakeAmountForYear.add(deviceWaterAmount.getWaterIntakeAmountForMonth()));
        }
        return deviceWaterAmount;
    }



    @Override
    public List<SceneAlarmVo> sceneAlarms() {
        LoginUser loginUser = UserUtil.getCurrentUser();
        String tenantId = loginUser.getTenantId();
        return monitorDataReportMapper.getAlarmInfoForScene(tenantId,loginUser.getType(),loginUser.getPermissonType(),loginUser.getProgramItemList());
    }

    @Override
    public List<SceneNormalRateVo> sceneNormalRates() {
        List<SceneNormalRateVo> sceneNormalRates = new ArrayList<>();
        UserCondition condition = UserUtil.getCurrentUser().getUserCondition();
        // 水质
        SceneNormalRateVo sceneNormalRate1 = monitorDataReportMapper.getQualificationForScene(-1, condition);
        // PH
        SceneNormalRateVo sceneNormalRate2 = monitorDataReportMapper.getQualificationForScene(8, condition);
        // 浊度
        SceneNormalRateVo sceneNormalRate3 = monitorDataReportMapper.getQualificationForScene(10, condition);
        // 余氯
        SceneNormalRateVo sceneNormalRate4 = monitorDataReportMapper.getQualificationForScene(11, condition);

        if (sceneNormalRate1 == null){
            sceneNormalRate1 = new SceneNormalRateVo();
        }
        if (sceneNormalRate2 == null){
            sceneNormalRate2 = new SceneNormalRateVo();
        }
        if (sceneNormalRate3 == null){
            sceneNormalRate3 = new SceneNormalRateVo();
        }
        if (sceneNormalRate4 == null){
            sceneNormalRate4 = new SceneNormalRateVo();
        }
        sceneNormalRate1.setTypeName("水质");
        sceneNormalRate2.setTypeName("PH");
        sceneNormalRate3.setTypeName("浊度");
        sceneNormalRate4.setTypeName("余氯");
        sceneNormalRates.add(sceneNormalRate1);
        sceneNormalRates.add(sceneNormalRate2);
        sceneNormalRates.add(sceneNormalRate3);
        sceneNormalRates.add(sceneNormalRate4);
        return sceneNormalRates;
    }

    @Override
    public SceneWaterPressure sceneWaterPressure(String sceneType) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        UserCondition condition = UserUtil.getCurrentUser().getUserCondition();
        Map<Integer, MonitorDataEntity> monitorDataMap = getIntegerMonitorDataEntityMap(loginUser);
        List<DeviceWaterDetailVo> devicePressureWaterDetailsForNow = monitorDataReportMapper.getDeviceWaterDetailForNow(sceneType, 13, condition);
        List<SceneWaterAmount> sceneWaterPressureAmounts = sceneWaterPressureAmounts(devicePressureWaterDetailsForNow, monitorDataMap);
        // 进行压力分组
        BigDecimal amountSum = BigDecimal.ZERO;
        SceneWaterPressure sceneWaterPressure = new SceneWaterPressure();
        SceneWaterAmount amountMax = null;
        SceneWaterAmount amountMin = null;
        for (SceneWaterAmount waterPressure : sceneWaterPressureAmounts) {
            if (StringUtils.isBlank(waterPressure.getSceneName()) || waterPressure.getWaterAmount() == null) {
                continue;
            }
            amountSum = amountSum.add(waterPressure.getWaterAmount());
            BigDecimal amount = waterPressure.getWaterAmount();
            amountMax = amountMax == null || amount.compareTo(amountMax.getWaterAmount()) == 1 ? waterPressure : amountMax;
            amountMin = amountMin == null || amount.compareTo(amountMin.getWaterAmount()) == -1 ? waterPressure : amountMin;

            if (amount.compareTo(new BigDecimal(0.15)) == -1) {
                sceneWaterPressure.setPressureLevel1(sceneWaterPressure.getPressureLevel1() + 1);
            } else if (amount.compareTo(new BigDecimal(0.15)) != 1 && amount.compareTo(new BigDecimal(0.30)) == -1) {
                sceneWaterPressure.setPressureLevel2(sceneWaterPressure.getPressureLevel2() + 1);
            } else if (amount.compareTo(new BigDecimal(0.30)) != -1 && amount.compareTo(new BigDecimal(0.40)) == -1) {
                sceneWaterPressure.setPressureLevel3(sceneWaterPressure.getPressureLevel3() + 1);
            } else if (amount.compareTo(new BigDecimal(0.40)) != -1 && amount.compareTo(new BigDecimal(0.50)) == -1) {
                sceneWaterPressure.setPressureLevel4(sceneWaterPressure.getPressureLevel4() + 1);
            } else if (amount.compareTo(new BigDecimal(0.50)) != -1) {
                sceneWaterPressure.setPressureLevel5(sceneWaterPressure.getPressureLevel5() + 1);
            }
        }
        if (sceneWaterPressureAmounts.size()>0) {
            sceneWaterPressure.setAvgPressureValue(amountSum.divide(new BigDecimal(sceneWaterPressureAmounts.size()),2,BigDecimal.ROUND_HALF_UP));
        }
        if (amountMax != null) {
            sceneWaterPressure.setMaxPressureSceneName(amountMax.getSceneName());
            sceneWaterPressure.setMaxPressureValue(amountMax.getWaterAmount());
        }
        if (amountMax != null) {
            sceneWaterPressure.setMinPressureSceneName(amountMin.getSceneName());
            sceneWaterPressure.setMinPressureValue(amountMin.getWaterAmount());
        }
        List<Integer> pressureLevels = new ArrayList<>();
        pressureLevels.add(sceneWaterPressure.getPressureLevel1());
        pressureLevels.add(sceneWaterPressure.getPressureLevel2());
        pressureLevels.add(sceneWaterPressure.getPressureLevel3());
        pressureLevels.add(sceneWaterPressure.getPressureLevel4());
        pressureLevels.add(sceneWaterPressure.getPressureLevel5());
        sceneWaterPressure.setPressureLevels(pressureLevels);
        return sceneWaterPressure;
    }


    @Override
    public List<SceneWaterAmount> sceneWaterAmounts() {
        LoginUser loginUser = UserUtil.getCurrentUser();
        // 查询设备数据
        Map<Integer, MonitorDataEntity> monitorDataMap = getIntegerMonitorDataEntityMap(loginUser);
        LocalDate localDate = LocalDate.now();

        DeviceWaterDto dto = new DeviceWaterDto();
        dto.setSceneTypeName("水厂");
        dto.setParmType(3);
        dto.setYear(localDate.plusDays(-1).getYear());
        dto.setMonth( localDate.plusDays(-1).getMonthValue());
        dto.setDay(localDate.plusDays(-1).getDayOfMonth());
        List<DeviceWaterDetailVo> deviceSupplyWaterDetailsForDay = monitorDataReportMapper.getDeviceWaterDetailForDay(dto,loginUser.getUserCondition());

        List<SceneWaterAmount> sceneWaterAmounts = new ArrayList<>();
        deviceSupplyWaterDetailsForDay.stream()
                .filter(item -> StringUtils.isNotBlank(item.getSceneName()) && item != null && item.getLatestValue() != null )
                .collect(Collectors.groupingBy(item -> item.getSceneName(), Collectors.toList()))
                .forEach((key, value) -> {
                    SceneWaterAmount sceneWaterAmount = new SceneWaterAmount();
                    sceneWaterAmount.setSceneName(key);
                    sceneWaterAmount.setWaterAmount(BigDecimal.ZERO);
                    value.stream().forEach(deviceWaterDetail -> {
                        MonitorDataEntity monitorDataEntity = monitorDataMap.get(deviceWaterDetail.getDeviceId());
                        if (monitorDataEntity != null && monitorDataEntity.getDataValues() != null && monitorDataEntity.getDataValues().size() > 0) {
                            monitorDataEntity.getDataValues().stream()
                                    .filter(monitorDataValueEntity ->
                                            monitorDataValueEntity.getAttributeId().equals(deviceWaterDetail.getAttributeId())
                                    )
                                    .forEach(monitorDataValueEntity ->
                                            //累计当天流量
                                            sceneWaterAmount.setWaterAmount((sceneWaterAmount.getWaterAmount().add(
                                                    new BigDecimal(monitorDataValueEntity.getDataValue()).subtract(deviceWaterDetail.getLatestValue()))))
                                    );
                        }
                    });
                    sceneWaterAmount.setWaterAmount(sceneWaterAmount.getWaterAmount().divide(BigDecimal.valueOf(10000),3, RoundingMode.HALF_UP));
                    sceneWaterAmounts.add(sceneWaterAmount);
                });
        //倒序排序
        sceneWaterAmounts.sort(Comparator.comparing(SceneWaterAmount::getWaterAmount).reversed());
        return sceneWaterAmounts;
    }

    @Override
    public List<WaterSupplyChart> waterSupplyCharts(String sceneTypeName) {
        BigDecimal multipleData;
        if (SceneTypeEnum.PUMPING_STATION.getMessage().equals(sceneTypeName)) {
            multipleData = new BigDecimal("1");
        } else {
            multipleData = new BigDecimal("10000");
        }
        LoginUser loginUser = UserUtil.getCurrentUser();
        String tenantId = loginUser.getTenantId();
        List<WaterSupplyDataVo> data = monitorDataReportMapper.getWaterSupplyData(tenantId, sceneTypeName, loginUser.getType(), loginUser.getPermissonType(), loginUser.getProgramItemList());
        List<WaterSupplyChart> waterSupplyCharts = new ArrayList<>();
        data.stream().collect(Collectors.groupingBy(item -> item.getYear() + "-" + item.getMonth() + "-" + item.getDay()))
            .forEach((key, value) -> {
                addWaterSupplyCharts(key, value, waterSupplyCharts, multipleData, true);
            });
        waterSupplyCharts.sort(Comparator.comparing(WaterSupplyChart::getSort));
        int length = 7;
        for (int i = 0; i < length; i++) {
            if (i == waterSupplyCharts.size() || !waterSupplyCharts.get(i).getSort().equals(i + 1)) {
                waterSupplyCharts.add(i, new WaterSupplyChart(i + 1));
            }
        }
        waterSupplyCharts.sort(Comparator.comparing(WaterSupplyChart::getSort).reversed());
        return waterSupplyCharts;
    }



    @Override
    public List<WaterSupplyChart> waterSupplyChartsForCurrentMonth(String sceneTypeName,Long sceneId) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        String tenantId = loginUser.getTenantId();
        List<Long> sceneIds = sceneService.findByParentIdsLike(sceneId);
        List<WaterSupplyDataVo> data = monitorDataReportMapper.getWaterSupplyDataForCurrentMonth(tenantId, sceneTypeName, sceneIds, loginUser.getType(), loginUser.getPermissonType(), loginUser.getProgramItemList());
        List<WaterSupplyChart> waterSupplyCharts = new ArrayList<>();
        BigDecimal per = BigDecimal.valueOf(1);
        if (!SceneTypeEnum.PUMPING_STATION.getMessage().equals(sceneTypeName)){
            per = BigDecimal.valueOf(10000);
        }
        BigDecimal finalPer = per;
        data.stream().collect(Collectors.groupingBy(item -> item.getYear() + "-" + item.getMonth() + "-" + item.getDay()))
            .forEach((key, value) -> {
                addWaterSupplyCharts(key, value, waterSupplyCharts, finalPer, false);
            });
        waterSupplyCharts.sort(Comparator.comparing(WaterSupplyChart::getSort));
        // 获取当日水量
        BigDecimal waterDataAmountCountMonth = getAmountCount(null, sceneId.intValue(), sceneTypeName, 3, 1);
        // 获取当日电耗
        BigDecimal powerDataAmountCountMonth = getAmountCount(null, sceneId.intValue(), sceneTypeName, 5, 1);
        LocalDate localDate = LocalDate.now();
        WaterSupplyChart waterSupplyChart = new WaterSupplyChart();
        waterSupplyChart.setDate(LocalDate.now().getYear() + "-" + LocalDate.now().getMonthValue() + "-" + LocalDate.now().getDayOfMonth());
        waterSupplyChart.setWaterData(waterDataAmountCountMonth.divide(finalPer, 3, RoundingMode.HALF_UP));
        waterSupplyChart.setPowerData(powerDataAmountCountMonth.divide(finalPer, 3, RoundingMode.HALF_UP));
        waterSupplyChart.setSort(localDate.getDayOfMonth());

        Integer maxDay =  LocalDate.now().getDayOfMonth();
        for(int i= 0; i < maxDay; i++) {
            if (i + 1 == localDate.getDayOfMonth()) {
                waterSupplyCharts.add(i, waterSupplyChart);
            } else if (i == waterSupplyCharts.size() || !waterSupplyCharts.get(i).getSort().equals(i+1)) {
                WaterSupplyChart temp=   new WaterSupplyChart(i + 1, localDate.getYear() + "-" + localDate.getMonthValue() + "-" + (i + 1));
                temp.setWaterData(BigDecimal.valueOf(0));
                temp.setPowerData(BigDecimal.valueOf(0));
                waterSupplyCharts.add(i, temp);
            }
        }
        waterSupplyCharts.sort(Comparator.comparing(WaterSupplyChart::getSort));
        return waterSupplyCharts;
    }

    @Override
    public List<WaterSupplyChart> waterSupplyChartsByMonth(String sceneTypeName, Integer companyOrgId) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        String tenantId     = loginUser.getTenantId();
        List<WaterSupplyDataVo> waterSupplyDatas = monitorDataReportMapper.getWaterSupplyDataByMonth(tenantId,companyOrgId,sceneTypeName,
                loginUser.getType(),loginUser.getPermissonType(),loginUser.getProgramItemList());
        // 获取本月水量
        BigDecimal waterDataAmountCountMonth = getAmountCount(companyOrgId,null, sceneTypeName, 3,2 );
        // 获取本月电耗
        BigDecimal powerDataAmountCountMonth = getAmountCount(companyOrgId,null, sceneTypeName, 5,2 );

        List<WaterSupplyChart> waterSupplyCharts = new ArrayList<>();
        waterSupplyDatas.stream().collect(Collectors.groupingBy(item -> item.getYear() + "-" + item.getMonth())).forEach((key, value) -> {
            WaterSupplyChart waterSupplyChart = new WaterSupplyChart();
            waterSupplyChart.setDate(key);
            value.stream().forEach(waterSupplyData -> {
                Period period = Period.between(LocalDate.of(waterSupplyData.getYear(), waterSupplyData.getMonth(),1), LocalDate.now());
                waterSupplyChart.setSort(period.getMonths()+1);
                BigDecimal amount = BigDecimalUtils.divide(waterSupplyData.getAmount(), 10000, 3);
                if (waterSupplyData.getParmType() == DeviceParamTypeEnum.WATER_SUPPLY.getCode()) {
                    waterSupplyChart.setWaterData(amount);
                } else if (waterSupplyData.getParmType() == DeviceParamTypeEnum.KWH.getCode()) {
                    waterSupplyChart.setPowerData(amount);
                }
            });
            waterSupplyCharts.add(waterSupplyChart);
        });
        WaterSupplyChart waterSupplyChart = new WaterSupplyChart();
        waterSupplyChart.setSort(1);
        waterSupplyChart.setDate(LocalDate.now().getYear()+"-"+LocalDate.now().getMonthValue());
        waterSupplyChart.setPowerData(BigDecimalUtils.divide(powerDataAmountCountMonth,10000, 3));
        waterSupplyChart.setWaterData(BigDecimalUtils.divide(waterDataAmountCountMonth,10000, 3));
        waterSupplyCharts.add(waterSupplyChart);
        waterSupplyCharts.sort(Comparator.comparing(WaterSupplyChart::getSort));
        int length = 6;
        for(int i = 0;i < length; i++){
            if (i == waterSupplyCharts.size() || !waterSupplyCharts.get(i).getSort().equals(i+1)){
                waterSupplyCharts.add(i,new WaterSupplyChart(i+1, 1));
            }
        }
        waterSupplyCharts.sort(Comparator.comparing(WaterSupplyChart::getSort).reversed());
        return waterSupplyCharts;
    }

    @Override
    public Map<Integer, MonitorDataEntity> getIntegerMonitorDataEntityMap(LoginUser loginUser) {
        // 查询设备编码
        List<String> deviceCodes = monitorDataReportMapper.selectDeviceCode(loginUser.getTenantId(),loginUser.getType(),loginUser.getPermissonType(),loginUser.getProgramItemList());
        // 根据编码获取redis中的实时数据
        // 将获取到 实时数据转换为map，方便匹配数据deviceId
        return getCacheMonitorData(deviceCodes).stream().collect(Collectors.toMap(MonitorDataEntity::getDeviceId, a -> a, (k1, k2) -> k1));
    }

    @Override
    public Date getLastCollectTime(Integer companyOrgId, Integer sceneId, String sceneTypeName){
       LoginUser loginUser = UserUtil.getCurrentUser();
       // 查询设备编码
       List<String> deviceCodes = monitorDataReportMapper.selectDeviceCodeByConditions(companyOrgId, sceneId, sceneTypeName, loginUser.getUserCondition());
       // 根据编码获取redis中的实时数据
       List<MonitorDataEntity> monitorDataEntities = getCacheMonitorData(deviceCodes);
       if (monitorDataEntities.size()>0) {
           monitorDataEntities.sort(Comparator.comparing(MonitorDataEntity::getCollectDate).reversed());
           return monitorDataEntities.get(0).getCollectDate();
       }
       return  null;
   }

    /**
     * 查询设备某个属性值
     * @param deviceCode
     * @param attributeId
     * @return
     */
    @Override
    public BigDecimal getDeviceAttributeValue(String deviceCode,Long attributeId) {
       BigDecimal amount = BigDecimal.ZERO;
       // 先取缓存里的数据
       byte[] bytes = redisUtil.get(("sms_water_" + deviceCode).getBytes());
       if (bytes == null || bytes.length == 0) {
           return amount;
       }
       MonitorDataEntity entity = ((MonitorDataEntity) ByteArrayUtils.bytesToObject(bytes).get());
       for (MonitorDataValueEntity monitorDataValueEntity : entity.getDataValues()) {
            if (monitorDataValueEntity.getAttributeId().equals(attributeId)) {
                // 获取当前数据
                amount = new BigDecimal(monitorDataValueEntity.getDataValue());
            }
       }
       return amount;
    }

    @Override
    public BigDecimal getAmountCount(Integer sceneId, Integer paramType,Integer searchType){
         return getAmountCount(null, sceneId, null, paramType, searchType);
    }
    /**
     *
     * @param companyOrgId 公司id
     * @param sceneId 场景类型
     * @param sceneTypeName 场景类型
     * @param parmType  标记值
     * @param searchType 查询类型：1日 2月 3年
     * @return
     */
    @Override
    public BigDecimal getAmountCount(Integer companyOrgId, Integer sceneId, String sceneTypeName, Integer parmType,Integer searchType){
        LoginUser loginUser = UserUtil.getCurrentUser();
        // 查询设备编码
        List<String> deviceCodes = monitorDataReportMapper.selectDeviceCodeByConditions(companyOrgId,  sceneId, sceneTypeName, loginUser.getUserCondition());
        // 根据编码获取redis中的实时数据
        List<MonitorDataEntity> monitorDataEntities = getCacheMonitorData(deviceCodes);
        // 将获取到 实时数据转换为map，方便匹配数据deviceId
        Map<Integer, MonitorDataEntity> monitorDataMap =  monitorDataEntities.stream().collect(Collectors.toMap(MonitorDataEntity::getDeviceId, a -> a, (k1, k2) -> k1));
        LocalDate localDate = LocalDate.now();
        DeviceWaterDto dto = new DeviceWaterDto();
        dto.setCompanyOrgId(companyOrgId);
        dto.setSceneId(sceneId);
        dto.setSceneTypeName(sceneTypeName);
        dto.setYear(localDate.plusDays(-1).getYear());
        dto.setMonth(localDate.plusDays(-1).getMonthValue());
        dto.setDay(localDate.plusDays(-1).getDayOfMonth());
        List<DeviceWaterDetailVo> deviceSupplyWaterDetailsForDay = monitorDataReportMapper.getDeviceWaterDetailForDay(dto,loginUser.getUserCondition());
        // 获取实时数据并计算出当天数据
        BigDecimal amountDay = amountDay(deviceSupplyWaterDetailsForDay, monitorDataMap);
        if (searchType == null || searchType == 1){
            return amountDay;
        }
        BigDecimal amountMonth = BigDecimal.ZERO;

        DeviceWaterDto queryDto = new DeviceWaterDto();
        queryDto.setCompanyOrgId(companyOrgId);
        queryDto.setSceneId(sceneId);
        queryDto.setSceneTypeName(sceneTypeName);
        queryDto.setParmType(parmType);
        queryDto.setYear(localDate.getYear());
        queryDto.setMonth(localDate.getMonthValue());
        // 当月数据
        BigDecimal waterSupplyAmountForMonth = monitorDataReportMapper.getDeviceWaterDetailForMonth(queryDto, loginUser.getUserCondition());
        if (waterSupplyAmountForMonth != null) {
            amountMonth = waterSupplyAmountForMonth.add(amountDay);
        }
        int month = 2;
        int year  = 3;
        if(searchType != null && searchType == month){
            return amountMonth;
        }
        //当年数据
        BigDecimal amountYear =BigDecimal.ZERO;
        BigDecimal waterSupplyAmountForYear = monitorDataReportMapper.getDeviceWaterDetailForYear(queryDto, loginUser.getUserCondition());
        if (waterSupplyAmountForYear != null) {
            amountYear = waterSupplyAmountForYear.add(amountMonth);
        }
        if(searchType != null && searchType == year){
            return amountYear;
        }
        return BigDecimal.ZERO;
    }

    @Override
    public BigDecimal getUseAmount(Integer companyOrgId, Integer searchType) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        BigDecimal amountMonth =  monitorDataReportMapper.getUseAmount(companyOrgId, loginUser.getTenantId(), searchType, loginUser.getType(), loginUser.getPermissonType(), loginUser.getProgramItemList());
        if (amountMonth == null) {
            amountMonth = BigDecimal.ZERO;
        }
        return amountMonth;
    }

    /**
    * 根据编码获取redis中的实时数据
    * @author Andy
    * @date 10:02 2021/8/17
    * @param deviceCodes:
    * @return java.util.List<com.zcxk.charge.core.entity.MonitorDataEntity>
    **/
    private List<MonitorDataEntity> getCacheMonitorData(List<String> deviceCodes){
        List<MonitorDataEntity> monitorDataEntities = new ArrayList<>();
        // 先取缓存里的数据
        for (String deviceCode : deviceCodes) {
            byte[] bytes = redisUtil.get(("sms_water_" + deviceCode).getBytes());
            if (bytes != null && bytes.length > 0) {
                monitorDataEntities.add((MonitorDataEntity) ByteArrayUtils.bytesToObject(bytes).get());
            }
        }
        return monitorDataEntities;
    }

    /**
    * 获取实时数据并计算出当天数据
    * @author Andy
    * @date 10:03 2021/8/17
    * @param deviceSupplyWaterDetailsForDay:
    * @return java.math.BigDecimal
    **/
    private BigDecimal amountDay(List<DeviceWaterDetailVo> deviceSupplyWaterDetailsForDay, Map<Integer, MonitorDataEntity> monitorDataMap ){
        BigDecimal amountDay = BigDecimal.ZERO;
        for (DeviceWaterDetailVo deviceWaterDetail : deviceSupplyWaterDetailsForDay) {
            MonitorDataEntity monitorDataEntity = monitorDataMap.get(deviceWaterDetail.getDeviceId());
            if (monitorDataEntity != null && !CollectionUtils.isEmpty(monitorDataEntity.getDataValues())
                     && deviceWaterDetail.getLatestValue() != null) {
                for (MonitorDataValueEntity monitorDataValueEntity : monitorDataEntity.getDataValues()) {
                    if (monitorDataValueEntity.getAttributeId().equals(deviceWaterDetail.getAttributeId())) {
                        //累计当天数据
                        amountDay = amountDay.add(new BigDecimal(monitorDataValueEntity.getDataValue()).subtract(deviceWaterDetail.getLatestValue()));
                    }
                }
            }
        }
        return amountDay;
    }

    /**
    * 数据补充
    * @author Andy
    * @date 15:51 2021/8/17
    * @param startTime:
    * @param endTime:
    * @param monitorDataChartReportDeviceDtos:
    * @return void
    **/
    private void fillLoseData(String startTime, String endTime,List<MonitorDataChartReportDeviceVo> monitorDataChartReportDeviceDtos){
        LocalDateTime  startDate =  LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime  endDate   =  LocalDateTime.parse(endTime,   DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        int startDay;
        int endDay;
        if (startDate.getYear() == endDate.getYear()){
            boolean sameMonth = startDate.getMonth().getValue() == endDate.getMonth().getValue();
            for (int i = startDate.getMonth().getValue(); i <= endDate.getMonth().getValue(); i++){
                startDay = (sameMonth || i == startDate.getMonth().getValue()) ? startDate.getDayOfMonth() : 1;
                endDay   = sameMonth  || i == endDate.getMonth().getValue() ? endDate.getDayOfMonth() :
                        startDate.withMonth(i).with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                fillLoseData(monitorDataChartReportDeviceDtos,2, startDate.getYear(), i, startDay, endDay);
            }
        } else {
            int start;
            int end;
            for (int i = startDate.getYear(); i <= endDate.getYear(); i++){
                start = i == startDate.getYear() ? startDate.getMonth().getValue() : 1;
                end   = i == endDate.getYear()   ? endDate.getMonthValue() : 12;
                for (int m = start; m <= end; m++){
                    startDay =  i == startDate.getYear() && m == start ? startDate.getDayOfMonth() : 1;
                    endDay   =  i == endDate.getYear() && m ==  endDate.getMonth().getValue() ?
                            endDate.getDayOfMonth() : startDate.withMonth(m).with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                    fillLoseData(monitorDataChartReportDeviceDtos,2, i, m, startDay, endDay);
                }
            }
        }
        for (MonitorDataChartReportDeviceVo dto : monitorDataChartReportDeviceDtos ) {
            for (MonitorDataChartReportAttributeDto attributeDto : dto.getAttributeData() ) {
                Collections.sort(attributeDto.getMonitorDataChartReportValue());
            }
        }
    }


    private static void fillLoseData(List<MonitorDataChartReportDeviceVo> monitorDataChartReportDeviceDtos,Integer type,Integer year,Integer month
            ,int startTime, int endTime) {
        LocalDateTime localDateTime = LocalDateTime.of(year, month,1,0,0,0);
        for(MonitorDataChartReportDeviceVo monitorDataChartReportDeviceDto: monitorDataChartReportDeviceDtos){
            if(monitorDataChartReportDeviceDto == null || monitorDataChartReportDeviceDto.getAttributeData() == null) {
                continue;
            }
            for(MonitorDataChartReportAttributeDto monitorDataChartReportAttributeDto:monitorDataChartReportDeviceDto.getAttributeData()){
                if (monitorDataChartReportAttributeDto == null ||
                        monitorDataChartReportAttributeDto.getMonitorDataChartReportValue() == null) {
                    continue;
                }
                String unit = monitorDataChartReportAttributeDto.getUnit();
                unit = StringUtils.isNotBlank(unit) ? unit : "";
                List<MonitorDataChartReportValueDto> monitorDataChartReportValueDtos = monitorDataChartReportAttributeDto.getMonitorDataChartReportValue();
                Map<String,MonitorDataChartReportValueDto> mmp = toMap(monitorDataChartReportValueDtos);
                for (int i = startTime; i <= endTime; i++ ) {
                    MonitorDataChartReportValueDto monitorDataChartReportValueDto =  mmp.get(year + "" + month + "" + i);
                    if (monitorDataChartReportValueDto == null){
                        monitorDataChartReportValueDto = new MonitorDataChartReportValueDto();
                        monitorDataChartReportValueDto.setData(0.0);
                        LocalDateTime dateTime = yearMonthDay(year,month, i);
                        setDateStringLabel(localDateTime, dateTime, i-1, monitorDataChartReportValueDto, type, true);
                        monitorDataChartReportValueDto.setDate(dateTime);
                        monitorDataChartReportValueDto.setDateLabel(i);
                        monitorDataChartReportValueDto.setMonitorData("");
                        monitorDataChartReportValueDtos.add(monitorDataChartReportValueDto);
                    } else {
                        monitorDataChartReportValueDto.setMonitorData(monitorDataChartReportValueDto.getData()+""+unit);
                        LocalDateTime dateTime = yearMonthDay(year,month, i);
                        if (StringUtils.isEmpty(monitorDataChartReportValueDto.getDateStringLabel())){
                            setDateStringLabel(localDateTime, dateTime, i , monitorDataChartReportValueDto, type, false);
                        }
                    }
                }
            }
        }
    }

    private static LocalDateTime yearMonthDay(Integer year, Integer month, Integer day){
        int minMonth = 10;
        String monthStr = month + "";
        String dayStr   = day + "";
        if (month < minMonth) {
            monthStr = 0 + "" + month;
        }
        if (day < minMonth) {
            dayStr = 0 + "" + day;
        }
        String time = year+ "-" + monthStr + "-" +  dayStr;
        return LocalDateTime.parse(time + " 00:00:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") );
    }

    private static Map<String, MonitorDataChartReportValueDto> toMap (List<MonitorDataChartReportValueDto> monitorDataChartReportValueDtos) {
        LocalDateTime localDateTime = null;
        Map<String, MonitorDataChartReportValueDto> result = new HashMap<>();
        for (MonitorDataChartReportValueDto monitorDataChartReportValueDto:monitorDataChartReportValueDtos) {
            if (StringUtils.isEmpty(monitorDataChartReportValueDto.getDateStringLabel())) {
                localDateTime = monitorDataChartReportValueDto.getDate();
            } else {
                localDateTime = LocalDateTime.parse(monitorDataChartReportValueDto.getDateStringLabel() + " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
            result.put(localDateTime.getYear() + "" +  localDateTime.getMonthValue() +"" + localDateTime.getDayOfMonth() , monitorDataChartReportValueDto);
        }
        return result;
    }

    private static void setDateStringLabel(LocalDateTime localDateTime,LocalDateTime dateTime, int i , MonitorDataChartReportValueDto monitorDataChartReportValueDto,
                                           Integer type, boolean isNull) {
        if (type == null) {
            return;
        }
        if(type ==3){
            dateTime= isNull ? localDateTime.plusHours(i) : dateTime;
            monitorDataChartReportValueDto.setDateStringLabel(
                    dateTime.getYear()+"-"+ String.format("%02d",dateTime.getMonthValue())+"-"+  String.format("%02d",dateTime.getDayOfMonth())
                            + " "+String.format("%02d",dateTime.getHour())+":00");
        }
        if(type ==2){
            //dateTime = isNull ? localDateTime.plusDays(i): dateTime;
            monitorDataChartReportValueDto.setDateStringLabel(dateTime.getYear()+"-" + String.format("%02d",dateTime.getMonthValue())+
                    "-"+ String.format("%02d",dateTime.getDayOfMonth()));
        }
        if (type ==1) {
            dateTime = isNull ? localDateTime.plusMonths(i) : dateTime;
            monitorDataChartReportValueDto.setDateStringLabel(dateTime.getYear()+"-" + String.format("%02d", dateTime.getMonthValue()));
        }
    }

    /**
     * 计算水电耗=每日电量/每日用水量*100
     * @author Andy
     * @date 15:41 2021/8/17
     * @param attributeDto:
     * @param map:
     * @return void
     **/
    private void calculation(MonitorDataChartReportAttributeDto attributeDto, Map<Integer,MonitorDataChartReportValueDto> map){
        for (MonitorDataChartReportValueDto valueDto : attributeDto.getMonitorDataChartReportValue()) {
            BigDecimal b1 = new BigDecimal(valueDto.getData());
            BigDecimal b2 = new BigDecimal(map.get(valueDto.getDateLabel()).getData());
            valueDto.setMonitorData("");
            if (b1.compareTo(new BigDecimal(0)) == 0 || b2.compareTo(new BigDecimal(0)) == 0) {
                valueDto.setData(0d);
                valueDto.setMonitorData("0 kwh/m³");
            } else {
                valueDto.setData(b1.divide(b2, 3, RoundingMode.HALF_UP).doubleValue());
                valueDto.setMonitorData(valueDto.getData() + " kwh/m³");
            }
        }
    }

    /**
     * 补充数据里日期时间缺失的
     */
    private static void fillLoseData(List<MonitorDataChartReportDeviceVo> monitorDataChartReportDeviceDtos,Integer type,Integer year,Integer month ,Integer day){
        for(MonitorDataChartReportDeviceVo monitorDataChartReportDeviceDto: monitorDataChartReportDeviceDtos){
            if (CollectionUtils.isEmpty(monitorDataChartReportDeviceDto.getAttributeData())){
                continue;
            }
            for(MonitorDataChartReportAttributeDto monitorDataChartReportAttributeDto : monitorDataChartReportDeviceDto.getAttributeData()){
                if(monitorDataChartReportAttributeDto.getMonitorDataChartReportValue() == null){
                    continue;
                }
                String unit = monitorDataChartReportAttributeDto.getUnit();
                unit = StringUtils.isNotBlank(unit) ? unit:"";
                List<MonitorDataChartReportValueDto> monitorDataChartReportValueDtos = monitorDataChartReportAttributeDto.getMonitorDataChartReportValue();
                Integer maxValue =0;
                LocalDateTime localDateTime = LocalDateTime.now();
                Integer growingBase = 1;
                if (type != null && type ==3) {
                    growingBase = 0;
                    maxValue = 24;
                    localDateTime=LocalDateTime.of(year,month,day,0,0,0);
                } else if(type != null && type ==2){
                    localDateTime=LocalDateTime.of(year,month,1,0,0,0);
                    maxValue = localDateTime.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                } else if(type != null && type ==1){
                    localDateTime=LocalDateTime.of(year,1,1,0,0,0);
                    maxValue=12;
                }
                for(int i = 0;i < maxValue; i++){
                    if (i == monitorDataChartReportValueDtos.size() || !monitorDataChartReportValueDtos.get(i).getDateLabel().equals(i+growingBase)){
                        MonitorDataChartReportValueDto monitorDataChartReportValueDto = new MonitorDataChartReportValueDto();
                        monitorDataChartReportValueDto.setData(0.0);
                        LocalDateTime dateTime = LocalDateTime.now();
                        if(type != null && type ==3){
                            dateTime= localDateTime.plusHours(i);
                            monitorDataChartReportValueDto.setDateStringLabel(
                                    dateTime.getYear()+"-"+String.format("%02d",dateTime.getMonthValue())+"-"+ String.format("%02d",dateTime.getDayOfMonth())+" "+
                                            String.format("%02d",dateTime.getHour())+":00");
                        }
                        if(type != null && type ==2){
                            dateTime= localDateTime.plusDays(i);
                            monitorDataChartReportValueDto.setDateStringLabel(
                                    dateTime.getYear()+"-"+ String.format("%02d",dateTime.getMonthValue())+"-"+ String.format("%02d",dateTime.getDayOfMonth()));
                        }
                        if (type != null && type ==1){
                            dateTime= localDateTime.plusMonths(i);
                            monitorDataChartReportValueDto.setDateStringLabel(
                                    dateTime.getYear()+"-"+
                                            String.format("%02d",dateTime.getMonthValue()));
                        }
                        monitorDataChartReportValueDto.setDate(dateTime);

                        monitorDataChartReportValueDto.setDateLabel(i+growingBase);
                        monitorDataChartReportValueDto.setMonitorData("");
                        monitorDataChartReportValueDtos.add(i,monitorDataChartReportValueDto);
                    }else{
                        MonitorDataChartReportValueDto monitorDataChartReportValueDto =monitorDataChartReportValueDtos.get(i);
                        monitorDataChartReportValueDto.setMonitorData(monitorDataChartReportValueDto.getData()+""+unit);
                        LocalDateTime dateTime = monitorDataChartReportValueDto.getDate();
                        if(type != null && type ==3){
                            monitorDataChartReportValueDto.setDateStringLabel(
                                    dateTime.getYear()+"-"+
                                            String.format("%02d",dateTime.getMonthValue())+"-"+
                                            String.format("%02d",dateTime.getDayOfMonth())+" "+
                                            String.format("%02d",dateTime.getHour())+":00");
                        }
                        if(type != null && type ==2){
                            monitorDataChartReportValueDto.setDateStringLabel(
                                    dateTime.getYear()+"-"+
                                            String.format("%02d",dateTime.getMonthValue())+"-"+
                                            String.format("%02d",dateTime.getDayOfMonth()));
                        }
                        if(type != null && type ==1){
                            monitorDataChartReportValueDto.setDateStringLabel(
                                    dateTime.getYear()+"-"+
                                            String.format("%02d",dateTime.getMonthValue()));
                        }
                    }
                }
            }
        }
    }


    private  List<SceneWaterAmount> sceneWaterPressureAmounts(List<DeviceWaterDetailVo> devicePressureWaterDetailsForNow, Map<Integer, MonitorDataEntity> monitorDataMap){
        List<SceneWaterAmount> sceneWaterPressureAmounts = new ArrayList<>();
        devicePressureWaterDetailsForNow.stream().filter(item -> StringUtils.isNotBlank(item.getSceneName())).collect(Collectors.groupingBy(item -> item.getSceneName(), Collectors.toList()))
                .forEach((key, value) -> {
                    SceneWaterAmount sceneWaterAmount = new SceneWaterAmount();
                    sceneWaterAmount.setSceneName(key);
                    sceneWaterAmount.setWaterAmount(BigDecimal.ZERO);
                    value.stream().forEach(deviceWaterDetail -> {
                        MonitorDataEntity monitorDataEntity = monitorDataMap.get(deviceWaterDetail.getDeviceId());
                        if (monitorDataEntity != null && !CollectionUtils.isEmpty(monitorDataEntity.getDataValues())) {
                            monitorDataEntity.getDataValues().stream().filter(monitorDataValueEntity -> monitorDataValueEntity.getAttributeId().equals(deviceWaterDetail.getAttributeId()))
                                    .forEach(monitorDataValueEntity -> {
                                                //累计当前压力
                                                if (monitorDataValueEntity.getDataValue() != null) {
                                                    sceneWaterAmount.setWaterAmount(sceneWaterAmount.getWaterAmount().add(new BigDecimal(monitorDataValueEntity.getDataValue())));
                                                }
                                            }
                                    );
                        }
                    });
                    sceneWaterPressureAmounts.add(sceneWaterAmount);
                });
        return sceneWaterPressureAmounts;
    }

    /**
     * 水厂获取实时流量
     * @author Andy
     * @date 14:47 2021/8/18
     * @param deviceWaterAmount:
     * @param monitorDataMap:
     * @return void
     **/
    private void addWaterSupplyAmountForNow(DeviceWaterAmount deviceWaterAmount, Map<Integer, MonitorDataEntity> monitorDataMap){
        List<DeviceWaterDetailVo> supplyForNow = monitorDataReportMapper.getDeviceWaterDetailForNow("水厂", 14, UserUtil.getCurrentUser().getUserCondition());
        for (DeviceWaterDetailVo deviceWaterDetail : supplyForNow) {
            MonitorDataEntity monitorDataEntity = monitorDataMap.get(deviceWaterDetail.getDeviceId());
            if (monitorDataEntity != null && monitorDataEntity.getDataValues() != null && monitorDataEntity.getDataValues().size() > 0) {
                for (MonitorDataValueEntity monitorDataValueEntity : monitorDataEntity.getDataValues()) {
                    if (monitorDataValueEntity.getAttributeId().equals(deviceWaterDetail.getAttributeId())) {
                        // 水厂累计瞬时流量
                        deviceWaterAmount.addWaterSupplyAmountForNow(new BigDecimal(monitorDataValueEntity.getDataValue()));
                    }
                }
            }
        }
    }

    /**
     * 水源获取实时流量
     * @author Andy
     * @date 14:48 2021/8/18
     * @param deviceWaterAmount:
     * @param monitorDataMap:
     * @return void
     **/
    private void addWaterIntakeAmountForNow(DeviceWaterAmount deviceWaterAmount, Map<Integer, MonitorDataEntity> monitorDataMap){
        // 14瞬时流量
        List<DeviceWaterDetailVo> intakeWaterForNow = monitorDataReportMapper.getDeviceWaterDetailForNow("水源", 14, UserUtil.getCurrentUser().getUserCondition());
        // 水源获取实时流量
        for (DeviceWaterDetailVo deviceWaterDetail : intakeWaterForNow) {
            MonitorDataEntity monitorDataEntity = monitorDataMap.get(deviceWaterDetail.getDeviceId());
            if (monitorDataEntity != null && monitorDataEntity.getDataValues() != null && monitorDataEntity.getDataValues().size() > 0) {
                for (MonitorDataValueEntity monitorDataValueEntity : monitorDataEntity.getDataValues()) {
                    if (monitorDataValueEntity.getAttributeId().equals(deviceWaterDetail.getAttributeId())) {
                        // 水源累计瞬时流量
                        deviceWaterAmount.addWaterIntakeAmountForNow(new BigDecimal(monitorDataValueEntity.getDataValue()));
                    }
                }
            }
        }
    }


    private void addWaterSupplyAmountForDay(DeviceWaterAmount deviceWaterAmount, Map<Integer, MonitorDataEntity> monitorDataMap, LocalDate localDate){
        DeviceWaterDto dto = new DeviceWaterDto();
        dto.setSceneTypeName("水厂");
        dto.setParmType(3);
        dto.setYear(localDate.plusDays(-1).getYear());
        dto.setMonth(localDate.plusDays(-1).getDayOfMonth());
        dto.setDay(localDate.plusDays(-1).getDayOfMonth());
        List<DeviceWaterDetailVo> supplyForDay = monitorDataReportMapper.getDeviceWaterDetailForDay(dto,UserUtil.getCurrentUser().getUserCondition());
        // 水厂计算出当天流量
        for (DeviceWaterDetailVo deviceWaterDetail : supplyForDay) {
            MonitorDataEntity monitorDataEntity = monitorDataMap.get(deviceWaterDetail.getDeviceId());
            if (monitorDataEntity != null && monitorDataEntity.getDataValues() != null && monitorDataEntity.getDataValues().size() > 0
                    && deviceWaterDetail != null && deviceWaterDetail.getLatestValue() != null) {
                for (MonitorDataValueEntity monitorDataValueEntity : monitorDataEntity.getDataValues()) {
                    if (monitorDataValueEntity.getAttributeId().equals(deviceWaterDetail.getAttributeId())) {
                        // 累计当天流量
                        deviceWaterAmount.addWaterSupplyAmountForDay((new BigDecimal(monitorDataValueEntity.getDataValue()).subtract(deviceWaterDetail.getLatestValue())
                        ).divide(BigDecimal.valueOf(10000),3, RoundingMode.HALF_UP));
                    }
                }
            }
        }
    }

    private void addWaterIntakeAmountForDay(DeviceWaterAmount deviceWaterAmount, Map<Integer, MonitorDataEntity> monitorDataMap, LocalDate localDate){
        DeviceWaterDto dto = new DeviceWaterDto();
        dto.setSceneTypeName("水源");
        dto.setParmType(4);
        dto.setYear(localDate.plusDays(-1).getYear());
        dto.setMonth(localDate.plusDays(-1).getDayOfMonth());
        dto.setDay(localDate.plusDays(-1).getDayOfMonth());
        List<DeviceWaterDetailVo> intakeForDay = monitorDataReportMapper.getDeviceWaterDetailForDay(dto, UserUtil.getCurrentUser().getUserCondition());
        // 水源计算出当天流量
        for (DeviceWaterDetailVo deviceWaterDetail : intakeForDay) {
            MonitorDataEntity monitorDataEntity = monitorDataMap.get(deviceWaterDetail.getDeviceId());
            if (monitorDataEntity != null && monitorDataEntity.getDataValues() != null && monitorDataEntity.getDataValues().size() > 0
                    && deviceWaterDetail != null && deviceWaterDetail.getLatestValue() != null) {
                for (MonitorDataValueEntity monitorDataValueEntity : monitorDataEntity.getDataValues()) {
                    if (monitorDataValueEntity.getAttributeId().equals(deviceWaterDetail.getAttributeId())) {
                        // 累计当天流量
                        deviceWaterAmount.addWaterIntakeAmountForDay((new BigDecimal(monitorDataValueEntity.getDataValue()).subtract(deviceWaterDetail.getLatestValue())
                        ).divide(BigDecimal.valueOf(10000),3, RoundingMode.HALF_UP));
                    }
                }
            }
        }
    }

    /**
     * 水厂
     * @author Andy
     * @date 15:19 2021/8/18
     * @param dto:
     * @return java.math.BigDecimal
     **/
    private BigDecimal waterSupplyAmountForMonth(DeviceWaterDto dto){
        BigDecimal waterSupplyAmountForMonth = monitorDataReportMapper.getDeviceWaterDetailForMonth(dto, UserUtil.getCurrentUser().getUserCondition());
        if (waterSupplyAmountForMonth == null) {
            waterSupplyAmountForMonth = BigDecimal.ZERO;
        }
        return waterSupplyAmountForMonth.divide(BigDecimal.valueOf(10000),3, RoundingMode.HALF_UP);
    }

    /**
     * 水源
     * @author Andy
     * @date 15:23 2021/8/18
     * @param queryDto:
     * @return java.math.BigDecimal
     **/
    private BigDecimal waterSupplyAmountForYear(DeviceWaterDto queryDto){
        BigDecimal waterIntakeAmountForYear  = monitorDataReportMapper.getDeviceWaterDetailForYear(queryDto, UserUtil.getCurrentUser().getUserCondition());
        if (waterIntakeAmountForYear == null) {
            waterIntakeAmountForYear = BigDecimal.ZERO;
        }
        return waterIntakeAmountForYear.divide(BigDecimal.valueOf(10000),3, RoundingMode.HALF_UP);
    }

    private DeviceWaterDto convertDeviceWaterDto(int parmType, String sceneTypeName, LocalDate localDate){
        DeviceWaterDto dto = new DeviceWaterDto();
        dto.setSceneTypeName(sceneTypeName);
        dto.setParmType(parmType);
        dto.setYear(localDate.getYear());
        dto.setMonth(localDate.getMonthValue());
        return dto;
    }

    private void addWaterSupplyCharts(String key, List<WaterSupplyDataVo> value, List<WaterSupplyChart> waterSupplyCharts, BigDecimal multipleData, boolean sort){
        WaterSupplyChart waterSupplyChart = new WaterSupplyChart();
        waterSupplyChart.setDate(key);
        value.stream().forEach(waterSupplyData -> {
            if (sort) {
                Period period = Period.between(LocalDate.of(waterSupplyData.getYear(), waterSupplyData.getMonth(), waterSupplyData.getDay()), LocalDate.now());
                waterSupplyChart.setSort(period.getDays());
            } else {
                waterSupplyChart.setSort(waterSupplyData.getDay());
            }
            if (waterSupplyData.getParmType() == DeviceParamTypeEnum.WATER_SUPPLY.getCode() && waterSupplyData.getAmount() != null) {
                waterSupplyChart.setWaterData(waterSupplyData.getAmount().divide(multipleData, 3, RoundingMode.HALF_UP));
            } else if (waterSupplyData.getParmType() == DeviceParamTypeEnum.KWH.getCode() && waterSupplyData.getAmount() != null) {
                waterSupplyChart.setPowerData(waterSupplyData.getAmount().divide(multipleData, 3, RoundingMode.HALF_UP));
            } else if (waterSupplyData.getParmType() == DeviceParamTypeEnum.DRUG_CONSUMPTION.getCode() && waterSupplyData.getAmount() != null) {
                waterSupplyChart.setDrugData(waterSupplyData.getAmount());
            }
        });
        waterSupplyCharts.add(waterSupplyChart);
    }


}
