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.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.DeviceTypeConfig;
import com.ho.business.entity.IncomeTotal;
import com.ho.business.entity.ModelDeviceColComp;
import com.ho.business.entity.Station;
import com.ho.business.feignclient.TdFeignClient;
import com.ho.business.service.*;
import com.ho.business.vo.req.DeviceReqVO;
import com.ho.business.vo.req.StationReq;
import com.ho.business.vo.resp.DeviceRespVO;
import com.ho.business.vo.resp.InverterResp.*;
import com.ho.business.vo.resp.chargepile.ChargePileRespVO;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.BigDecimalUtil;
import com.ho.common.tools.util.RedisCommon;
import com.ho.datacollect.api.vo.req.StatisticsRespVO;
import com.ho.datacollect.api.vo.req.add.TdBase;
import com.ho.datacollect.api.vo.req.inverter.InverterCurveListVo;
import com.ho.td.api.entity.TdDeviceIdEntity;
import com.ho.td.api.entity.inverter.InverterCurrent;
import com.ho.td.api.entity.query.DeviceIdAndTypeVo;
import com.ho.td.api.entity.query.TdBaseTimeQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author fancl
 * @desc: 光伏电站实现类
 * @date 2023/1/6
 */
@Slf4j
@Service
public class PvStationServiceImpl implements PvStationService {

    @Autowired
    RedisService redisService;

    @Autowired
    StationService stationService;

    @Autowired
    TdFeignClient tdFeignClient;

    @Autowired
    RedisCommon redisUtil;

    @Autowired
    JoinTbSuffixService joinTbSuffixService;

    @Autowired
    ElecPriceService elecPriceService;

    @Autowired
    IncomeTotalService incomeTotalService;

    @Autowired
    DeviceService deviceService;

    @Autowired
    ModelDeviceService modelDeviceService;

    @Autowired
    BigDecimalUtil bigDecimalUtil;

    @Autowired
    DeviceTypeConfigService deviceTypeConfigService;

    @Value("${energy.co2ToCole}")
    BigDecimal co2ToCole;

    //碳排放因子
    @Value("${inverter.co2Factor}")
    String co2Factor;


    @Value("${station.timeDifference}")
    Integer minute;


    //查询逆变器
    //目前4种 阳光 禾望 华为 固德威
    @Override
    public List<DeviceRespVO> getIntervalsByStationId(Integer stationId) {
        DeviceReqVO reqVO = new DeviceReqVO();
        reqVO.setStationId(stationId);
        reqVO.setDeviceTypePrefix(DeviceTypeConstant.INVERTER_PREFIX);
        List<DeviceRespVO> list = deviceService.getList(reqVO);
        return list;
    }

    //光伏电站面板数据
    @Override
    public PVStationPanelRespVO getPvPanel(Integer stationId, List<DeviceRespVO> deviceRespVOS) {
        PVStationPanelRespVO pv = new PVStationPanelRespVO();
        //查询电站信息获取装机容量、运行天数
        Station station = stationService.selectById(stationId);
        //电站为空 直接返回空数据
        if (station == null) {
            log.error("未查到对应电站, stationId:" + stationId);
            return pv;
        }
        //先设置装机容量
        //装机容量 直接取电站装机容量
        BigDecimal capacity = null;
        capacity = station.getCapacity();
        pv.setCapacity(capacity);
        // 累计运行时间单位hour ,合计后 (累计运行天数)再除以24 得到 cumulativeConnectDay
        Long cumulativeConnectTime = 0L;
        //累计运行时间(取最大值的运行时间)
        Date createTime = station.getGridTime();
        Date newDate = new Date();
        long createDateTime = createTime.getTime();
        long newDateTime = newDate.getTime();
        cumulativeConnectTime = ((newDateTime - createDateTime) / (1000 * 60 * 60 * 24));
        //累计运行时间 cumulativeConnectDay = cumulativeConnectTime/24向上取整
        int cumulativeConnectDay = 0;
        if (cumulativeConnectTime != null && cumulativeConnectTime.compareTo(0L) > 0) {
            cumulativeConnectDay = (int) Math.ceil((double) cumulativeConnectTime);
        }
        //给累计运行天数赋值
        pv.setCumulativeConnectDay(cumulativeConnectDay);
        if (deviceRespVOS == null || deviceRespVOS.isEmpty()) {
            return pv;
        }
        //日等效小时 = 日发电量/装机容量
        BigDecimal dailyEquivalentHour = BigDecimal.ZERO;
        //日发电量 合计
        BigDecimal dailyPowerGeneration = BigDecimal.ZERO;
        //累计发电量 合计
        BigDecimal cumulativePowerGeneration = BigDecimal.ZERO;
        //有功功率 取值交流有功功率 合计
        BigDecimal acActivePower = BigDecimal.ZERO;
        //二氧化碳减排量 Kg 合计 然后乘以系数得到标准煤的kg  savingStandardCoal
        BigDecimal co2Reductions = BigDecimal.ZERO;
        //标准煤 kg
        BigDecimal savingStandardCoal = BigDecimal.ZERO;

        //出力指数, 有功功率合计值/装机容量 *100%
        BigDecimal outputIndex = BigDecimal.ZERO;
        //逆变器台数 等于拓扑数据
        Integer inverterCount = deviceRespVOS.size();

        //交流无功功率 合计
        BigDecimal acReactivePower = BigDecimal.ZERO;

        //当月发电量
        BigDecimal currentMonthPowerGeneration = BigDecimal.ZERO;
        //当年
        BigDecimal currentYearPowerGeneration = BigDecimal.ZERO;
        List<Integer> srcIdList = deviceRespVOS.stream().map(s -> {
                    return s.getSrcId();
                }
        ).collect(Collectors.toList());

        //逆变器台数
        pv.setInverterCount(inverterCount);
        //在线的设备
        int onLine = 0;
        log.info("循环处理各个逆变器 start:" + System.currentTimeMillis());
        //循环处理各个逆变器
        for (DeviceRespVO topology : deviceRespVOS) {
            //各个数据从缓存取值
            String inverterKey = topology.getDeviceType() + ":" + stationId + ":" + topology.getSrcId();
            //没有对应缓存,continue
            if (!redisService.hasKey(inverterKey)) {
                continue;
            }
            ModelNewInverter modelInverter = new ModelNewInverter();
            Map<Object, Object> inverterMap = redisService.hgetall(inverterKey);
            if (inverterMap != null) {
                modelInverter = JSON.parseObject(JSON.toJSONString(inverterMap), ModelNewInverter.class);
            }
            //日发电量
            //定义一个本次日发电量
            BigDecimal theDailyPowerGeneration = BigDecimal.ZERO;
            if (modelInverter.getDailyPowerGeneration() != null && modelInverter.getDailyPowerGeneration().getValue() != null) {
                theDailyPowerGeneration = modelInverter.getDailyPowerGeneration().getValue();
            }
            dailyPowerGeneration = dailyPowerGeneration.add(theDailyPowerGeneration);
            //累计发电量
            //定义一个本次累计发电量
            BigDecimal theCumulativePowerGeneration = BigDecimal.ZERO;
            if (modelInverter.getCumulativePowerGeneration() != null && modelInverter.getCumulativePowerGeneration().getValue() != null) {
                theCumulativePowerGeneration = modelInverter.getCumulativePowerGeneration().getValue();
            }
            cumulativePowerGeneration = cumulativePowerGeneration.add(theCumulativePowerGeneration);
            //日等效小时

            //交流有功功率 acActivePower
            //本次交流有功功率
            BigDecimal theAcActivePower = BigDecimal.ZERO;
            if (modelInverter.getAcActivePower() != null && modelInverter.getAcActivePower().getValue() != null) {
                theAcActivePower = modelInverter.getAcActivePower().getValue();
            }
            acActivePower = acActivePower.add(theAcActivePower);
            //C02排放量 kg
            //禾望直接取，如果没有则进行总发电量*0.997
            //二氧化碳减排量
/*            //在进行逆变器类型判断
            Device device = deviceService.selectByStationIdAndSrcId(stationId, topology.getSrcId());
            String deviceType = device.getDeviceType();*/
            BigDecimal cumulative = BigDecimal.ZERO;
            if (modelInverter.getCumulativePowerGeneration() != null && modelInverter.getCumulativePowerGeneration().getValue() != null) {
                cumulative = modelInverter.getCumulativePowerGeneration().getValue();
            }
            BigDecimal multiply = cumulative.multiply(new BigDecimal(co2Factor));
            co2Reductions = co2Reductions.add(multiply);


            //在线的设备更新时间和现在时间相差大于5分钟，则认为时离线
            Date updateTime = modelInverter.getUpdateTime();
            if (updateTime != null) {
                long between = DateUtil.between(updateTime, new Date(), DateUnit.MINUTE);
                //如果时间差值大于5 ,则设备的离线个数+1
                if (between < minute) {
                    onLine++;
                }
            }
            //交流无功功率
            //本次无功交流功率
            BigDecimal theAcReactivePower = BigDecimal.ZERO;
            if (modelInverter.getAcReactivePower() != null && modelInverter.getAcReactivePower().getValue() != null) {
                theAcReactivePower = modelInverter.getAcReactivePower().getValue();
            }
            acReactivePower = acReactivePower.add(theAcReactivePower);
        }
        long start = System.currentTimeMillis();
        log.info("循环处理各个逆变器 end:" + start);
        List<ChargePileRespVO> chargePileRespVOS = deviceService.selectBySrcIds(stationId, srcIdList);
        TdBaseTimeQuery tdBaseTimeQuery = new TdBaseTimeQuery();
        Map<String, String> colNameMap = new HashMap<>();
        List<TdDeviceIdEntity> tdDeviceIds = new ArrayList<>();
        TdDeviceIdEntity tdDeviceIdEntity = new TdDeviceIdEntity();
        tdDeviceIdEntity.setStationId(stationId);
        tdBaseTimeQuery.setGroupId(station.getGroupId());
        List<DeviceIdAndTypeVo> deviceIdAndTypeVos = chargePileRespVOS.stream().map(s -> {
            DeviceIdAndTypeVo deviceIdAndTypeVo = new DeviceIdAndTypeVo();
            deviceIdAndTypeVo.setDeviceType(s.getDeviceType());
            deviceIdAndTypeVo.setSrcId(s.getSrcId());
            return deviceIdAndTypeVo;
        }).collect(Collectors.toList());

        deviceIdAndTypeVos.stream().forEach(s -> {
            if (colNameMap.get(s.getDeviceType()) == null) {
                List<ModelDeviceColComp> acActivePowerList = modelDeviceService.getCompListByType("device", s.getDeviceType(), "cumulativePowerGeneration");
                for (int i = 0; i < acActivePowerList.size(); i++) {
                    ModelDeviceColComp cumulativePowerGenerationCol = acActivePowerList.get(CommonConstant.ZERO);
                    colNameMap.put(s.getDeviceType(), cumulativePowerGenerationCol.getDeviceCol());
                }

            }
        });
        tdDeviceIdEntity.setDeviceIdAndTypeVos(deviceIdAndTypeVos);
        tdDeviceIds.add(tdDeviceIdEntity);
        tdBaseTimeQuery.setColNameMap(colNameMap);
        tdBaseTimeQuery.setTdDeviceIds(tdDeviceIds);
        long startOpen = System.currentTimeMillis();
        log.info("getCurrentMonthAndYear start:" + startOpen);
        DataResult<List<InverterCurrent>> currentMonthAndYear = tdFeignClient.getCurrentMonthAndYear(tdBaseTimeQuery);
        long endOpen = System.currentTimeMillis();
        long used = endOpen - startOpen;
        log.info("getCurrentMonthAndYear end:" + System.currentTimeMillis());
        log.info("getCurrentMonthAndYear used:" + used);
        if (currentMonthAndYear.isSuccess() && currentMonthAndYear.getData() != null) {
            if (!currentMonthAndYear.getData().isEmpty()) {
                InverterCurrent inverterCurrent = currentMonthAndYear.getData().get(currentMonthAndYear.getData().size() - 1);
                currentMonthPowerGeneration = inverterCurrent.getCurrentMonthPowerGeneration() != null ? cumulativePowerGeneration.subtract(inverterCurrent.getCurrentMonthPowerGeneration()) : cumulativePowerGeneration;
                currentYearPowerGeneration = inverterCurrent.getCurrentYearPowerGeneration() != null ? cumulativePowerGeneration.subtract(inverterCurrent.getCurrentYearPowerGeneration()) : cumulativePowerGeneration;
                //月发电量
                pv.setCurrentMonthPowerGeneration(currentMonthPowerGeneration);
                //年发电量
                pv.setCurrentYearPowerGeneration(currentYearPowerGeneration);
            } else {
                //月发电量
                pv.setCurrentMonthPowerGeneration(cumulativePowerGeneration);
                //年发电量
                pv.setCurrentYearPowerGeneration(cumulativePowerGeneration);
            }
        } else {
            //月发电量
            pv.setCurrentMonthPowerGeneration(cumulativePowerGeneration);
            //年发电量
            pv.setCurrentYearPowerGeneration(cumulativePowerGeneration);
        }
        //循环完毕后给各个值赋值
        //日发电量
        pv.setDailyPowerGeneration(dailyPowerGeneration);

        BigDecimal stationCap = station.getCapacity();
        if (stationCap != null && BigDecimal.ZERO.compareTo(stationCap) != 0) {
            dailyEquivalentHour = dailyPowerGeneration.divide(stationCap, 2, BigDecimal.ROUND_HALF_UP);
        }
        //日等效小时
        pv.setDailyEquivalentHour(dailyEquivalentHour);
        //累计发电量 cumulativePowerGeneration
        pv.setCumulativePowerGeneration(cumulativePowerGeneration);
        //二氧化碳排放量
        pv.setCo2Reductions(co2Reductions);
        //交流有功功率  acActivePower
        pv.setAcActivePower(acActivePower);
        //出力指数 =有功功率之和/capacity 如果装机容量有有效值,才进行赋值计算
        if (capacity != null && capacity.compareTo(BigDecimal.ZERO) != 0) {
            outputIndex = acActivePower.divide(capacity, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        pv.setOutputIndex(outputIndex);
        //无功功率
        pv.setAcReactivePower(acReactivePower);
        //标准煤 由二氧化碳排放量 co2Reductions * 系数
        savingStandardCoal = co2Reductions.multiply(co2ToCole).setScale(2, BigDecimal.ROUND_HALF_UP);
        pv.setSavingStandardCoal(savingStandardCoal);
        //在线率
        BigDecimal rate = BigDecimal.ZERO;
        if (inverterCount != 0) {
            BigDecimal onLineBig = new BigDecimal(onLine);
            BigDecimal all = new BigDecimal(inverterCount);
            rate = onLineBig.divide(all, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        pv.setOnlineRate(rate);
        //电网频率 取第一个就行
        //判断topologies 是否为空
        BigDecimal gridFreq = BigDecimal.ZERO;
        if (deviceRespVOS.isEmpty()) {
            gridFreq = BigDecimal.ZERO;
        } else {
            if (!deviceRespVOS.isEmpty()) {
                DeviceRespVO deviceRespVO = deviceRespVOS.get(0);
                String inverterKey = deviceRespVO.getDeviceType() + ":" + stationId + ":" + deviceRespVO.getSrcId();
                log.info("inverterKey:{}", inverterKey);
                if (redisService.hasKey(inverterKey)) {
                    Map<Object, Object> inverterMap = redisService.hgetall(inverterKey);
                    if (inverterMap != null) {
                        ModelNewInverter modelInverter = new ModelNewInverter();
                        modelInverter = JSON.parseObject(JSON.toJSONString(inverterMap), ModelNewInverter.class);
                        if (modelInverter.getGridFreq() != null && modelInverter.getGridFreq().getValue() != null) {
                            gridFreq = modelInverter.getGridFreq().getValue();
                        }
                    }
                }
            }
        }
        pv.setGridFreq(gridFreq);
        return pv;
    }


    @Override
    public List<RealtimeCurveRespVO> getRealtimeCurve(Integer stationId, List<DeviceRespVO> topologies) {
        log.info("getRealtimeCurve start:" + System.currentTimeMillis());
        Station station = stationService.selectById(stationId);
        if (station == null) {
            return new ArrayList<>();
        }
        //计算当天开始时间
        Date day = new Date();
        DateTime yesterday = DateUtil.yesterday();
        String beginTime = DateUtil.format(DateUtil.beginOfDay(day), CommonConstant.DATE);
        String yesterdayBeginTime = DateUtil.format(DateUtil.beginOfDay(yesterday), CommonConstant.DATE);
        String endTime = DateUtil.format(day, CommonConstant.DATE);
        String yesterdayEndTime = DateUtil.format(DateUtil.endOfDay(yesterday), CommonConstant.DATE);
        //拿到今天的时间
        //List<String> oneHourRedisKey = (List<String>) redisUtil.get(RedisKeyConstant.SIXTY_MINUTE_INTERVAL);
        //查询时间
        List<DateTime> dateTimeList = DateUtil.rangeToList(DateUtil.beginOfDay(new Date()), DateUtil.endOfDay(new Date()), DateField.MINUTE, 5);

        //List<String> oneHourRedisKey = (List<String>) redisService.get(RedisKeyConstant.FIVE_MINUTE_INTERVAL);
        //结果集
        List<RealtimeCurveRespVO> resList = new ArrayList<>();
        //将结果集转为24个值的集合
        for (int i = 0; i < 288; i++) {
            RealtimeCurveRespVO cur = new RealtimeCurveRespVO();
            cur.setDate(dateTimeList.get(i).toString(CommonConstant.DATE));
            cur.setRealtimePower(BigDecimal.ZERO);
            cur.setIrradiation(BigDecimal.ZERO);
            resList.add(cur);
        }

        //批量查询设备类型
        List<Integer> srcIdList = topologies.stream().map(s -> {
                    return s.getSrcId();
                }
        ).collect(Collectors.toList());
        List<ChargePileRespVO> chargePileRespVOS = deviceService.selectBySrcIds(stationId, srcIdList);
        log.info("topologies:size:" + topologies.size());
        //多个逆变器的采样值
        for (DeviceRespVO topology : topologies) {
            String deviceType = null;
            for (ChargePileRespVO chargePileRespVO : chargePileRespVOS) {
                if (topology.getSrcId().equals(chargePileRespVO.getSrcId())) {
                    deviceType = chargePileRespVO.getDeviceType();
                    break;
                }
            }
            //调用公共方法查询采集率的集合
            log.info("intervalList_1.start:" + System.currentTimeMillis());
            InverterCurveListVo data = intervalList(deviceType, station, topology, beginTime, endTime, "acActivePower", "60m");
            log.info("intervalList_2.start:" + System.currentTimeMillis());
            InverterCurveListVo yesterdayData = intervalList(deviceType, station, topology, yesterdayBeginTime, yesterdayEndTime, "acActivePower", "60m");
            log.info("intervalList_2.end:" + System.currentTimeMillis());
            //对返回的数据进行处理
            if (data.getStatistics() != null) {
                if (data.getStatistics().size() == 288 || yesterdayData.getStatistics().size() == 288) {
                    //每个结果集都是24个,需要把各个值累计到 resList 对应位置 ,是一对一关系
                    for (int i = 0; i < data.getStatistics().size(); i++) {
                        //把原来的值拿出来进行累加
                        BigDecimal realtimeCurve = resList.get(i).getRealtimePower();
                        if (data.getStatistics().get(i) != null) {
                            realtimeCurve = realtimeCurve.add(data.getStatistics().get(i).getDigital());
                        } else {
                            realtimeCurve = realtimeCurve.add(new BigDecimal(0));
                        }

                        //判断当前时间的数据和返回List中的时间进行对比，大于当前小时的数据set(0)
                        String substring = DateUtil.format(new Date(), CommonConstant.DATE_YMD_HMSS).substring(11, 13);
                        String date = resList.get(i).getDate().substring(11, 13);
                        int res = substring.compareTo(date);
                        //是否判断数据库入库的第一条数据的时间，时间之前赋0
                        if (data.getFirstTime() == null) {
                            resList.get(i).setRealtimePower(realtimeCurve);
                        } else {
                            Date firstTime = data.getFirstTime();
                            DateTime dateTime = dateTimeList.get(i);
                            boolean after = firstTime.after(dateTime);
                            if (res < CommonConstant.ZERO || after == true) {
                                resList.get(i).setRealtimePower(BigDecimal.ZERO);
                            } else {
                                //然后再放进去
                                resList.get(i).setRealtimePower(realtimeCurve);
                            }
                        }
                    }
                    for (int i = 0; i < yesterdayData.getStatistics().size(); i++) {
                        //把原来的值拿出来进行累加
                        BigDecimal irradiation = resList.get(i).getIrradiation();
                        if (yesterdayData.getStatistics().get(i) != null) {
                            irradiation = irradiation.add(yesterdayData.getStatistics().get(i).getDigital());
                        } else {
                            irradiation = irradiation.add(new BigDecimal(0));
                        }

                        //然后再放进去
                        resList.get(i).setIrradiation(irradiation);
                    }
                }
            }
        }

        for (RealtimeCurveRespVO realtimeCurveRespVO : resList) {
            String timeSubstring = realtimeCurveRespVO.getDate().substring(11, 16);
            realtimeCurveRespVO.setDate(timeSubstring);
        }
        return resList;
    }


    //某天的发电量,这个方法是通用方法, 如果传入的day来决定加工哪天数据
    @Override
    public List<PowerGenerateRespVO> powerGenerationCurrentDay(Integer stationId, List<DeviceRespVO> deviceRespVOS, Date day) {
        //如果没传day,那么使用昨天
        if (day == null) {
            day = DateUtil.offsetDay(new Date(), -1);
        }
        //当月第一天和昨天
        Date today = new Date();
        //今天的字符串
        String endDayTime = DateUtil.format(DateUtil.endOfDay(today), CommonConstant.DATE);
        String startDayTime = DateUtil.format(DateUtil.beginOfDay(today), CommonConstant.DATE);
        Station station = stationService.selectById(stationId);
        if (station == null) {
            return new ArrayList<>();
        }
        //查询mysql数据库
        List<PowerGenerateRespVO> list = new ArrayList<>();
        //拿到今天的时间
        List<String> oneHourRedisKey = (List<String>) redisUtil.get(RedisKeyConstant.SIXTY_MINUTE_INTERVAL);
        //将结果集转为24个值的集合
        for (int i = 0; i < 24; i++) {
            PowerGenerateRespVO powerGenerateRespVO = new PowerGenerateRespVO();
            powerGenerateRespVO.setDate(oneHourRedisKey.get(i));
            powerGenerateRespVO.setPowerGenerate(BigDecimal.ZERO);
            powerGenerateRespVO.setProfit(BigDecimal.ZERO);
            list.add(powerGenerateRespVO);
        }
        List<IncomeTotal> incomeTotals = incomeTotalService.getDayPower(station, null, startDayTime, endDayTime);
        if (incomeTotals.isEmpty()) {
            return new ArrayList<>();
        }
        //计算24小时收益
        for (PowerGenerateRespVO powerGenerateRespVO : list) {
            BigDecimal profit = BigDecimal.ZERO;
            BigDecimal powerGenerate = BigDecimal.ZERO;
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(DateUtil.parse(powerGenerateRespVO.getDate()));
            calendar.add(Calendar.HOUR_OF_DAY, 1);
            Date newDate = calendar.getTime();
            String newDateString = DateUtil.format(newDate, CommonConstant.DATE).substring(11, 16);
            String powerDate = powerGenerateRespVO.getDate().substring(11, 16);
            for (IncomeTotal incomeTotal : incomeTotals) {
                String date = incomeTotal.getDataDate().substring(11, 16);
                if (date.compareTo(powerDate) > 0 && date.compareTo(newDateString) <= 0) {
                    profit = profit.add(incomeTotal.getTotalFee());
                    powerGenerate = powerGenerate.add(new BigDecimal(incomeTotal.getEle()));
                }
            }
            powerGenerateRespVO.setDate(powerDate);
            powerGenerateRespVO.setProfit(profit);
            powerGenerateRespVO.setPowerGenerate(powerGenerate);
        }

        return list;
    }
    //某天的发电量,这个方法是通用方法, 如果传入的day来决定加工哪天数据
    /* @Override
    public List<PowerGenerateRespVO> powerGenerationCurrentDay(Integer stationId, List<Topology> topologies, Date day) {
        //如果没传day,那么使用昨天
        if (day == null) {
            day = DateUtil.offsetDay(new Date(), -1);
        }
        //计算这个day的前一天 23:00到这个day当晚的23:00的一共25个值
        Date today = day;
        String startDayTime = DateUtil.format(DateUtil.offsetDay(today, -1), CommonConstant.DATE_YMD) + " 23:00:00";
        String endDayTime = DateUtil.format(DateUtil.endOfDay(today), CommonConstant.DATE);
        Station station = stationService.selectById(stationId);
        if (station == null) {
            return new ArrayList<>();
        }
        //拿到24小时
        List<String> hour24List = BusiConstant.hour24List;
        //结果集
        List<PowerGenerateRespVO> resList = new ArrayList<>();
        //将结果集转为24个值的集合
        for (int i = 0; i < 24; i++) {
            PowerGenerateRespVO cur = new PowerGenerateRespVO();
            cur.setDate(hour24List.get(i));
            cur.setPowerGenerate(BigDecimal.ZERO);
            resList.add(cur);
        }
        //多个逆变器的采样值,对应时间点累加
        for (Topology topology : topologies) {
            //调用公共方法查询采集率的集合
            List<StatisticsRespVO> data = intervalList(null,station, topology, startDayTime, endDayTime,
                    "cumulativePowerGeneration", "60m");
            //包含昨天23:00的,一共25个值
            if (data.size() == 25) {
                //每个结果集都是25个,需要把各个值累计到 resList 对应位置 ,是一对一关系
                for (int i = 0; i < data.size() - 1; i++) {
                    //把原来的值拿出来进行累加
                    //定义一个变量 j = i+1, 这样i 和j对应的值相减即得到想要的差值
                    int j = i + 1;
                    //
                    BigDecimal before = data.get(i).getDigital();
                    BigDecimal now = data.get(j).getDigital();
                    BigDecimal current = now.subtract(before);
                    BigDecimal originalGenerate = resList.get(i).getPowerGenerate();
                    originalGenerate = originalGenerate.add(current).setScale(2, BigDecimal.ROUND_HALF_UP);
                    //然后再放进去
                    resList.get(i).setPowerGenerate(originalGenerate);
                }
            }
        }
        //拿到最新电价,并且把电价转换为map<时间, 电价>
        List<ElecPrice> elecPrices = elecPriceService.selectLatestPrices(station.getGroupId(), null, null, null);
        //将电价转为 key为 07:00 ,value 为电价的格式
        //没有电价, 就不相乘,直接返回原来的结果集
        if (elecPrices.isEmpty()) {
            return resList;
        }
        //时间只保留 HH:mm
        elecPrices = elecPrices.stream().map(elec -> {
            String time = elec.getStartTime().substring(11, 16);
            elec.setStartTime(time);
            return elec;
        }).collect(Collectors.toList());
        //转为电价map
        Map<String, ElecPrice> elecPriceMap = elecPrices.stream().collect(Collectors.toMap(ElecPrice::getStartTime, ElecPrice -> ElecPrice));
        for (PowerGenerateRespVO power : resList) {
            BigDecimal profit = BigDecimal.ZERO;
            if (elecPriceMap.containsKey(power.getDate())) {
                ElecPrice elecPrice = elecPriceMap.get(power.getDate());
                BigDecimal powerGenerate = power.getPowerGenerate();
                //利润 = 发电量 * 电价
                profit = powerGenerate.multiply(elecPrice.getPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
                power.setProfit(profit);
            }
        }
        return resList;
    }*/

    @Override
    public InverterCurveListVo intervalList(String deviceType, Station station, DeviceRespVO topology, String beginTime, String endTime,
                                            String colName, String interval) {
        //根据device_type和电站id查询device_type_config
        String modelName = null;
        List<DeviceTypeConfig> deviceTypeConfigs = deviceTypeConfigService.selectByType(deviceType, station.getId());
        for (DeviceTypeConfig deviceTypeConfig : deviceTypeConfigs) {
            modelName = deviceTypeConfig.getModelName();
        }
        //组表名
        TdBase tdAddBase = TdBase.builder()
                .groupId(station.getGroupId())
                .stationId(station.getId())
                .srcId(topology.getSrcId())
                .build();
        String tdStackSuffix = joinTbSuffixService.getTdInverterSuffix(tdAddBase);
        tdAddBase.setTableName(tdStackSuffix);
        tdAddBase.setBeginTime(beginTime);
        tdAddBase.setEndTime(endTime);
        tdAddBase.setDeviceType(deviceType);
        tdAddBase.setModelName(modelName);
        //查询逆变器的设备本身的字段名
        List<ModelDeviceColComp> acActivePowerList = modelDeviceService.getCompListByType("device", deviceType, colName);
        if (acActivePowerList.isEmpty() || acActivePowerList == null) {
            return new InverterCurveListVo();
        }
        ModelDeviceColComp acActivePowerDeviceCol = acActivePowerList.get(0);
        tdAddBase.setColName(acActivePowerDeviceCol.getDeviceCol());
        //循环调用
        long start = System.currentTimeMillis();
        log.info("tdFeignClient.queryInterval start:" + start);
        DataResult<InverterCurveListVo> listDataResult = tdFeignClient.queryInterval(tdAddBase);
        long end = System.currentTimeMillis();
        log.info("tdFeignClient.queryInterval end:" + end);
        log.info("tdFeignClient.queryInterval used:" + (end - start));
        //没查到数据就返回空集合
        if (!listDataResult.isSuccess() || listDataResult.getData() == null || listDataResult.getData().getStatistics() == null) {
            InverterCurveListVo inverterCurveListVo = new InverterCurveListVo();
            List<StatisticsRespVO> list = new ArrayList<>();
            //将结果集转为24个值的集合
            for (int i = 0; i < 288; i++) {
                StatisticsRespVO statisticsRespVO = new StatisticsRespVO();
                statisticsRespVO.setDigital(BigDecimal.ZERO);
                list.add(statisticsRespVO);
            }
            inverterCurveListVo.setStatistics(list);
            return inverterCurveListVo;
        } else if (CommonConstant.ONE.equals(listDataResult.getData().getStatistics().size())) {
            InverterCurveListVo inverterCurveListVo = new InverterCurveListVo();
            List<StatisticsRespVO> list = new ArrayList<>();
            //将结果集转为24个值的集合
            for (int i = 0; i < 288; i++) {
                StatisticsRespVO statisticsRespVO = new StatisticsRespVO();
                statisticsRespVO.setDigital(listDataResult.getData().getStatistics().get(0).getDigital());
                list.add(statisticsRespVO);
            }
            inverterCurveListVo.setStatistics(list);
            return inverterCurveListVo;
        }
        InverterCurveListVo data = listDataResult.getData();
        return data;
    }

    @Override
    public List<PowerGenerateRespVO> powerGeneration(Integer stationId, List<DeviceRespVO> deviceRespVOS, String queryType) {
        Station station = stationService.selectById(stationId);
        if (station == null) {
            return new ArrayList<>();
        }
        //结果集
        List<PowerGenerateRespVO> resList = new ArrayList<>();
        //月度和年度的都从冻结值表中取值
        //月的 ,计算当月第一天和昨天的
        if (CommonConstant.MONTH.equals(queryType)) {
            //当月第一天和昨天
            Date today = new Date();
            //今天的字符串
            String endDayTime = DateUtil.format(today, CommonConstant.DATE);
            //本月第一天 和昨天
            String startDayTime = DateUtil.format(DateUtil.beginOfMonth(today), CommonConstant.DATE);
            //查询mysql数据库
            List<IncomeTotal> incomeTotals = incomeTotalService.getDayPower(station, null, startDayTime, endDayTime);
            if (incomeTotals.isEmpty()) {
                return new ArrayList<>();
            }
            //去缓存中当月的天数
            List<String> dayList = (List<String>) redisService.get(RedisKeyConstant.ONE_DAY_INTERVAL);

            //将结果集转为24个值的集合
            for (int i = 0; i < dayList.size(); i++) {
                PowerGenerateRespVO powerGenerateRespVO = new PowerGenerateRespVO();
                powerGenerateRespVO.setDate(dayList.get(i) + CommonConstant.START_SUFFIX_TIMESTAMP);
                powerGenerateRespVO.setPowerGenerate(BigDecimal.ZERO);
                powerGenerateRespVO.setProfit(BigDecimal.ZERO);
                resList.add(powerGenerateRespVO);
            }
            for (PowerGenerateRespVO powerGenerateRespVO : resList) {
                BigDecimal profit = BigDecimal.ZERO;
                BigDecimal powerGenerate = BigDecimal.ZERO;
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(DateUtil.parse(powerGenerateRespVO.getDate()));
                calendar.add(Calendar.DATE, 1);//日
                Date newDate = calendar.getTime();
                String newDateString = DateUtil.format(newDate, CommonConstant.DATE);
                String powerDate = powerGenerateRespVO.getDate();
                for (IncomeTotal incomeTotal : incomeTotals) {
                    String dataDate = incomeTotal.getDataDate();
                    if (dataDate.compareTo(powerDate) > 0 && dataDate.compareTo(newDateString) <= 0) {
                        profit = profit.add(incomeTotal.getTotalFee());
                        powerGenerate = powerGenerate.add(new BigDecimal(incomeTotal.getEle()));
                    }
                }
                powerGenerateRespVO.setDate(powerDate.substring(5, 10));
                powerGenerateRespVO.setProfit(profit);
                powerGenerateRespVO.setPowerGenerate(powerGenerate);
            }
            return resList;
        }
        //年的,计算今年第一天到昨天的
        else if (CommonConstant.YEAR.equals(queryType)) {
            //今年第一天 昨天
            Date today = new Date();
            String startDayTime = DateUtil.format(DateUtil.beginOfYear(today), CommonConstant.DATE);
            String endDayTime = DateUtil.format(today, CommonConstant.DATE);

            //查询mysql数据库
            List<IncomeTotal> incomeTotals = incomeTotalService.getDayPower(station, null, startDayTime, endDayTime);
            if (incomeTotals.isEmpty()) {
                return new ArrayList<>();
            }
            //去缓存中当月的天数
            List<String> monthList = (List<String>) redisService.get(RedisKeyConstant.MONTH_INTERVAL);
            //将结果集转为24个值的集合
            for (int i = 0; i < monthList.size(); i++) {
                PowerGenerateRespVO powerGenerateRespVO = new PowerGenerateRespVO();
                String START = "-01 00:00:00";
                powerGenerateRespVO.setDate(monthList.get(i) + START);
                powerGenerateRespVO.setPowerGenerate(BigDecimal.ZERO);
                powerGenerateRespVO.setProfit(BigDecimal.ZERO);
                resList.add(powerGenerateRespVO);
            }
            for (PowerGenerateRespVO powerGenerateRespVO : resList) {
                BigDecimal profit = BigDecimal.ZERO;
                BigDecimal powerGenerate = BigDecimal.ZERO;
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(DateUtil.parse(powerGenerateRespVO.getDate()));
                calendar.add(Calendar.MONTH, 1);
                Date newDate = calendar.getTime();
                String newDateString = DateUtil.format(newDate, CommonConstant.DATE);
                String powerDate = powerGenerateRespVO.getDate();
                for (IncomeTotal incomeTotal : incomeTotals) {
                    String dataDate = incomeTotal.getDataDate();
                    if (dataDate.compareTo(powerDate) > 0 && dataDate.compareTo(newDateString) <= 0) {
                        profit = profit.add(incomeTotal.getTotalFee());
                        powerGenerate = powerGenerate.add(new BigDecimal(incomeTotal.getEle()));
                    }
                }
                powerGenerateRespVO.setDate(powerDate.substring(0, 7));
                powerGenerateRespVO.setProfit(profit);
                powerGenerateRespVO.setPowerGenerate(powerGenerate);
            }
        }
        return resList;
    }

    //分页查询逆变器列表
    @Override
    public List<InverterRespVO> inverterStatusList(StationReq queryVo) {
        //查电站地理位置
        Integer stationId = queryVo.getStationId();
        Station station = stationService.selectById(stationId);
        if (station == null) {
            return new ArrayList<>();
        }
        String address = station.getAddress();
        List<String> deviceTypeList = new ArrayList<>();
        deviceTypeList.add(DeviceTypeConstant.INVERTER_PREFIX);
    /*    deviceTypeList.add(DeviceTypeConstant.INVERTER_HUAWEI);
        deviceTypeList.add(DeviceTypeConstant.INVERTER_HW);
        deviceTypeList.add(DeviceTypeConstant.INVERTER_YG);*/
        //从设备表周工查逆变器列表
        DeviceReqVO deviceReqVO = new DeviceReqVO();
        deviceReqVO.setStationId(queryVo.getStationId());
        deviceReqVO.setDeviceType(DeviceTypeConstant.INVERTER_PREFIX);
        //todo 假设逆变器的总数不超过50个
        //deviceReqVO.setDeviceTypeList(deviceTypeList);
        List<DeviceRespVO> deviceList = deviceService.getListByInfo(deviceTypeList, deviceReqVO);
        //构造返回的集合
        List<InverterRespVO> inverterList = new ArrayList<>();
        //device表中有
        JSONObject deviceJson = null;
        for (DeviceRespVO device : deviceList) {
            String deviceAddress = "";
            String deviceModel = "";
            InverterRespVO inverter = new InverterRespVO();
            deviceJson = device.getDeviceJson();
            if (null != deviceJson) {
                deviceAddress = deviceJson.getString(DeviceTypeConstant.ADDRESS);
                deviceModel = deviceJson.getString(DeviceTypeConstant.DEVICE_MODEL);
            }
            deviceAddress = (null == deviceAddress ? "" : deviceAddress);
            inverter.setAddress(address + deviceAddress);
            inverter.setDeviceModel(deviceModel);
            inverter.setDeviceName(device.getDeviceName());
            inverter.setDeviceType(device.getDeviceType());
            inverter.setStationId(stationId);
            inverter.setSrcId(device.getSrcId());
            //todo deviceType可能需要修改
            //额定功率 交流实时功率 通讯状态 从缓存中取
            //先构造缓存key
            String key = device.getDeviceType() + ":" + stationId + ":" + device.getSrcId();
            if (redisService.hasKey(key)) {
                ModelNewInverter modelInverter = new ModelNewInverter();

                Map<Object, Object> inverterMap = redisService.hgetall(key);
                if (inverterMap != null) {
                    modelInverter = JSON.parseObject(JSON.toJSONString(inverterMap), ModelNewInverter.class);
                    BigDecimal ratedPower = BigDecimal.ZERO;
                    BigDecimal acActivePower = BigDecimal.ZERO;
                    BigDecimal dailyPowerGeneration = BigDecimal.ZERO;
                    if (modelInverter.getRatedPower() != null && modelInverter.getRatedPower().getValue() != null) {
                        ratedPower = modelInverter.getRatedPower().getValue();
                    }
                    if (modelInverter.getAcActivePower() != null && modelInverter.getAcActivePower().getValue() != null) {
                        acActivePower = modelInverter.getAcActivePower().getValue();
                    }
                    if (modelInverter.getDailyPowerGeneration() != null && modelInverter.getDailyPowerGeneration().getValue() != null) {
                        dailyPowerGeneration = modelInverter.getDailyPowerGeneration().getValue();
                    }
                    inverter.setRatedPower(ratedPower);
                    inverter.setAcActivePower(acActivePower);
                    inverter.setDailyPowerGeneration(dailyPowerGeneration);
                    //日等效小时 = 日发电量/站容量
                    BigDecimal stationCap = station.getCapacity();
                    BigDecimal dailyEquivalentHour = BigDecimal.ZERO;
                    if (stationCap != null && BigDecimal.ZERO.compareTo(stationCap) != 0) {
                        dailyEquivalentHour = dailyPowerGeneration.divide(stationCap, 2, BigDecimal.ROUND_HALF_UP);
                    }
                    inverter.setDailyEquivalentHour(dailyEquivalentHour);
//                    Integer communicationStatus = modelInverter.getCommunicationStatus();
//                    //通讯状态为0的时候直接判断故障
//                    if(CommonConstant.ZERO.equals(communicationStatus)){
//                        inverter.setCommunicationStatus(CommonConstant.ZERO);
//                    }else{
//                    boolean onLine = deviceService.isOnLine(device);
//                    if (onLine) {
//                        inverter.setCommunicationStatus(CommonConstant.ONE);
//                    } else {
//                        inverter.setCommunicationStatus(CommonConstant.ZERO);
//                    }
//                    Date updateTime = modelInverter.getUpdateTime();
//                    long between = DateUtil.between(updateTime, new Date(), DateUnit.MINUTE);
//                    //在线的设备更新时间和现在时间相差大于5分钟，则认为时离线
//                    if (between > minute) {
//                        inverter.setCommunicationStatus(CommonConstant.ZERO);
//                        inverter.setRunStatus(CommonConstant.THREE);
//                    } else {
//                        //在线的设备更新时间和现在时间相差小于5分钟，则按照特定字段值，取设备状态
//                        inverter.setCommunicationStatus(CommonConstant.ONE);
//                        inverter.setRunStatus(getRunStatus(device.getDeviceType(), modelInverter));
//                    }

                    boolean onLine = deviceService.isOnLine(device);
                    //在线的设备更新时间和现在时间相差大于5分钟，则认为时离线
                    if (!onLine) {
                        inverter.setCommunicationStatus(CommonConstant.ZERO);
                        inverter.setRunStatus(CommonConstant.THREE);
                    } else {
                        //在线的设备更新时间和现在时间相差小于5分钟，则按照特定字段值，取设备状态
                        inverter.setCommunicationStatus(CommonConstant.ONE);
                        inverter.setRunStatus(getRunStatus(device.getDeviceType(), modelInverter));
                    }
//                    }
//                    //在线的设备更新时间和现在时间相差大于5分钟，则认为时离线
//                    long updateTime = modelInverter.getUpdateTime().getTime();
//                    long newDate = System.currentTimeMillis();
//                    long min = (newDate - updateTime) / 60 / 1000;
//                    double ceil = Math.ceil((double) min);
//                    BigDecimal fiveMinutes = new BigDecimal(minute);
//                    int flag = new BigDecimal(ceil).compareTo(fiveMinutes);
//                    if (flag < CommonConstant.ONE) {
//                        inverter.setCommunicationStatus(CommonConstant.ONE);
//                    } else {
//                        inverter.setCommunicationStatus(CommonConstant.ZERO);
//                    }

                }
            } else {
                //缓存中没有值，直接离线
                inverter.setRunStatus(CommonConstant.THREE);
            }
            inverterList.add(inverter);
        }

        return inverterList;
    }

    /**
     * 获取光伏逆变器运行状态(默认返回运行)
     * 0停机 1并网运行 2故障停机
     *
     * @param deviceType
     * @param modelInverter
     * @return
     */
    private Integer getRunStatus(String deviceType, ModelNewInverter modelInverter) {
        Integer runStatus = CommonConstant.ZERO;
        if (DeviceTypeConstant.INVERTER_HW.equals(deviceType)) {
            if (modelInverter.getFaultShutdown() != null && BigDecimal.ONE.compareTo(modelInverter.getFaultShutdown().getValue()) == 0) {
                runStatus = CommonConstant.TWO;
            } else if (modelInverter.getInverterSwitchStatus() != null && BigDecimal.ZERO.compareTo(modelInverter.getInverterSwitchStatus().getValue()) == 0) {
                runStatus = CommonConstant.ZERO;
            } else if (modelInverter.getInverterSwitchStatus() != null && BigDecimal.ONE.compareTo(modelInverter.getInverterSwitchStatus().getValue()) == 0) {
                runStatus = CommonConstant.ONE;
            }
        } else if (DeviceTypeConstant.INVERTER_HUAWEI.equals(deviceType)) {
            if (modelInverter.getFaultOutage() != null && BigDecimal.ONE.compareTo(modelInverter.getFaultOutage().getValue()) == 0) {
                runStatus = CommonConstant.TWO;
            } else if (modelInverter.getShutdown() != null && BigDecimal.ONE.compareTo(modelInverter.getShutdown().getValue()) == 0) {
                runStatus = CommonConstant.ZERO;
            } else if (modelInverter.getGT() != null && BigDecimal.ONE.compareTo(modelInverter.getGT().getValue()) == 0) {
                runStatus = CommonConstant.ONE;
            }
        } else if (DeviceTypeConstant.INVERTER_YG.equals(deviceType)) {
            if (modelInverter.getDWSFaultShutDown() != null && BigDecimal.ONE.compareTo(modelInverter.getDWSFaultShutDown().getValue()) == 0) {
                runStatus = CommonConstant.TWO;
            } else if (modelInverter.getDWSShutDown() != null && BigDecimal.ONE.compareTo(modelInverter.getDWSShutDown().getValue()) == 0) {
                runStatus = CommonConstant.ZERO;
            } else if (modelInverter.getDWSWorking() != null && BigDecimal.ONE.compareTo(modelInverter.getDWSWorking().getValue()) == 0) {
                runStatus = CommonConstant.ONE;
            }
        } else if (DeviceTypeConstant.INVERTER_GDW.equals(deviceType)) {
            if (modelInverter.getCFaultMode() != null && BigDecimal.ONE.compareTo(modelInverter.getCFaultMode().getValue()) == 0) {
                runStatus = CommonConstant.TWO;
            } else if (modelInverter.getCNormalMode() != null && BigDecimal.ONE.compareTo(modelInverter.getCNormalMode().getValue()) == 0) {
                runStatus = CommonConstant.ONE;
            }
        }
        return runStatus;
    }
}
