package com.ho.business.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.util.DateUtils;
import com.alibaba.excel.util.StringUtils;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.*;
import com.ho.business.feignclient.UserFeignClient;
import com.ho.business.mapper.EarningsCalculateMapper;
import com.ho.business.mapper.IndustrialElecPriceMapper;
import com.ho.business.service.*;
import com.ho.business.util.QueuesUtil;
import com.ho.business.vo.DeviceTransfer;
import com.ho.business.vo.RegionData;
import com.ho.business.vo.req.StationReq;
import com.ho.business.vo.req.bigScreen.CommonBigScreenReq;
import com.ho.business.vo.req.carbin.EarningsCalculateReq;
import com.ho.business.vo.req.colCount.ColCountReq;
import com.ho.business.vo.req.industrialElec.IndustrialElecPriceReqVo;
import com.ho.business.vo.req.pcsStation.PcsStationReq;
import com.ho.business.vo.req.report.ReportReqVO;
import com.ho.business.vo.resp.CountEleData;
import com.ho.business.vo.resp.DeviceRespVO;
import com.ho.business.vo.resp.InverterResp.PowerGenerateRespVO;
import com.ho.business.vo.resp.cabin.EarningsCalculateCountResp;
import com.ho.business.vo.resp.cabin.EarningsCalculateResp;
import com.ho.business.vo.resp.colCount.ColCountResp;
import com.ho.business.vo.resp.income.RevenueOverview;
import com.ho.business.vo.resp.income.RevenueOverviewData;
import com.ho.business.vo.resp.mppt.MpptActiveVo;
import com.ho.business.vo.resp.pcsStation.EarningsCalculateData;
import com.ho.business.vo.resp.pcsStation.PcsElecData;
import com.ho.business.vo.resp.profit.DayProfitType;
import com.ho.business.vo.resp.profit.GroupProfitType;
import com.ho.business.vo.resp.profit.StationProfitType;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.common.tools.service.RedisService;
import com.ho.datacollect.api.constant.DataCollectConstant;
import com.ho.user.api.vo.req.SysSubDictVO;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Description 耗能电表数据操作
 * Author yule
 * Date 2022/11/1 18:52
 */
@Service
@Slf4j
public class EarningsCalculateServiceImpl implements EarningsCalculateService {

    @Autowired
    EarningsCalculateMapper earningsCalculateMapper;

    @Autowired
    StationService stationService;

    @Autowired
    private ColCountService colCountService;

    @Autowired
    private ModelDeviceService modelDeviceService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private RedisService redisService;

    @Autowired
    OutApiService outApiService;

    @Autowired
    ElecMeterValueService elecMeterValueService;

    @Autowired
    StationHomeService stationHomeService;

    @Autowired
    IndustrialElecPriceMapper industrialElecPriceMapper;

    @Autowired
    UserFeignClient userFeignClient;

    @Autowired
    OpenStationService openStationService;

    @Autowired
    EarningsCalculateMpptService earningsCalculateMpptService;

    public static final String DICT_TYPE = "electrovalence_type";

    /** start */
    /** todo: 原有电表,pcs计算字段标识 */

    public static final String TOTAL_CHARGE = "totalCharge";

    public static final String TOTAL_DISCHARGE = "totalDischarge";

    /** end */

    /** start */
    /** todo: 尖峰平谷电表字段标识 */
    // 正向有功尖
    public static final String FOR_WARD_ACT_E1 = "forwardActE1";
    // 正向有功峰
    public static final String FOR_WARD_ACT_E2 = "forwardActE2";
    // 正向有功平
    public static final String FOR_WARD_ACT_E3 = "forwardActE3";
    // 正向有功谷
    public static final String FOR_WARD_ACT_E4 = "forwardActE4";
    // 反向有功尖
    public static final String BACK_WARD_ACT_E1 = "backwardActE1";
    // 反向有功峰
    public static final String BACK_WARD_ACT_E2 = "backwardActE2";
    // 反向有功平
    public static final String BACK_WARD_ACT_E3 = "backwardActE3";
    // 反向有功谷
    public static final String BACK_WARD_ACT_E4 = "backwardActE4";

    /** end */

    private static Map<String, String> staticMap = new HashMap<>(0);

    public static final Integer CHARGE = 0;

    public static final Integer DISCHARGE = 1;

    Map<String,String> rateTypeMap = new HashMap<>();
    {
        rateTypeMap.put("低谷时段","Valley period");
        rateTypeMap.put("高峰时段","Peak period");
        rateTypeMap.put("尖峰时段","Spike period");
        rateTypeMap.put("平时段","Flat period");
        rateTypeMap.put("深谷时段","Deep valley period");
    }


    @Override
    public EarningsCalculateResp getTotal(EarningsCalculateReq earningsCalculateReq, Integer type) {

        if (earningsCalculateReq.getTime() == null) {
            throw new BusinessException(BaseResponseCode.NON_DATA);
        }
        EarningsCalculateResp ec = new EarningsCalculateResp();
        Station station = stationService.selectById(earningsCalculateReq.getStationId());
        if (station == null || station.getId() == null) {
            return ec;
        }
        boolean flag = false;
        if(DataCollectConstant.ONE.equals(station.getInverterFlag())){
            flag = true;
        }
        Integer stationId = station.getId();
        String deviceType = colCountService.getDeviceType(stationId);
        List<DeviceRespVO> deviceRespVOS = deviceService.getListByDeviceType(stationId, deviceType);
        List<Integer> deviceTypeList = new ArrayList<>();
        if (deviceRespVOS.isEmpty()) {
            deviceRespVOS = deviceService.getListByFuzzyDeviceType(stationId, deviceType);
        } else {
            for (DeviceRespVO deviceRespVO : deviceRespVOS) {
                deviceTypeList.add(deviceRespVO.getSrcId());
            }
        }
        Integer unitType = deviceRespVOS != null && deviceRespVOS.size() > 0 && deviceRespVOS.get(0).getUnitType() != null ? deviceRespVOS.get(0).getUnitType() : 1;

        LocalDateTime date = DateUtil.parse(earningsCalculateReq.getTime(), CommonConstant.DATE_YM).toLocalDateTime();
        LocalDateTime begin = date.with(TemporalAdjusters.firstDayOfMonth());
        LocalDateTime end = date.with(TemporalAdjusters.lastDayOfMonth());
        earningsCalculateReq.setBeginTime(DateUtil.format(begin, CommonConstant.DATE_YMD));
        earningsCalculateReq.setEndTime(DateUtil.format(end, CommonConstant.DATE_YMD));
        // 装机容量
        ec.setCapacity(station.getCapacity());
        List<EarningsCalculate> list = earningsCalculateMapper.totalList(earningsCalculateReq);
//        Double totalCharge_col_count = earningsCalculateMapper.getColCount(station.getId(), TOTAL_CHARGE);
//        Double totalDischarge_col_count = earningsCalculateMapper.getColCount(station.getId(), TOTAL_DISCHARGE);
        ColCountReq colCountReq = new ColCountReq();
        colCountReq.setStationId(station.getId());
        colCountReq.setCol(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
        //总充
        List<ColCountResp> chargeList = colCountService.selectByParam(colCountReq);
        //总放
        colCountReq.setCol(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
        List<ColCountResp> disChargeList = colCountService.selectByParam(colCountReq);

        String time = earningsCalculateReq.getTime();
        ec.setMonth(time.substring(time.length() - 2, time.length()));
        String reportName = CommonConstant.REPORT_NAME;
        String billName = CommonConstant.BILL_NAME;
        String name = station.getName();
        if(CommonConstant.langTemp.EN_US.equals(earningsCalculateReq.getLang())){
            reportName = CommonConstant.REPORT_NAME_EN;
            billName = CommonConstant.BILL_NAME_EN;
            name = station.getNameEn();
        }
        if(CommonConstant.langTemp.FR_FR.equals(earningsCalculateReq.getLang())){
            reportName = CommonConstant.REPORT_NAME_FRA;
            billName = CommonConstant.BILL_NAME_FRA;
            name = station.getNameFra();
        }
        if(CommonConstant.langTemp.ES_ES.equals(earningsCalculateReq.getLang())){
            reportName = CommonConstant.REPORT_NAME_SPA;
            billName = CommonConstant.BILL_NAME_SPA;
            name = station.getNameSpa();
        }
        if(CommonConstant.langTemp.DE_DE.equals(earningsCalculateReq.getLang())){
            reportName = CommonConstant.REPORT_NAME_DE;
            billName = CommonConstant.BILL_NAME_DE;
            name = station.getNameDe();
        }
        if(CommonConstant.langTemp.PL_PL.equals(earningsCalculateReq.getLang())){
            reportName = CommonConstant.REPORT_NAME_PL;
            billName = CommonConstant.BILL_NAME_PL;
            name = station.getNamePl();
        }
        if(CommonConstant.langTemp.AR_EG.equals(earningsCalculateReq.getLang())){
            reportName = CommonConstant.REPORT_NAME_ARA;
            billName = CommonConstant.BILL_NAME_ARA;
            name = station.getNameAra();
        }
        // 电站名称(报表标题)
        if (type == 0) {
            ec.setStationName(name + "( " + time + " ) "+reportName);
        } else {
            ec.setStationName(name + "( " + time + " ) "+billName);
        }
        ec.setList(list);
        //充电收益
        ec.setTotalChargePrice(list.stream().filter(s -> CommonConstant.ZERO.equals(s.getType())).map(EarningsCalculate::getDigital).reduce(BigDecimal.ZERO, BigDecimal::add));
        //放电收益
        ec.setTotalDisChargePrice(list.stream().filter(s -> CommonConstant.ONE.equals(s.getType())).map(EarningsCalculate::getDigital).reduce(BigDecimal.ZERO, BigDecimal::add));

        List<PcsElecData> pcsElecData = getPcsElecData(earningsCalculateReq, deviceTypeList);
        BigDecimal pcsElecDatumChargeElec = BigDecimal.ZERO;
        //日放电量
        BigDecimal pcsElecDatumDischargeElec = BigDecimal.ZERO;
        for (PcsElecData pcsElecDatum : pcsElecData) {
            pcsElecDatumChargeElec = pcsElecDatumChargeElec.add(pcsElecDatum.getChargeElec());
            pcsElecDatumDischargeElec = pcsElecDatumDischargeElec.add(pcsElecDatum.getDischargeElec());
        }

        boolean sameMonth = DateUtil.isSameMonth(new Date(), DateUtil.parse(earningsCalculateReq.getTime(), CommonConstant.DATE_YM));
        //日充电量
        BigDecimal dailyChargeElec = BigDecimal.ZERO;
        //日放电量
        BigDecimal dailyDischargeElec = BigDecimal.ZERO;
        //今日收益（mppt）
        BigDecimal todayIncone = BigDecimal.ZERO;
        //今日发电量（mppt）
        BigDecimal dailyReleaseElec = BigDecimal.ZERO;
        //当月则叠加当日，否则不叠加
        if (sameMonth) {
            //将当日的日充日放叠加到日冻结中
            StationReq req = new StationReq();
            req.setStationId(earningsCalculateReq.getStationId());
            req.setDeviceType(DeviceTypeConstant.PCS);
            if (null != chargeList && chargeList.size() > 0) {
                req.setDeviceType(chargeList.get(0).getDeviceType());
            }
            CountEleData countEleData = stationHomeService.getCountEleData(req);
            //日充电量
            dailyChargeElec = countEleData.getDailyChargeElec();
            //日放电量
            dailyDischargeElec = countEleData.getDailyDischargeElec();
            if(flag){
                //今日收益（mppt）
                String key = RedisKeyConstant.PV.STATION_PV_TODAY_PROFIT + station.getId();
                todayIncone = (BigDecimal)redisService.get(key)==null?BigDecimal.ZERO:(BigDecimal)redisService.get(key);
                //今日发电量（mppt）
                MpptActiveVo pv = openStationService.getPvActivePower(stationId);
                dailyReleaseElec = pv.getDailyReleaseElec();
            }
        }
        if(flag){
            BigDecimal monthIncone = earningsCalculateMpptService.countAllPvIncome(station.getId(),earningsCalculateReq.getBeginTime(),earningsCalculateReq.getEndTime());
            ec.setMonthIncone(monthIncone.add(todayIncone));
            BigDecimal monthReleaseElec = elecMeterValueService.selectSumByType(station.getId(),DeviceTypeConstant.ELEC_METER_VALUE_TYPE.PV_CHARGE,earningsCalculateReq.getBeginTime(),earningsCalculateReq.getEndTime(),null);
            ec.setMonthReleaseElec(monthReleaseElec.add(dailyReleaseElec));
            BigDecimal totalIncome = earningsCalculateMpptService.countAllPvIncome(station.getId(),null,null);
            ec.setTotalIncome(totalIncome.add(todayIncone));
            BigDecimal totalReleaseElec = elecMeterValueService.selectSumValue(station.getId(),DeviceTypeConstant.ELEC_METER_VALUE_TYPE.PV_CHARGE,null);
            ec.setTotalReleaseElec(totalReleaseElec.add(dailyReleaseElec));
            ec.setPvPower(station.getPvPower());
        }
        ec.setTotalChargeElec(pcsElecData.stream().map(PcsElecData::getChargeElec).reduce(BigDecimal.ZERO, BigDecimal::add).add(dailyChargeElec));
        ec.setTotalDischargeElec(pcsElecData.stream().map(PcsElecData::getDischargeElec).reduce(BigDecimal.ZERO, BigDecimal::add).add(dailyDischargeElec));

        MonFreezeTotal monFreezeTotal = earningsCalculateMapper.queryData(stationId, time);

        // 总充
        if (monFreezeTotal != null) {
            ec.setTotalCharge(monFreezeTotal.getTotalCharge() == null ? BigDecimal.ZERO : monFreezeTotal.getTotalCharge());
            ec.setTotalDischarge(monFreezeTotal.getTotalDischarge() == null ? BigDecimal.ZERO : monFreezeTotal.getTotalDischarge());
        } else {
            //总充电量
            BigDecimal totalChargeElec = BigDecimal.ZERO;
            //总放电量
            BigDecimal totalDischargeElec = BigDecimal.ZERO;

            for (DeviceRespVO deviceRespVO : deviceRespVOS) {
                //拼接电表缓存key
                String redisKey = deviceRespVO.getDeviceType() + ":" + deviceRespVO.getStationId() + ":" + deviceRespVO.getSrcId();
                //判断电表换是否存在
                if (redisService.hasKey(redisKey)) {
                    Map<Object, Object> map = redisService.hgetall(redisKey);
                    if (map != null) {
                        //总充, 总放
                        Object objTotalCharge = map.get(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
                        if (objTotalCharge instanceof DeviceTransfer) {
                            DeviceTransfer totalCharge = (DeviceTransfer) map.get(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
                            totalChargeElec = totalCharge.getValue() != null ? totalChargeElec.add(totalCharge.getValue()) : totalChargeElec;
                        }
                        Object objTotalDischarge = map.get(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
                        if (objTotalDischarge instanceof DeviceTransfer) {
                            DeviceTransfer totalDischarge = (DeviceTransfer) map.get(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
                            totalDischargeElec = totalDischarge.getValue() != null ? totalDischargeElec.add(totalDischarge.getValue()) : totalDischargeElec;
                        }
                    }
                }
            }
            ec.setTotalCharge(colCountService.countOffset(totalChargeElec, chargeList).setScale(4, RoundingMode.UP));
            ec.setTotalDischarge(colCountService.countOffset(totalDischargeElec, disChargeList).setScale(4, RoundingMode.UP));
        }

        if (ec.getTotalChargeElec() != null && ec.getTotalChargeElec().compareTo(BigDecimal.ZERO) != 0 && ec.getTotalDischargeElec() != null && ec.getTotalDischargeElec().compareTo(BigDecimal.ZERO) != 0) {
            ec.setMonConvRate(ec.getTotalDischargeElec().divide(ec.getTotalChargeElec(), BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
        }
        if (ec.getTotalCharge() != null && ec.getTotalCharge().compareTo(BigDecimal.ZERO) != 0 && ec.getTotalDischarge() != null && ec.getTotalDischarge().compareTo(BigDecimal.ZERO) != 0) {
            ec.setTotalConvRate(ec.getTotalDischarge().divide(ec.getTotalCharge(), BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
        }
        if (ec.getTotalDisChargePrice() != null && ec.getTotalChargePrice() != null) {
            ec.setIncome(ec.getTotalDisChargePrice().subtract(ec.getTotalChargePrice()));
        }

        // 转换单位
        if (ec.getTotalCharge() != null) {
            ec.setTotalCharge(unitConversion(ec.getTotalCharge(), unitType));
        }
        if (ec.getTotalDischarge() != null) {
            ec.setTotalDischarge(unitConversion(ec.getTotalDischarge(), unitType));
        }
        if (ec.getTotalChargeElec() != null) {
            ec.setTotalChargeElec(unitConversion(ec.getTotalChargeElec(), unitType));
        }
        if (ec.getTotalDischargeElec() != null) {
            ec.setTotalDischargeElec(unitConversion(ec.getTotalDischargeElec(), unitType));
        }
        return ec;
    }

    private BigDecimal unitConversion(BigDecimal data, Integer unitType) {
        BigDecimal result = null;
        switch (unitType) {
            case 2:
                result = data.multiply(new BigDecimal(1000));
                break;
            case 3:
                result = data.multiply(new BigDecimal(1000)).multiply(new BigDecimal(1000));
                break;
            default:
                result = data;
                break;
        }
        return result;
    }

    /**
     * 查询月冻结值
     *
     * @param earningsCalculateReq
     * @return
     */
    private List<PcsElecData> getPcsElecData(EarningsCalculateReq earningsCalculateReq,List<Integer> deviceTypeList) {
        //查询冻结值
        List<Integer> typeList = new ArrayList<>();
        //充放电
        typeList.add(DeviceTypeConstant.ELEC_METER_VALUE_TYPE.CHARGE);
        typeList.add(DeviceTypeConstant.ELEC_METER_VALUE_TYPE.DISCHARGE);
        //List<ElecMeterValue> list = elecMeterValueService.selectList(earningsCalculateReq.getStationId(), typeList, earningsCalculateReq.getBeginTime(), earningsCalculateReq.getEndTime());
        List<ElecMeterValue> list = elecMeterValueService.selectAllList(earningsCalculateReq.getStationId(), typeList, earningsCalculateReq.getBeginTime(), earningsCalculateReq.getEndTime(),deviceTypeList);
        Map<Integer, List<ElecMeterValue>> map = list.stream().collect(Collectors.groupingBy(ElecMeterValue::getType));
        //根据天获取时间段
        List<PcsElecData> resultList = new ArrayList<>();
        try {
            List<DateTime> dateTimes = DateUtil.rangeToList(DateUtils.parseDate(earningsCalculateReq.getBeginTime()), DateUtils.parseDate(earningsCalculateReq.getEndTime()), DateField.DAY_OF_MONTH);
            for (DateTime dateTime : dateTimes) {
                String date = DateUtil.format(dateTime, CommonConstant.DATE_YMD);
                PcsElecData pcsElecData = new PcsElecData();
                pcsElecData.setDate(date);
                pcsElecData.setChargeElec(BigDecimal.ZERO);
                pcsElecData.setDischargeElec(BigDecimal.ZERO);
                //充电量
                List<ElecMeterValue> chargeList = map.get(DeviceTypeConstant.ELEC_METER_VALUE_TYPE.CHARGE);
                //过滤多余的值
                //过滤多余的值
                BigDecimal ChargeElec = BigDecimal.ZERO;
                //日放电量
                BigDecimal DischargeElec = BigDecimal.ZERO;
                if (chargeList != null) {
                    for (ElecMeterValue elecMeterValue : chargeList) {
                        if (date.equals(elecMeterValue.getDay())) {
                            ChargeElec = ChargeElec.add(elecMeterValue.getDigital());
                        }
                    }
                    pcsElecData.setChargeElec(ChargeElec);
                }
                //放电
                List<ElecMeterValue> dischargeList = map.get(DeviceTypeConstant.ELEC_METER_VALUE_TYPE.DISCHARGE);
                if (dischargeList != null) {
                    for (ElecMeterValue elecMeterValue : dischargeList) {
                        if (date.equals(elecMeterValue.getDay())) {
                            DischargeElec = DischargeElec.add(elecMeterValue.getDigital());
                        }
                    }
                    pcsElecData.setDischargeElec(DischargeElec);
                }
                resultList.add(pcsElecData);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return resultList;
    }

    @Override
    public List<EarningsCalculate> selectList(EarningsCalculateReq earningsCalculateReq) {
        List<EarningsCalculate> elecMeterValues = earningsCalculateMapper.selectList(earningsCalculateReq);
        return elecMeterValues;
    }

    //按日期和类型删除

    @Override
    public int deleteByDay(String day, List<Integer> typeList) {
        int i = earningsCalculateMapper.deleteByDay(day, typeList);
        return i;
    }

    @Override
    public int insert(EarningsCalculate elecMeterValue) {
        elecMeterValue.setCreateTime(new Date());
        int i = earningsCalculateMapper.insertSelective(elecMeterValue);
        return i;
    }

    //批量插入
    @Override
    public int insertBatch(List<EarningsCalculate> list) {
        int i = 0;
        if (list != null && !list.isEmpty()) {
            i = earningsCalculateMapper.insertBatch(list);
        }
        return i;
    }


    @Override
    public void queryDeviceByStationId(List<Station> stations, Integer computationStationId, String beginTime) {
        /** todo: 判断电站是否有数据，如果没有则不执行之后的方法 */
        if (stations != null && stations.size() > 0) {
            // TODO: 2024/3/15 如果不是电表,或者没有配置尖峰平谷电量指标的走原来的计算逻辑,如果是电表并且配置了尖峰平谷指标的走新流程
            Map<Integer, List<List<ModelDeviceColComp>>> chargeMap = new HashMap<>(0);
            Map<Integer, List<List<ModelDeviceColComp>>> dischargeMap = new HashMap<>(0);
            /** start */
            /** todo: 尖峰平谷电表相关参数对象 */
            // 充尖 FOR_WARD_ACT_E1
            Map<Integer, List<List<ModelDeviceColComp>>> chargeE1Map = new HashMap<>(0);
            // 充峰 FOR_WARD_ACT_E2
            Map<Integer, List<List<ModelDeviceColComp>>> chargeE2Map = new HashMap<>(0);
            // 充平 FOR_WARD_ACT_E3
            Map<Integer, List<List<ModelDeviceColComp>>> chargeE3Map = new HashMap<>(0);
            // 充谷 FOR_WARD_ACT_E4
            Map<Integer, List<List<ModelDeviceColComp>>> chargeE4Map = new HashMap<>(0);
            // 放尖 BACK_WARD_ACT_E1
            Map<Integer, List<List<ModelDeviceColComp>>> dischargeE1Map = new HashMap<>(0);
            // 放峰 BACK_WARD_ACT_E2
            Map<Integer, List<List<ModelDeviceColComp>>> dischargeE2Map = new HashMap<>(0);
            // 放平 BACK_WARD_ACT_E3
            Map<Integer, List<List<ModelDeviceColComp>>> dischargeE3Map = new HashMap<>(0);
            // 放谷 BACK_WARD_ACT_E4
            Map<Integer, List<List<ModelDeviceColComp>>> dischargeE4Map = new HashMap<>(0);
            /** end */
            for (Station station : stations) {

//                if( station.getId() != 349 ){
//                    continue;
//                }

                if (computationStationId != null && !station.getId().equals(computationStationId)) {
                    continue;
                }
                // 判断标志,如果为false则不进入原来的总电量查询方法
                boolean flag = true;

                Integer stationId = station.getId();
                String deviceType = colCountService.getDeviceType(stationId);
                // 总充
                List<DeviceRespVO> deviceRespVOS = deviceService.getListByDeviceType(stationId, deviceType);
                if (deviceRespVOS.isEmpty()) {
                    deviceRespVOS = deviceService.getListByFuzzyDeviceType(stationId, deviceType);
                }
                log.info("queryDeviceByStationId 获取设备类型{}", deviceType);
                /** start */
                /** todo: 原有的总电量查询*/
                List<List<ModelDeviceColComp>> chargeList = new ArrayList<>(0);
                List<List<ModelDeviceColComp>> dischargeList = new ArrayList<>(0);
                /** end */

                /** start */
                /** todo: 尖峰平谷电量查询*/
                List<List<ModelDeviceColComp>> chargeE1List = new ArrayList<>(0);
                List<List<ModelDeviceColComp>> chargeE2List = new ArrayList<>(0);
                List<List<ModelDeviceColComp>> chargeE3List = new ArrayList<>(0);
                List<List<ModelDeviceColComp>> chargeE4List = new ArrayList<>(0);
                List<List<ModelDeviceColComp>> dischargeE1List = new ArrayList<>(0);
                List<List<ModelDeviceColComp>> dischargeE2List = new ArrayList<>(0);
                List<List<ModelDeviceColComp>> dischargeE3List = new ArrayList<>(0);
                List<List<ModelDeviceColComp>> dischargeE4List = new ArrayList<>(0);
                /** end */

                List<ModelDeviceColComp> chargeParams = null;
                List<ModelDeviceColComp> dischargeParams = null;

                /** start */
                /** todo: 充电查询参数集合 */
                List<ModelDeviceColComp> chargeE1Params = null;
                List<ModelDeviceColComp> chargeE2Params = null;
                List<ModelDeviceColComp> chargeE3Params = null;
                List<ModelDeviceColComp> chargeE4Params = null;
                /** end */

                /** start */
                /** todo: 放电查询参数集合 */
                List<ModelDeviceColComp> dischargeE1Params = null;
                List<ModelDeviceColComp> dischargeE2Params = null;
                List<ModelDeviceColComp> dischargeE3Params = null;
                List<ModelDeviceColComp> dischargeE4Params = null;
                /** end */
                for (DeviceRespVO vo : deviceRespVOS) {
                    /** start */
                    /** todo: 如果有尖峰平谷配置走这里,下面的充放电查询方法跳过 */
                    // 充尖
                    chargeE1Params = new ArrayList<>(0);
                    List<ModelDeviceColComp> deviceCpE1 = modelDeviceService.getCompListByType("device", vo.getDeviceType(), FOR_WARD_ACT_E1);
                    extracted(beginTime, chargeE1List, chargeE1Params, vo, deviceCpE1);
                    if (!deviceCpE1.isEmpty()) {
                        flag = false;
                    }
                    // 如果第一个都没有后面的直接跳过
                    if (!flag) {
                        /** start */
                        /** todo: 充电*/
                        // 充峰
                        chargeE2Params = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceCpE2 = modelDeviceService.getCompListByType("device", vo.getDeviceType(), FOR_WARD_ACT_E2);
                        extracted(beginTime, chargeE2List, chargeE2Params, vo, deviceCpE2);
                        // 充平
                        chargeE3Params = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceCpE3 = modelDeviceService.getCompListByType("device", vo.getDeviceType(), FOR_WARD_ACT_E3);
                        extracted(beginTime, chargeE3List, chargeE3Params, vo, deviceCpE3);
                        // 充谷
                        chargeE4Params = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceCpE4 = modelDeviceService.getCompListByType("device", vo.getDeviceType(), FOR_WARD_ACT_E4);
                        extracted(beginTime, chargeE4List, chargeE4Params, vo, deviceCpE4);
                        /** end */

                        /** start */
                        /** todo: 放电 */
                        // 放峰
                        dischargeE1Params = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceDcpE1 = modelDeviceService.getCompListByType("device", vo.getDeviceType(), BACK_WARD_ACT_E1);
                        extracted(beginTime, dischargeE1List, dischargeE1Params, vo, deviceDcpE1);
                        // 放峰
                        dischargeE2Params = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceDcpE2 = modelDeviceService.getCompListByType("device", vo.getDeviceType(), BACK_WARD_ACT_E2);
                        extracted(beginTime, dischargeE2List, dischargeE2Params, vo, deviceDcpE2);
                        // 放平
                        dischargeE3Params = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceDcpE3 = modelDeviceService.getCompListByType("device", vo.getDeviceType(), BACK_WARD_ACT_E3);
                        extracted(beginTime, dischargeE3List, dischargeE3Params, vo, deviceDcpE3);
                        // 放谷
                        dischargeE4Params = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceDcpE4 = modelDeviceService.getCompListByType("device", vo.getDeviceType(), BACK_WARD_ACT_E4);
                        extracted(beginTime, dischargeE4List, dischargeE4Params, vo, deviceDcpE4);
                        /** end */
                    }
                    /** end */

                    /** start */
                    /** todo: 原有设备采总充放电量计算查询参数方法 */
                    if (flag) {
                        // 总充
                        chargeParams = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceCp = modelDeviceService.getCompListByType("device", vo.getDeviceType(), TOTAL_CHARGE);
                        extracted(beginTime, chargeList, chargeParams, vo, deviceCp);
                        // 总放
                        dischargeParams = new ArrayList<>(0);
                        List<ModelDeviceColComp> deviceDcp = modelDeviceService.getCompListByType("device", vo.getDeviceType(), TOTAL_DISCHARGE);
                        extracted(beginTime, dischargeList, dischargeParams, vo, deviceDcp);
                    }
                    /** end */
                }
                // 存放需要计算的电站信息
                QueuesUtil.setStationMap(station);
                QueuesUtil.setDischargeStationMap(station);

                if (chargeList.size() > 0 || dischargeList.size() > 0) {
                    chargeMap.put(stationId, chargeList);
                    dischargeMap.put(stationId, dischargeList);
                }
                /** start */
                /** todo: 尖峰平谷电表存放队列 */
                // 尖
                if (chargeE1List.size() > 0 || dischargeE1List.size() > 0) {
                    chargeE1Map.put(stationId, chargeE1List);
                    dischargeE1Map.put(stationId, dischargeE1List);
                }
                // 峰
                if (chargeE2List.size() > 0 || dischargeE2List.size() > 0) {
                    chargeE2Map.put(stationId, chargeE2List);
                    dischargeE2Map.put(stationId, dischargeE2List);
                }
                // 平
                if (chargeE3List.size() > 0 || dischargeE3List.size() > 0) {
                    chargeE3Map.put(stationId, chargeE3List);
                    dischargeE3Map.put(stationId, dischargeE3List);
                }
                // 谷
                if (chargeE4List.size() > 0 || dischargeE4List.size() > 0) {
                    chargeE4Map.put(stationId, chargeE4List);
                    dischargeE4Map.put(stationId, dischargeE4List);
                }
                /** end */
            }
            /** start */
            /** todo: 原有总充放队列 */
            // 存放查询总充队列
            QueuesUtil.setChargeMap(chargeMap);
            // 存放查询总放队列
            QueuesUtil.setDischargeMap(dischargeMap);
            /** end */

            /** start */
            /** todo: 尖峰平谷充放电队列 */
            // 存放查询尖充队列
            QueuesUtil.setChargeE1Map(chargeE1Map);
            // 存放查询尖放队列
            QueuesUtil.setDischargeE1Map(dischargeE1Map);

            // 存放查询峰充队列
            QueuesUtil.setChargeE2Map(chargeE2Map);
            // 存放查询峰放队列
            QueuesUtil.setDischargeE2Map(dischargeE2Map);

            // 存放查询平充队列
            QueuesUtil.setChargeE3Map(chargeE3Map);
            // 存放查询平放队列
            QueuesUtil.setDischargeE3Map(dischargeE3Map);

            // 存放查询谷充队列
            QueuesUtil.setChargeE4Map(chargeE4Map);
            // 存放查询谷放队列
            QueuesUtil.setDischargeE4Map(dischargeE4Map);
            /** end */
        }
    }

    /**
     * @param beginTime  数据时间
     * @param list       结果集
     * @param params     参数新对象(内存引用问题)
     * @param vo         查询参数(取srcId和单位类型)
     * @param deviceMdcp 查询到的模型数据
     */
    private static void extracted(String beginTime, List<List<ModelDeviceColComp>> list, List<ModelDeviceColComp> params, DeviceRespVO vo, List<ModelDeviceColComp> deviceMdcp) {
        if (!deviceMdcp.isEmpty()) {
            for (ModelDeviceColComp mdcp : deviceMdcp) {
                ModelDeviceColComp newMdcp = new ModelDeviceColComp();
                BeanUtils.copyProperties(mdcp, newMdcp);
                newMdcp.setBeginTime(beginTime);
                newMdcp.setUnitType(vo.getUnitType() == null ? 1 : vo.getUnitType());
                newMdcp.setSrcId(vo.getSrcId());
                params.add(newMdcp);
            }
            list.add(params);
        }
    }


    @Override
    public List<EarningsCalculateSub> queryElecTemplateSubByStationId(Integer stationId, Integer templateType, String dateStr) {
        // 获取配置的电价模板,修改成先获取电价模板,如果没有配置再尝试获取国网电价,如果都没有获取到则直接返回空集合
        List<EarningsCalculateSub> earningsCalculateSubs = null;
        String date = null;
        if (dateStr != null && !"".equals(dateStr)) {
            date = dateStr.substring(0, 7);
        }
        Integer elecType = 1;
        earningsCalculateSubs = earningsCalculateMapper.queryElecTemplateSubByStationId(stationId, templateType, dateStr,elecType);
        if (earningsCalculateSubs != null && earningsCalculateSubs.size() > 0) {
            return earningsCalculateSubs;
        }
        // 如果上面没return掉方法,那么就根据电站id查询电站信息来获取国网电价,国网电价需要重新组装一次数据,组装成原来的电价模板格式
        Station station = stationService.selectByPrimaryKey(stationId);
        // 如果电站就是空就直接return
        if (station == null) {
            return new ArrayList<>(0);
        }
        // 如果参数时间字符串是空,则获取当前时间,格式为yyyy-MM 用于查询电价模板
        if (dateStr == null || "".equals(dateStr)) {
            date = DateUtil.format(new Date(), "yyyy-MM");
        }
        // 国网电价可能出现用省,市,区,县各级别电价的,如果是县级那么县的判断为区+县拼接的字符串
        IndustrialElecPriceReqVo vo = new IndustrialElecPriceReqVo();
        vo.setExecutionTime(date);
        if (station.getVoltageLevel() != null) {
            vo.setVoltageLevel(station.getVoltageLevel());
        }
        if (station.getCustomerType() != null) {
            vo.setCustomerType(station.getCustomerType());
        }
        if (station.getElectricityType() != null) {
            vo.setElectricityType(station.getElectricityType());
        }
        RegionData regionData = earningsCalculateMapper.queryRegionDataByDistrict(station.getDistrict(), station.getCity(), station.getProvince());
        Integer regionId = this.getRegionId(regionData);
        vo.setRegionId(regionId);
        IndustrialElecPrice byCondition = industrialElecPriceMapper.findByCondition(vo);
        earningsCalculateSubs = processElecTemplateSubDatas(byCondition);
        if (earningsCalculateSubs != null && earningsCalculateSubs.size() > 0) {
            return earningsCalculateSubs;
        }
        // 如果上面两个判断都没进过,那表示这个站查不到电价,直接返回空集合,后面计算方法会自己跳过计算过程
        return new ArrayList<>(0);
    }

    /**
     * 判断需要使用哪个regionId来查询电价
     *
     * @return regionData
     */
    private Integer getRegionId(RegionData regionData) {
        // 根据regionID来判断使用什么电价,如果更小级别地区有的,就用最小级别的
        Integer regionId = 0;
        if (regionData != null) {
            // 此处利用程序的执行顺序,按照省-市-区的顺序来获取regionId,最终需要使用的是最小级别的regionId,请勿轻易修改,如果要修改请确认逻辑
            if (regionData.getProvinceRegionId() != null) {
                regionId = regionData.getProvinceRegionId();
            }
            if (regionData.getCityRegionId() != null) {
                regionId = regionData.getCityRegionId();
            }
            if (regionData.getDistrictRegionId() != null) {
                regionId = regionData.getDistrictRegionId();
            }
        }
        return regionId;
    }

    private List<EarningsCalculateSub> processElecTemplateSubDatas(IndustrialElecPrice condition) {
        List<EarningsCalculateSub> earningsCalculateSubs = new ArrayList<>(0);
        // 先判断内存是否已经有了,如果没有则查询一次放进内存
        if (staticMap.size() == 0) {
            SysSubDictVO vo = new SysSubDictVO();
            vo.setType(DICT_TYPE);
            staticMap = userFeignClient.getSysSubDict(vo);
        }
        if (condition != null) {
            // 尖
            if (condition.getSpikePrice() != null && !"".equals(condition.getSpikePrice()) && condition.getSpikePriceInterval() != null && !"".equals(condition.getSpikePriceInterval())) {
                String spikePriceInterval = condition.getSpikePriceInterval();
                String spikePriceName = staticMap.get("1") != null ? staticMap.get("1") : "尖峰时段";
                BigDecimal spikePrice = condition.getSpikePrice();
                List<EarningsCalculateSub> list = this.splitInterval(spikePriceInterval, spikePriceName, spikePrice, 1);
                earningsCalculateSubs.addAll(list);
            }
            // 峰
            if (condition.getPeakPrice() != null && !"".equals(condition.getPeakPrice()) && condition.getPeakPriceInterval() != null && !"".equals(condition.getPeakPriceInterval())) {
                String peakPriceInterval = condition.getPeakPriceInterval();
                String peakPriceName = staticMap.get("2") != null ? staticMap.get("2") : "高峰时段";
                BigDecimal peakPrice = condition.getPeakPrice();
                List<EarningsCalculateSub> list = this.splitInterval(peakPriceInterval, peakPriceName, peakPrice, 2);
                earningsCalculateSubs.addAll(list);
            }
            // 平
            if (condition.getRegularPrice() != null && !"".equals(condition.getRegularPrice()) && condition.getRegularPriceInterval() != null && !"".equals(condition.getRegularPriceInterval())) {
                String regularPriceInterval = condition.getRegularPriceInterval();
                String regularPriceName = staticMap.get("3") != null ? staticMap.get("3") : "平时段";
                BigDecimal regularPrice = condition.getRegularPrice();
                List<EarningsCalculateSub> list = this.splitInterval(regularPriceInterval, regularPriceName, regularPrice, 3);
                earningsCalculateSubs.addAll(list);
            }
            // 谷
            if (condition.getLowValleyPrice() != null && !"".equals(condition.getLowValleyPrice()) && condition.getLowValleyPriceInterval() != null && !"".equals(condition.getLowValleyPriceInterval())) {
                String lowValleyPriceInterval = condition.getLowValleyPriceInterval();
                String lowValleyPriceName = staticMap.get("4") != null ? staticMap.get("4") : "低谷时段";
                BigDecimal lowValleyPrice = condition.getLowValleyPrice();
                List<EarningsCalculateSub> list = this.splitInterval(lowValleyPriceInterval, lowValleyPriceName, lowValleyPrice, 4);
                earningsCalculateSubs.addAll(list);
            }
            // 深谷
            if (condition.getDeepValleyPrice() != null && !"".equals(condition.getDeepValleyPrice()) && condition.getDeepValleyPriceInterval() != null && !"".equals(condition.getDeepValleyPriceInterval())) {
                String deepValleyPriceInterval = condition.getDeepValleyPriceInterval();
                String deepValleyPriceName = staticMap.get("5") != null ? staticMap.get("5") : "深谷时段";
                BigDecimal deepValleyPrice = condition.getDeepValleyPrice();
                List<EarningsCalculateSub> list = this.splitInterval(deepValleyPriceInterval, deepValleyPriceName, deepValleyPrice, 5);
                earningsCalculateSubs.addAll(list);
            }
        }
        /** todo: 对得到的最终结果进行排序并返回 */
        this.sortList(earningsCalculateSubs);
        return earningsCalculateSubs;
    }

    @Override
    public List<EarningsCalculateSub> queryElecRateTemplateSubByStationId(Integer stationId, Integer templateType, String dateStr) {
        // 获取配置的电价模板,修改成先获取电价模板,如果没有配置再尝试获取国网电价,如果都没有获取到则直接返回空集合
        List<EarningsCalculateSub> earningsCalculateSubs = null;
        String date = null;
        if (dateStr != null && !"".equals(dateStr)) {
            date = dateStr.substring(0, 7);
        }
        earningsCalculateSubs = earningsCalculateMapper.queryElecRateTemplateSubByStationId(stationId, templateType, dateStr);
        if (earningsCalculateSubs != null && earningsCalculateSubs.size() > 0) {
            return earningsCalculateSubs;
        }
        // 如果上面没return掉方法,那么就根据电站id查询电站信息来获取国网电价,国网电价需要重新组装一次数据,组装成原来的电价模板格式
        Station station = stationService.selectByPrimaryKey(stationId);
        // 如果电站就是空就直接return
        if (station == null) {
            return new ArrayList<>(0);
        }
        // 如果参数时间字符串是空,则获取当前时间,格式为yyyy-MM 用于查询电价模板
        if (dateStr == null || "".equals(dateStr)) {
            date = DateUtil.format(new Date(), "yyyy-MM");
        }
        // 国网电价可能出现用省,市,区,县各级别电价的,如果是县级那么县的判断为区+县拼接的字符串
        IndustrialElecPriceReqVo vo = new IndustrialElecPriceReqVo();
        vo.setExecutionTime(date);
        if (station.getVoltageLevel() != null) {
            vo.setVoltageLevel(station.getVoltageLevel());
        }
        if (station.getCustomerType() != null) {
            vo.setCustomerType(station.getCustomerType());
        }
        if (station.getElectricityType() != null) {
            vo.setElectricityType(station.getElectricityType());
        }
        RegionData regionData = earningsCalculateMapper.queryRegionDataByDistrict(station.getDistrict(), station.getCity(), station.getProvince());
        Integer regionId = this.getRegionId(regionData);
        vo.setRegionId(regionId);
        IndustrialElecPrice byCondition = industrialElecPriceMapper.findByCondition(vo);
        earningsCalculateSubs = processElecRateTemplateSubDatas(byCondition);
        if (earningsCalculateSubs != null && earningsCalculateSubs.size() > 0) {
            return earningsCalculateSubs;
        }
        // 如果上面两个判断都没进过,那表示这个站查不到电价,直接返回空集合,后面计算方法会自己跳过计算过程
        return new ArrayList<>(0);
    }

    private List<EarningsCalculateSub> processElecRateTemplateSubDatas(IndustrialElecPrice condition) {
        List<EarningsCalculateSub> earningsCalculateSubs = new ArrayList<>(0);
        // 先判断内存是否已经有了,如果没有则查询一次放进内存
        if (staticMap.size() == 0) {
            SysSubDictVO vo = new SysSubDictVO();
            vo.setType(DICT_TYPE);
            staticMap = userFeignClient.getSysSubDict(vo);
        }
        if (condition != null) {
            // 尖
            if (condition.getSpikePrice() != null && !"".equals(condition.getSpikePrice()) && condition.getSpikePriceInterval() != null && !"".equals(condition.getSpikePriceInterval())) {
                String spikePriceName = staticMap.get("1") != null ? staticMap.get("1") : "尖峰时段";
                BigDecimal spikePrice = condition.getSpikePrice();
                List<EarningsCalculateSub> list = this.parseList(spikePriceName, spikePrice, 1);
                earningsCalculateSubs.addAll(list);
            }
            // 峰
            if (condition.getPeakPrice() != null && !"".equals(condition.getPeakPrice()) && condition.getPeakPriceInterval() != null && !"".equals(condition.getPeakPriceInterval())) {
                String peakPriceName = staticMap.get("2") != null ? staticMap.get("2") : "高峰时段";
                BigDecimal peakPrice = condition.getPeakPrice();
                List<EarningsCalculateSub> list = this.parseList(peakPriceName, peakPrice, 2);
                earningsCalculateSubs.addAll(list);
            }
            // 平
            if (condition.getRegularPrice() != null && !"".equals(condition.getRegularPrice()) && condition.getRegularPriceInterval() != null && !"".equals(condition.getRegularPriceInterval())) {
                String regularPriceName = staticMap.get("3") != null ? staticMap.get("3") : "平时段";
                BigDecimal regularPrice = condition.getRegularPrice();
                List<EarningsCalculateSub> list = this.parseList(regularPriceName, regularPrice, 3);
                earningsCalculateSubs.addAll(list);
            }
            // 谷
            if (condition.getLowValleyPrice() != null && !"".equals(condition.getLowValleyPrice()) && condition.getLowValleyPriceInterval() != null && !"".equals(condition.getLowValleyPriceInterval())) {
                String lowValleyPriceName = staticMap.get("4") != null ? staticMap.get("4") : "低谷时段";
                BigDecimal lowValleyPrice = condition.getLowValleyPrice();
                List<EarningsCalculateSub> list = this.parseList(lowValleyPriceName, lowValleyPrice, 4);
                earningsCalculateSubs.addAll(list);
            }
            // 深谷
            if (condition.getDeepValleyPrice() != null && !"".equals(condition.getDeepValleyPrice()) && condition.getDeepValleyPriceInterval() != null && !"".equals(condition.getDeepValleyPriceInterval())) {
                String deepValleyPriceName = staticMap.get("5") != null ? staticMap.get("5") : "深谷时段";
                BigDecimal deepValleyPrice = condition.getDeepValleyPrice();
                List<EarningsCalculateSub> list = this.parseList(deepValleyPriceName, deepValleyPrice, 5);
                earningsCalculateSubs.addAll(list);
            }
        }
        return earningsCalculateSubs;
    }

    private List<EarningsCalculateSub> parseList(String name, BigDecimal price, Integer rateType) {
        List<EarningsCalculateSub> list = new ArrayList<>(0);
        EarningsCalculateSub sub = new EarningsCalculateSub();
        sub.setType(name);
        sub.setPrice(price);
        sub.setRateType(rateType);
        list.add(sub);
        return list;
    }

    /**
     * 对集合进行排序
     *
     * @param earningsCalculateSubs
     */
    private void sortList(List<EarningsCalculateSub> earningsCalculateSubs) {
        Collections.sort(earningsCalculateSubs, new Comparator<EarningsCalculateSub>() {
            @Override
            public int compare(EarningsCalculateSub p1, EarningsCalculateSub p2) {
                String[] time1 = p1.getBeginTime().split(":");
                String[] time2 = p2.getBeginTime().split(":");
                int hour1 = Integer.parseInt(time1[0]);
                int minute1 = Integer.parseInt(time1[1]);
                int hour2 = Integer.parseInt(time2[0]);
                int minute2 = Integer.parseInt(time2[1]);
                return (hour1 * 60 + minute1) - (hour2 * 60 + minute2);
            }
        });
    }

    /**
     * 使用电网电价的话默认折扣全都是100%
     *
     * @param interval
     * @param name
     * @param price
     * @return
     */
    private List<EarningsCalculateSub> splitInterval(String interval, String name, BigDecimal price, Integer rateType) {
        List<EarningsCalculateSub> list = new ArrayList<>(0);
        String[] split = interval.split(",");
        Arrays.stream(split).forEach(s -> {
            EarningsCalculateSub sub = new EarningsCalculateSub();
            String startTime = s.substring(0, s.indexOf("-"));
            String endTime = s.substring(s.indexOf("-") + 1, s.length());
            sub.setBeginTime(startTime);
            sub.setEndTime(endTime);
            sub.setType(name);
            sub.setDiscount(BigDecimal.ONE);
            sub.setPrice(price);
            sub.setRateType(rateType);
            list.add(sub);
        });
        return list;
    }


    @Override
    public Integer getSrcIdByStationId(Integer stationId, String deviceType) {
        return earningsCalculateMapper.getSrcIdByStationId(stationId, deviceType);
    }

    @Override
    public Double getColCount(Integer stationId, String col) {
        return earningsCalculateMapper.getColCount(stationId, col);
    }

    @Override
    public void freezeMonthTotalEle(List<Station> stations) {
        if (stations == null || stations.size() == 0) {
            return;
        }
        List<MonFreezeTotal> list = new ArrayList<>(0);
        MonFreezeTotal total = null;
        for (Station station : stations) {
            total = new MonFreezeTotal();
            Integer stationId = station.getId();

//            Double totalCharge_col_count = earningsCalculateMapper.getColCount(stationId, TOTAL_CHARGE);
//            Double totalDischarge_col_count = earningsCalculateMapper.getColCount(stationId, TOTAL_DISCHARGE);
            ColCountReq colCountReq = new ColCountReq();
            colCountReq.setStationId(station.getId());
            colCountReq.setCol(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
            //总充
            List<ColCountResp> chargeList = colCountService.selectByParam(colCountReq);
            //总放
            colCountReq.setCol(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
            List<ColCountResp> disChargeList = colCountService.selectByParam(colCountReq);
            // 总充
            String deviceType = colCountService.getDeviceType(stationId);
            if (null == deviceType) {
                deviceType = DeviceTypeConstant.PCS;
            }

            //总充电量
            BigDecimal totalChargeElec = BigDecimal.ZERO;
            //总放电量
            BigDecimal totalDischargeElec = BigDecimal.ZERO;

            //总充,总放来自于BMS ,日充, 日放也来自于BMS
            List<DeviceRespVO> deviceRespVOS = deviceService.getListByDeviceType(stationId, deviceType);
            if (deviceRespVOS.isEmpty()) {
                deviceRespVOS = deviceService.getListByFuzzyDeviceType(stationId, deviceType);
            }

            for (DeviceRespVO deviceRespVO : deviceRespVOS) {
                //拼接电表缓存key
                String redisKey = deviceRespVO.getDeviceType() + ":" + deviceRespVO.getStationId() + ":" + deviceRespVO.getSrcId();
                //判断电表换是否存在
                if (redisService.hasKey(redisKey)) {
                    Map<Object, Object> map = redisService.hgetall(redisKey);
                    if (map != null) {
                        //总充, 总放
                        Object objTotalCharge = map.get(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
                        if (objTotalCharge instanceof DeviceTransfer) {
                            DeviceTransfer totalCharge = (DeviceTransfer) map.get(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
                            totalChargeElec = totalCharge.getValue() != null ? totalChargeElec.add(totalCharge.getValue()) : totalChargeElec;
                        }
                        Object objTotalDischarge = map.get(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
                        if (objTotalDischarge instanceof DeviceTransfer) {
                            DeviceTransfer totalDischarge = (DeviceTransfer) map.get(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
                            totalDischargeElec = totalDischarge.getValue() != null ? totalDischargeElec.add(totalDischarge.getValue()) : totalDischargeElec;
                        }
                    }
                }
            }
            DateTime yesterday = DateUtil.yesterday();
            String month = DateUtil.format(yesterday, "YYYY-MM");
            total.setStationId(stationId);
            total.setMonth(month);
            total.setTotalCharge(colCountService.countOffset(totalChargeElec, chargeList).setScale(4, RoundingMode.UP));
            total.setTotalDischarge(colCountService.countOffset(totalDischargeElec, disChargeList).setScale(4, RoundingMode.UP));
            list.add(total);
        }
        if (list.size() > 0) {
            earningsCalculateMapper.batchInsertData(list);
        }
    }

    @Override
    public EarningsCalculateCountResp getEarningsCount(Integer stationId) {

        EarningsCalculateCountResp resp = new EarningsCalculateCountResp();
        EarningsCalculateReq earningsCalculateReq = new EarningsCalculateReq();
        earningsCalculateReq.setStationId(stationId);
        LocalDateTime date = new DateTime().toLocalDateTime();
        //月收益
        earningsCalculateReq.setBeginTime(DateUtil.format(date.with(TemporalAdjusters.firstDayOfMonth()), CommonConstant.DATE_YMD));
        earningsCalculateReq.setEndTime(DateUtil.format(date.with(TemporalAdjusters.lastDayOfMonth()), CommonConstant.DATE_YMD));
        List<EarningsCalculate> list = earningsCalculateMapper.totalList(earningsCalculateReq);
        resp.setMonthIncome(list.stream().filter(s -> CommonConstant.ONE.equals(s.getType())).map(EarningsCalculate::getDigital).reduce(BigDecimal.ZERO, BigDecimal::add)
                .subtract(list.stream().filter(s -> CommonConstant.ZERO.equals(s.getType())).map(EarningsCalculate::getDigital).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //年收益
        earningsCalculateReq.setBeginTime(null);
        earningsCalculateReq.setEndTime(null);
        list = earningsCalculateMapper.totalList(earningsCalculateReq);
        resp.setTotalIncome(list.stream().filter(s -> CommonConstant.ONE.equals(s.getType())).map(EarningsCalculate::getDigital).reduce(BigDecimal.ZERO, BigDecimal::add)
                .subtract(list.stream().filter(s -> CommonConstant.ZERO.equals(s.getType())).map(EarningsCalculate::getDigital).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //日收益
        earningsCalculateReq.setBeginTime(DateUtil.format(date, CommonConstant.DATE_YMD));
        earningsCalculateReq.setEndTime(DateUtil.format(date, CommonConstant.DATE_YMD));
        list = earningsCalculateMapper.totalList(earningsCalculateReq);
        String key = RedisKeyConstant.EARNINGS_BACK + stationId;
        String timeKey = RedisKeyConstant.EARNINGS + stationId;
        BigDecimal income = new BigDecimal(CommonConstant.ZERO);
        if (list.size() == 0) {
            if (redisService.hasKey(key)) {
                income = new BigDecimal(redisService.get(key).toString());
            }
            resp.setDayIncome(income);
            resp.setMonthIncome(resp.getMonthIncome().add(income));
            resp.setTotalIncome(resp.getTotalIncome().add(income));
        } else {
            income = list.stream().filter(s -> CommonConstant.ONE.equals(s.getType())).map(EarningsCalculate::getDigital).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .subtract(list.stream().filter(s -> CommonConstant.ZERO.equals(s.getType())).map(EarningsCalculate::getDigital).reduce(BigDecimal.ZERO, BigDecimal::add));
            resp.setDayIncome(income);
            redisService.set(key, resp.getDayIncome());
        }
        try {
            Long expire = redisService.getExpire(timeKey, TimeUnit.SECONDS);
            if (expire < 5) {
                earningsCount(stationId);
                //修改成每7分钟执行一次
                redisService.set(timeKey, resp.getDayIncome(), 420, TimeUnit.SECONDS);
            }

        } catch (Exception e) {
            log.error("删除当日收益数据失败:{}", e.getMessage());
        }
        return resp;
    }

    /**
     * 计算日收益
     *
     * @param stationId
     */
    @Override
    public void earningsCount(Integer stationId) {
        String beginTime = DateUtil.formatDate(DateUtil.date());
        int result = deleteByDay(beginTime, null);
        log.info("获取收益，删除当日结果:{}", result);
//        QueuesUtil.setDateMap(stationId,beginTime);
//        QueuesUtil.date = beginTime;
        List<Station> stations = new ArrayList<>();
        Station station = stationService.selectById(stationId);
        stations.add(station);
        queryDeviceByStationId(stations, null, beginTime);
    }


    @Override
    public List<EarningsCalculate> totalList(EarningsCalculateReq earningsCalculateReq) {
        List<EarningsCalculate> list = earningsCalculateMapper.totalList(earningsCalculateReq);
        return list;
    }


    @Override
    public BigDecimal selectSumByType(Integer stationId, Integer type, String beginTime, String endTime) {
        return earningsCalculateMapper.selectSumIncomeByStationId(stationId, type, beginTime, endTime);
    }

    @Override
    public List<EarningsCalculateData> getEarningsList(PcsStationReq req) {
        EarningsCalculateReq earningsCalculateReq = new EarningsCalculateReq();
        earningsCalculateReq.setStationId(req.getStationId());
        //收益
        earningsCalculateReq.setBeginTime(req.getBeginTime());
        earningsCalculateReq.setEndTime(req.getEndTime());
        List<EarningsCalculate> list = earningsCalculateMapper.totalListByDay(earningsCalculateReq);
        //组装格式
        Map<String, List<EarningsCalculate>> dataMap = list.stream().collect(Collectors.groupingBy(EarningsCalculate::getDay));
        DateTime begin = DateUtil.parse(req.getBeginTime());
        DateTime end = DateUtil.parse(req.getEndTime());
        List<EarningsCalculateData> resultList = new ArrayList<>();
        String type = req.getType();
//        if(CommonConstant.MONTH.equals(type)){
//            begin = DateUtil.beginOfMonth(begin);
//            end = DateUtil.beginOfMonth(end);
//            List<DateTime> monthTimes = DateUtil.rangeToList(begin, end, DateField.MONTH);
//        }else if(CommonConstant.YEAR.equals(type)){
//            begin = DateUtil.beginOfMonth(begin);
//            end = DateUtil.beginOfMonth(end);
//            List<DateTime> yearTimes = DateUtil.rangeToList(begin, end, DateField.YEAR);
//        }else{
        //根据天获取时间段
        List<DateTime> monthTimes = DateUtil.rangeToList(begin, end, DateField.DAY_OF_MONTH);
        String date = "";
        for (DateTime dateTime : monthTimes) {
            date = DateUtil.format(dateTime, CommonConstant.DATE_YMD);
            List<EarningsCalculate> calculateList = dataMap.get(date);
            EarningsCalculateData elecData = new EarningsCalculateData();
            elecData.setDate(date);
            BigDecimal chargeTip = BigDecimal.ZERO;
            BigDecimal chargePeak = BigDecimal.ZERO;
            BigDecimal chargeFlat = BigDecimal.ZERO;
            BigDecimal chargeValley = BigDecimal.ZERO;
            BigDecimal chargeDeepValley = BigDecimal.ZERO;
            BigDecimal chargeElec = BigDecimal.ZERO;
            BigDecimal dischargeTip = BigDecimal.ZERO;
            BigDecimal dischargePeak = BigDecimal.ZERO;
            BigDecimal dischargeFlat = BigDecimal.ZERO;
            BigDecimal dischargeValley = BigDecimal.ZERO;
            BigDecimal dischargeDeepValley = BigDecimal.ZERO;
            BigDecimal dischargeElec = BigDecimal.ZERO;
            if (null == calculateList) {
                continue;
            }
            for (EarningsCalculate e : calculateList) {
                if (CommonConstant.ZERO.equals(e.getType())) {
                    //充电数据
                    if (CommonConstant.RateType.TIP.equals(e.getRateType())) {
                        chargeTip = e.getElec();
                    } else if (CommonConstant.RateType.PEAK.equals(e.getRateType())) {
                        chargePeak = e.getElec();
                    } else if (CommonConstant.RateType.FLAT.equals(e.getRateType())) {
                        chargeFlat = e.getElec();
                    } else if (CommonConstant.RateType.VALLEY.equals(e.getRateType())) {
                        chargeValley = e.getElec();
                    } else if (CommonConstant.RateType.DEEP_VALLEY.equals(e.getRateType())) {
                        chargeDeepValley = e.getElec();
                    }
                    chargeElec = chargeElec.add(e.getElec());
                } else if (CommonConstant.ONE.equals(e.getType())) {
                    //放电数据
                    if (CommonConstant.RateType.TIP.equals(e.getRateType())) {
                        dischargeTip = e.getElec();
                    } else if (CommonConstant.RateType.PEAK.equals(e.getRateType())) {
                        dischargePeak = e.getElec();
                    } else if (CommonConstant.RateType.FLAT.equals(e.getRateType())) {
                        dischargeFlat = e.getElec();
                    } else if (CommonConstant.RateType.VALLEY.equals(e.getRateType())) {
                        dischargeValley = e.getElec();
                    } else if (CommonConstant.RateType.DEEP_VALLEY.equals(e.getRateType())) {
                        dischargeDeepValley = e.getElec();
                    }
                    dischargeElec = dischargeElec.add(e.getElec());
                }
            }
            elecData.setStationId(req.getStationId());
            elecData.setName(req.getStationName());
            elecData.setChargeTip(chargeTip);
            elecData.setChargePeak(chargePeak);
            elecData.setChargeFlat(chargeFlat);
            elecData.setChargeValley(chargeValley);
            elecData.setChargeDeepValley(chargeDeepValley);
            elecData.setDischargeTip(dischargeTip);
            elecData.setDischargePeak(dischargePeak);
            elecData.setDischargeFlat(dischargeFlat);
            elecData.setDischargeValley(dischargeValley);
            elecData.setChargeElec(chargeElec);
            elecData.setDischargeElec(dischargeElec);
            elecData.setDischargeDeepValley(dischargeDeepValley);
            resultList.add(elecData);
        }
//        }
        return resultList;
    }

    @Override
    public int deleteByStationId(String transDayStr, Integer stationId, List<Integer> typeList) {
        return earningsCalculateMapper.deleteByStationId(transDayStr, stationId, typeList);
    }

    @Override
    public BigDecimal getGroupProfit(String beginString, String endString, Integer groupId) {
        //根据时间按类型分组查询集团收益
        List<GroupProfitType> list = earningsCalculateMapper.getGroupProfit(beginString, endString, groupId);
        //根据类型分组
        Map<Integer, List<GroupProfitType>> map = list.stream().collect(Collectors.groupingBy(GroupProfitType::getType));
        //充
        List<GroupProfitType> chargeGroupProfitTypes = map.get(CHARGE);
        //放
        List<GroupProfitType> dischargeGroupProfitTypes = map.get(DISCHARGE);
        //充收益
        BigDecimal chargeProfit = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(chargeGroupProfitTypes)) {
            for (GroupProfitType chargeGroupProfitType : chargeGroupProfitTypes) {
                chargeProfit = chargeGroupProfitType.getDigital() != null ? chargeProfit.add(chargeGroupProfitType.getDigital()) : chargeProfit;
            }
        }
        //放收益
        BigDecimal dischargeProfit = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(dischargeGroupProfitTypes)) {
            for (GroupProfitType chargeGroupProfitType : dischargeGroupProfitTypes) {
                dischargeProfit = chargeGroupProfitType.getDigital() != null ? dischargeProfit.add(chargeGroupProfitType.getDigital()) : dischargeProfit;
            }
        }
        BigDecimal result = dischargeProfit.subtract(chargeProfit);
        if (result.doubleValue() < 0.0) {
            return BigDecimal.ZERO;
        }
        return result;
    }

    @Override
    public List<StationProfitType> getStationProfit(String beginString, String endString, Integer groupId) {
        return earningsCalculateMapper.getStationProfit(beginString, endString, groupId);
    }

    @Override
    public List<DayProfitType> getDayProfit(String beginString, String endString, Integer groupId) {
        return earningsCalculateMapper.getDayProfit(beginString, endString, groupId);
    }

    @Override
    public Date getFirstTime() {
        String day = earningsCalculateMapper.getFirstTime();
        DateTime date = null;
        if(day!=null){
            date = DateUtil.parse(day, CommonConstant.DATE_YMD);
        }
        return date;
    }

    @Override
    public List<DayProfitType> getProfit(String begin, String end, Integer groupId) {
        return earningsCalculateMapper.getProfit(begin, end, groupId);

    }

    @Override
    public List<RevenueOverviewData> getRevenueOverviewData(ReportReqVO vo) {
        String dateType = vo.getDateType();
        if (dateType == null) {
            dateType = CommonConstant.DAY;
        }
        String beginTime = vo.getBeginTime();
        String endTime = vo.getEndTime();
        //设置默认值为当月
        Date begin = null;
        if (beginTime == null) {
            begin = DateUtil.beginOfMonth(new Date());
            beginTime = DateUtil.formatDate(begin);
        }
        Date end = null;
        if (endTime == null) {
            end = DateUtil.endOfMonth(new Date());
            endTime = DateUtil.formatDate(end);
        }
        //创建返回值
        List<RevenueOverviewData> list = new ArrayList<>();
        if (CommonConstant.DAY.equals(dateType) && beginTime != null && endTime != null) {
            begin = DateUtil.beginOfDay(DateUtil.parse(beginTime));
            end = DateUtil.endOfDay(DateUtil.parse(endTime));
            List<EarningsCalculate> earningsCalculateList = getEarningsCalculateList(vo, begin, end);
            Map<String, List<EarningsCalculate>> map = earningsCalculateList.stream().collect(Collectors.groupingBy(EarningsCalculate::getDay));
            setRevenueOverviewDataList(list, map, vo.getSettlementRate());
        } else if (CommonConstant.MONTH.equals(dateType) && beginTime != null && endTime != null) {
            begin = DateUtil.beginOfMonth(DateUtil.parse(beginTime));
            end = DateUtil.endOfMonth(DateUtil.parse(endTime));
            List<EarningsCalculate> earningsCalculateList = getEarningsCalculateList(vo, begin, end);
            Map<String, List<EarningsCalculate>> map = earningsCalculateList.stream().map(s -> {
                s.setDay(s.getDay().substring(0, 6));
                return s;
            }).collect(Collectors.groupingBy(EarningsCalculate::getDay));
            setRevenueOverviewDataList(list, map, vo.getSettlementRate());
        } else if (CommonConstant.YEAR.equals(dateType) && beginTime != null && endTime != null) {
            begin = DateUtil.beginOfYear(DateUtil.parse(beginTime));
            end = DateUtil.endOfYear(DateUtil.parse(endTime));
            List<EarningsCalculate> earningsCalculateList = getEarningsCalculateList(vo, begin, end);
            Map<String, List<EarningsCalculate>> map = earningsCalculateList.stream().map(s -> {
                s.setDay(s.getDay().substring(0, 3));
                return s;
            }).collect(Collectors.groupingBy(EarningsCalculate::getDay));
            setRevenueOverviewDataList(list, map, vo.getSettlementRate());
        }

        return list.stream().sorted(new Comparator<RevenueOverviewData>() {
            @Override
            public int compare(RevenueOverviewData o1, RevenueOverviewData o2) {
                return o1.getTime().compareTo(o2.getTime());
            }
        }).collect(Collectors.toList());
    }

    private void setRevenueOverviewDataList(List<RevenueOverviewData> list, Map<String, List<EarningsCalculate>> map, BigDecimal settlementRate) {
        map.forEach((k, v) -> {
            RevenueOverviewData data = new RevenueOverviewData();
            data.setTime(k);
            BigDecimal chargeRevenue = BigDecimal.ZERO;
            BigDecimal dischargeRevenue = BigDecimal.ZERO;

            BigDecimal charge = BigDecimal.ZERO;
            BigDecimal tipCharge = BigDecimal.ZERO;
            BigDecimal peakCharge = BigDecimal.ZERO;
            BigDecimal flatCharge = BigDecimal.ZERO;
            BigDecimal valleyCharge = BigDecimal.ZERO;
            BigDecimal deepValleyCharge = BigDecimal.ZERO;

            BigDecimal discharge = BigDecimal.ZERO;
            BigDecimal tipDischarge = BigDecimal.ZERO;
            BigDecimal peakDischarge = BigDecimal.ZERO;
            BigDecimal flatDischarge = BigDecimal.ZERO;
            BigDecimal valleyDischarge = BigDecimal.ZERO;
            BigDecimal deepValleyDischarge = BigDecimal.ZERO;

            for (EarningsCalculate e : v) {
                if (CommonConstant.ZERO.equals(e.getType())) {
                    //充电数据
                    if (e.getRateType().contains(CommonConstant.RateTypeSimple.TIP)) {
                        tipCharge = e.getElec() != null ? tipCharge.add(e.getElec()) : tipCharge;
                    } else if (e.getRateType().contains(CommonConstant.RateTypeSimple.PEAK)) {
                        peakCharge = e.getElec() != null ? peakCharge.add(e.getElec()) : peakCharge;
                    } else if (e.getRateType().contains(CommonConstant.RateTypeSimple.FLAT)) {
                        flatCharge = e.getElec() != null ? flatCharge.add(e.getElec()) : flatCharge;
                    } else if (e.getRateType().contains(CommonConstant.RateTypeSimple.VALLEY)) {
                        valleyCharge = e.getElec() != null ? valleyCharge.add(e.getElec()) : valleyCharge;
                    } else if (e.getRateType().contains(CommonConstant.RateTypeSimple.DEEP_VALLEY)) {
                        deepValleyCharge = e.getElec() != null ? deepValleyCharge.add(e.getElec()) : deepValleyCharge;
                    }
                    charge = e.getElec() != null ? charge.add(e.getElec()) : charge;
                    chargeRevenue = e.getDigital() != null ? chargeRevenue.add(e.getDigital()) : chargeRevenue;
                } else if (CommonConstant.ONE.equals(e.getType())) {
                    //放电数据
                    if (e.getRateType().contains(CommonConstant.RateTypeSimple.TIP)) {
                        tipDischarge = e.getElec() != null ? tipDischarge.add(e.getElec()) : tipDischarge;
                    } else if (e.getRateType().contains(CommonConstant.RateTypeSimple.PEAK)) {
                        peakDischarge = e.getElec() != null ? peakDischarge.add(e.getElec()) : peakDischarge;
                    } else if (e.getRateType().contains(CommonConstant.RateTypeSimple.FLAT)) {
                        flatDischarge = e.getElec() != null ? flatDischarge.add(e.getElec()) : flatDischarge;
                    } else if (e.getRateType().contains(CommonConstant.RateTypeSimple.VALLEY)) {
                        valleyDischarge = e.getElec() != null ? valleyDischarge.add(e.getElec()) : valleyDischarge;
                    } else if (e.getRateType().contains(CommonConstant.RateTypeSimple.DEEP_VALLEY)) {
                        deepValleyDischarge = e.getElec() != null ? deepValleyDischarge.add(e.getElec()) : deepValleyDischarge;
                    }
                    discharge = e.getElec() != null ? discharge.add(e.getElec()) : discharge;
                    dischargeRevenue = e.getDigital() != null ? dischargeRevenue.add(e.getDigital()) : dischargeRevenue;
                }
            }
            BigDecimal revenue = dischargeRevenue.subtract(chargeRevenue);
            data.setRevenue(revenue);
            data.setTipCharge(tipCharge);
            data.setFlatCharge(flatCharge);
            data.setPeakCharge(peakCharge);
            data.setValleyCharge(valleyCharge);
            data.setDeepValleyCharge(deepValleyCharge);

            data.setTipDischarge(tipDischarge);
            data.setPeakDischarge(peakDischarge);
            data.setValleyDischarge(valleyDischarge);
            data.setFlatDischarge(flatDischarge);
            data.setDeepValleyDischarge(deepValleyDischarge);

            data.setChargeRevenue(chargeRevenue);
            data.setDischargeRevenue(dischargeRevenue);

            BigDecimal conversionRate = null;
            try {
                int i = charge.compareTo(BigDecimal.ZERO);
                conversionRate = i != 0 ? discharge.divide(charge, BigDecimal.ROUND_HALF_UP, 2) : BigDecimal.ZERO;
            } catch (Exception e) {
                System.out.println(k);
                e.printStackTrace();
            }
            data.setConversionRate(conversionRate.multiply(new BigDecimal("100")));
            data.setSettlementRevenue(revenue.multiply(settlementRate).divide(new BigDecimal("100"), BigDecimal.ROUND_HALF_UP, 2));
            list.add(data);
        });
    }

    private List<EarningsCalculate> getEarningsCalculateList(ReportReqVO vo, Date begin, Date end) {
        //查询对应数据
        EarningsCalculateReq calculateReq = new EarningsCalculateReq();
        calculateReq.setBeginTime(DateUtil.formatDate(begin));
        calculateReq.setEndTime(DateUtil.formatDate(end));
        calculateReq.setStationId(vo.getStationId());
        return earningsCalculateMapper.selectList(calculateReq);
    }

    @Override
    public RevenueOverview getInvestment(ReportReqVO vo) {
        RevenueOverview revenueOverview = new RevenueOverview();
        //根据id查询电站
        Station station = stationService.selectById(vo.getStationId());
        if (station == null) {
            throw new BusinessException(BaseResponseCode.STATION_YC_NOT_EXISTS);
        }
        //计算运行天数
        long operationDays = DateUtil.between(station.getGridTime(), new Date(), DateUnit.DAY);
        revenueOverview.setStationName(station.getName());
        revenueOverview.setCapacity(station.getCapacity());
        revenueOverview.setOperationDays((int) operationDays);

        List<RevenueOverviewData> list = getRevenueOverviewData(vo);

        BigDecimal chargingPrice = BigDecimal.ZERO;
        BigDecimal dischargingPrice = BigDecimal.ZERO;
        BigDecimal revenue = BigDecimal.ZERO;

        BigDecimal charging = BigDecimal.ZERO;
        BigDecimal discharging = BigDecimal.ZERO;
        for (RevenueOverviewData data : list) {
            chargingPrice = chargingPrice.add(data.getChargeRevenue());
            dischargingPrice = dischargingPrice.add(data.getDischargeRevenue());
            revenue = revenue.add(data.getRevenue());
            charging = charging.add(data.getTipCharge()).add(data.getFlatCharge())
                    .add(data.getPeakCharge()).add(data.getValleyCharge()).add(data.getDeepValleyCharge());
            discharging = discharging.add(data.getTipDischarge()).add(data.getFlatDischarge())
                    .add(data.getPeakDischarge()).add(data.getValleyDischarge()).add(data.getDeepValleyDischarge());
        }

        revenueOverview.setChargingPrice(chargingPrice);
        revenueOverview.setDischargingPrice(dischargingPrice);
        revenueOverview.setRevenue(revenue);
        revenueOverview.setSettlementRevenue(revenue.multiply(vo.getSettlementRate()).divide(new BigDecimal("100"), BigDecimal.ROUND_HALF_UP, 2));
        revenueOverview.setSettlementRate(vo.getSettlementRate());
        vo.setBeginTime(DateUtil.formatDate(station.getCreateTime()));
        vo.setEndTime(DateUtil.formatDate(new Date()));
        List<RevenueOverviewData> revenueOverviewDataList = getRevenueOverviewData(vo);
        BigDecimal totalRevenue = BigDecimal.ZERO;
        for (RevenueOverviewData data : revenueOverviewDataList) {
            totalRevenue = totalRevenue.add(data.getRevenue());
        }
        revenueOverview.setTotalRevenue(totalRevenue.divide(new BigDecimal("10000"), BigDecimal.ROUND_HALF_UP, 2));
        //总充电量
        BigDecimal totalChargeElec = BigDecimal.ZERO;
//总放电量
        BigDecimal totalDischargeElec = BigDecimal.ZERO;

        Integer stationId = vo.getStationId();
        String deviceType = null;
        ColCountReq colCountReq = new ColCountReq();
        colCountReq.setStationId(stationId);
        List<String> colsList = new ArrayList<>();
        colsList.add(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
        colsList.add(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
        List<ColCountResp> colCountList = colCountService.selectByParam(colCountReq);
        Map<String, List<ColCountResp>> colMap = colCountList.stream().collect(Collectors.groupingBy(ColCount::getCol));
        List<ColCountResp> chargeList = colMap.get(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
        List<ColCountResp> disChargeList = colMap.get(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
        if(chargeList != null){
            deviceType = chargeList.get(0).getDeviceType();
        }

        List<DeviceRespVO> deviceRespVOS = deviceService.getListByDeviceType(stationId, deviceType);
        if (deviceRespVOS.isEmpty()) {
            deviceRespVOS = deviceService.getListByFuzzyDeviceType(stationId, deviceType);
        }

        for (DeviceRespVO deviceRespVO : deviceRespVOS) {
            //拼接电表缓存key
            String redisKey = deviceRespVO.getDeviceType() + ":" + deviceRespVO.getStationId() + ":" + deviceRespVO.getSrcId();
            //判断电表换是否存在
            if (redisService.hasKey(redisKey)) {
                Map<Object, Object> map = redisService.hgetall(redisKey);
                if (map != null) {
                    //总充, 总放
                    Object objTotalCharge = map.get(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
                    if (objTotalCharge instanceof DeviceTransfer) {
                        DeviceTransfer totalCharge = (DeviceTransfer) map.get(DataCollectConstant.Elec_Meter.TOTAL_CHARGE);
                        totalChargeElec = totalCharge.getValue() != null ? totalChargeElec.add(totalCharge.getValue()) : totalChargeElec;
                    }
                    Object objTotalDischarge = map.get(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
                    if (objTotalDischarge instanceof DeviceTransfer) {
                        DeviceTransfer totalDischarge = (DeviceTransfer) map.get(DataCollectConstant.Elec_Meter.TOTAL_DISCHARGE);
                        totalDischargeElec = totalDischarge.getValue() != null ? totalDischargeElec.add(totalDischarge.getValue()) : totalDischargeElec;
                    }
                }
            }
        }
        //加上偏移量
        totalChargeElec = colCountService.countOffset(totalChargeElec, chargeList);
        totalDischargeElec = colCountService.countOffset(totalDischargeElec, disChargeList);
        revenueOverview.setCharging(totalChargeElec);
        revenueOverview.setDischarging(totalDischargeElec);

        BigDecimal revenueProfit = charging.compareTo(BigDecimal.ZERO) == 0 || discharging.compareTo(BigDecimal.ZERO) == 0
                ? BigDecimal.ZERO : discharging.divide(charging, BigDecimal.ROUND_HALF_UP, 4).multiply(new BigDecimal("100"));
        revenueOverview.setRevenueProfit(revenueProfit);
        return revenueOverview;
    }

    @Override
    public void export(ReportReqVO vo, HttpServletResponse response) {

    }

    @Override
    public List<Map<String, Object>> getElecPrice(Integer stationId) {
        List<EarningsCalculateSub> earningsCalculateSubs = queryElecTemplateSubByStationId(stationId, 0, DateUtil.now());
        Map<String, List<EarningsCalculateSub>> map = earningsCalculateSubs.stream().collect(Collectors.groupingBy(EarningsCalculateSub::getType));
        List<EarningsCalculateSub> list = new ArrayList<>();
        map.forEach((k, v) -> {
            EarningsCalculateSub data = new EarningsCalculateSub();
            data.setPrice(v.get(0).getPrice());
            String time = "";
            for (EarningsCalculateSub earningsCalculateSub : v) {
                if (StringUtils.isEmpty(time)) {
                    time = earningsCalculateSub.getBeginTime() + "-" + earningsCalculateSub.getEndTime();
                } else {
                    time = time + "," + earningsCalculateSub.getBeginTime() + "-" + earningsCalculateSub.getEndTime();
                }
            }
            data.setBeginTime(time);
            data.setType(k);
            list.add(data);
        });
        List<Map<String, Object>> listData = new ArrayList<>();
        for (EarningsCalculateSub earningsCalculateSub : list) {
            Map lowMap = new HashMap<>();
            lowMap.put("name", earningsCalculateSub.getType());
            ArrayList<BigDecimal> lowList = list(earningsCalculateSub);
            lowMap.put("list", lowList);
            listData.add(lowMap);
        }
        return listData;
    }

    @Override
    public List<DayProfitType> getEarningsByParam(CommonBigScreenReq req) {
        return earningsCalculateMapper.getEarningsByParam(req);
    }

    @Override
    public List<PowerGenerateRespVO> getPvMonthData(EarningsCalculateReq req) {
        List<PowerGenerateRespVO> list = new ArrayList<>();
        LocalDateTime mDate = DateUtil.parse(req.getTime(), CommonConstant.DATE_YM).toLocalDateTime();
        LocalDateTime begin = mDate.with(TemporalAdjusters.firstDayOfMonth());
        LocalDateTime end = mDate.with(TemporalAdjusters.lastDayOfMonth());
        String beginTime= DateUtil.format(begin, CommonConstant.DATE_YMD);
        String endTime = DateUtil.format(end, CommonConstant.DATE_YMD);
        //光伏收益
        List<PowerGenerateRespVO> pvIncome = earningsCalculateMpptService.countPvIncome(req.getStationId(),beginTime, endTime);
        Map<String,List<PowerGenerateRespVO>> mapIncome = pvIncome.stream().collect(Collectors.groupingBy(i ->i.getDate()));
        //光伏放电
        List<Integer> types = new ArrayList<>();
        types.add(DeviceTypeConstant.ELEC_METER_VALUE_TYPE.PV_CHARGE);
        List<ElecMeterValue> elecMeterValues = elecMeterValueService.selectList(req.getStationId(), types, beginTime, endTime);
        Map<String, List<ElecMeterValue>> mapMeter = elecMeterValues.stream().collect(Collectors.groupingBy(i ->i.getDay()));

        //根据天获取时间段
        List<DateTime> dateTimes = DateUtil.rangeToList(DateUtil.parse(beginTime), DateUtil.parse(endTime), DateField.DAY_OF_MONTH);
        for (DateTime dateTime : dateTimes){
            String date = DateUtil.format(dateTime, CommonConstant.DATE_YMD);
            PowerGenerateRespVO  pv = new PowerGenerateRespVO();
            pv.setDate(date);
            List<PowerGenerateRespVO> pvIn = mapIncome.get(date);
            //收益
            if(pvIn != null){
                pv.setProfit(pvIn.get(0).getProfit());
            }
            //放电
            List<ElecMeterValue> elecs = mapMeter.get(date);
            if(elecs != null){
                pv.setPowerGenerate(elecs.stream().map(ElecMeterValue::getDigital).reduce(BigDecimal.ZERO,BigDecimal::add));
            }
            if(date.equals(endTime)){
                String key = RedisKeyConstant.PV.STATION_PV_TODAY_PROFIT + req.getStationId();
                //获取今日收益
                BigDecimal todayIncone = (BigDecimal)redisService.get(key);
                pv.setProfit(todayIncone);
                //获取今日发电
                //当前功率(光伏)、总发电量、日发电量
                MpptActiveVo todayPv = openStationService.getPvActivePower(req.getStationId());
                pv.setPowerGenerate(todayPv.getDailyReleaseElec());

            }
            list.add(pv);
        }
        return list;
    }

    public static ArrayList<BigDecimal> list(EarningsCalculateSub earningsCalculateSub) {
        BigDecimal[] bigDecimal = new BigDecimal[49];
        ArrayList<BigDecimal> list = new ArrayList<BigDecimal>(Arrays.asList(bigDecimal));
        String time = earningsCalculateSub.getBeginTime();
        String[] split;
        if (time.contains(",")) {
            //这种格式22:00-24:00,00:00-06:00
            split = time.split(",");
        } else {
            //这种格式22:00-24:00
            split = new String[1];
            split[0] = time;
        }
        for (int i = 0; i < split.length; i++) {
            //22:30-24:00
            String s = split[i];

            String[] timeSplit = split[i].split("-");
            if (timeSplit.length < 2) {
                continue;
            }
            if (timeSplit[0].split(":").length < 2) {
                continue;
            }
            String startTime = timeSplit[0].split(":")[0];
            if (timeSplit[1].split(":").length < 2) {
                continue;
            }
            String endTime = timeSplit[1].split(":")[0];
            Integer start = null;
            Integer end = null;
            if (startTime.startsWith("0") && !"00".equals(startTime)) {
                startTime = startTime.split("0")[1];
            }
            if (endTime.startsWith("0") && !"00".equals(endTime)) {
                endTime = endTime.split("0")[1];
            }
            if (timeSplit[0].contains(":00")) {
                start = Integer.parseInt(startTime) * 2;
            } else {
                start = Integer.parseInt(startTime) * 2 + 1;
            }
            if (timeSplit[1].contains(":00")) {
                end = Integer.parseInt(endTime) * 2;
            } else {
                end = Integer.parseInt(endTime) * 2 + 1;
            }
            for (int j = start; j <= end; j++) {
                list.set(j, earningsCalculateSub.getPrice());
            }
            if (earningsCalculateSub.getBeginTime().contains("23:59")) {
                list.set(48, earningsCalculateSub.getPrice());
            }
        }
        return list;
    }

    public static boolean isInterval(String interval) {
        String pattern = "^((2[0-3]|[01]?[0-9]):[03][0])-((2[0-4]|[01]?[0-9]):[03][0])$";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(interval);
        return m.matches();
    }
}
