package com.ho.business.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.Device;
import com.ho.business.entity.ElecMeterValue;
import com.ho.business.entity.Station;
import com.ho.business.feignclient.TdFeignClient;
import com.ho.business.service.*;
import com.ho.business.vo.DeviceTransfer;
import com.ho.business.vo.req.carbin.ElecMeterReq;
import com.ho.business.vo.resp.DeviceColData;
import com.ho.business.vo.resp.DeviceRespVO;
import com.ho.business.vo.resp.cabin.ChargeDischarge;
import com.ho.business.vo.resp.cabin.LeftPanel;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.entity.PointCurveSrcCol;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.DateNewUtil;
import com.ho.common.tools.vo.req.PointData;
import com.ho.datacollect.api.constant.DataCollectConstant;
import com.ho.td.api.entity.query.TdBaseTimeQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @author fancl
 * @desc: 舱的实现类
 * @date 2023/5/5
 */
@Service
@Slf4j
public class CabinServiceImpl implements CabinService {

    @Autowired
    DeviceService deviceService;

    @Autowired
    ElecMeterValueService elecMeterValueService;

    @Autowired
    ModelDeviceService modelDeviceService;

    @Autowired
    RedisService redisService;

    @Autowired
    StationHomeService stationHomeService;

    @Autowired
    StationService stationService;

    @Autowired
    TdFeignClient feignClient;

    @Override
    public LeftPanel dealDevice(Integer stationId, Integer srcId) {
        //
        return null;
    }

    //几个发电量
    @Override
    public LeftPanel powerGeneration(Integer stationId, Integer srcId) {
        LeftPanel leftPanel = new LeftPanel();
        //根据设备pid查询下面的BMS
        //当日的可以从缓存直接取,月度,年度有定时任务跑数据,但截至时间只到昨天, 所以再加上当日的数据,即为总数据
        //查这个设备下的BMS
        List<DeviceRespVO> bmsList = deviceService.getListByDeviceTypeAndPid(stationId, srcId, DeviceTypeConstant.BMS);
        //只有一个
        if (!bmsList.isEmpty()) {
            DeviceRespVO deviceRespVO = bmsList.get(0);
            //查这个设备的缓存数据
            String key = deviceRespVO.getDeviceType() + ":" + stationId + ":" + deviceRespVO.getSrcId();
            if (redisService.hasKey(key)) {
                //日充,日放,得从映射字段取值 ,不要直接取值
                //日充
                /*List<ModelDeviceColComp> dayChargeType = modelDeviceService.getCompListByType("device", deviceRespVO.getDeviceType(), "dailyCharge");
                if(!dayChargeType.isEmpty()){
                    ModelDeviceColComp comp = dayChargeType.get(0);
                    String deviceCol = comp.getDeviceCol();
                    DeviceTransfer transfer =(DeviceTransfer) redisService.hget(key, deviceCol);
                    if(transfer!=null){
                        BigDecimal value = transfer.getValue();
                        leftPanel.setDayCharge(value);
                    }
                }
                //日放
                List<ModelDeviceColComp> dayDischargeType = modelDeviceService.getCompListByType("device", deviceRespVO.getDeviceType(), "dailyDischarge");
                if(!dayDischargeType.isEmpty()){
                    ModelDeviceColComp comp = dayDischargeType.get(0);
                    String deviceCol = comp.getDeviceCol();
                    DeviceTransfer transfer =(DeviceTransfer) redisService.hget(key, deviceCol);
                    if(transfer!=null){
                        BigDecimal value = transfer.getValue();
                        leftPanel.setDayDischarge(value);
                    }
                }*/
                //查6个值 ,日充, 日放, 月充, 月放, 年充, 年放
                //都从缓存中拿
                DeviceTransfer dayChargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.DAY_CHARGE);
                DeviceTransfer dayDischargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.DAY_DISCHARGE);
                DeviceTransfer monthChargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.MONTH_CHARGE);
                DeviceTransfer monthDischargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.MONTH_DISCHARGE);

                //DeviceTransfer yearChargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.YEAR_CHARGE);
                ///DeviceTransfer yearDischargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.YEAR_DISCHARGE);
                //年充,年放 先保持和累计值相同
                DeviceTransfer yearChargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.TOTAL_CHARGE);
                DeviceTransfer yearDischargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.TOTAL_DISCHARGE);
                //累计充,累计放
                DeviceTransfer totalChargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.TOTAL_CHARGE);
                DeviceTransfer totalDischargeTransfer = (DeviceTransfer) redisService.hget(key, RedisKeyConstant.BMS_DEVICE.TOTAL_DISCHARGE);
                if (dayChargeTransfer != null) {
                    leftPanel.setDayCharge(dayChargeTransfer.getValue());
                }
                if (dayDischargeTransfer != null) {
                    leftPanel.setDayDischarge(dayDischargeTransfer.getValue());
                }
                if (monthChargeTransfer != null) {
                    leftPanel.setMonthCharge(monthChargeTransfer.getValue());
                }
                //月放= 缓存里的月放 + 当日
                if (monthDischargeTransfer != null) {
                    leftPanel.setMonthDischarge(monthDischargeTransfer.getValue());
                }
                //这两个值先取和累计充,累计放一样
                if (yearChargeTransfer != null) {
                    leftPanel.setYearCharge(yearChargeTransfer.getValue());
                }
                if (yearDischargeTransfer != null) {

                    leftPanel.setYearDischarge(yearDischargeTransfer.getValue());
                }
                if (totalChargeTransfer != null) {
                    leftPanel.setTotalCharge(totalChargeTransfer.getValue());
                }
                if (totalDischargeTransfer != null) {
                    leftPanel.setTaotalDischarge(totalDischargeTransfer.getValue());
                }
            }
        }
        return leftPanel;
    }

    @Override
    public List<ChargeDischarge> getChargeList(Integer stationId, Integer srcId, String beginTime, String endTime) {
        Device device = deviceService.selectByStationIdAndSrcId(stationId, srcId);
        List<ChargeDischarge> list = new ArrayList<>();
        if (device == null) {
            log.error("设备为空");
            return list;
        }
        List<ChargeDischarge> discharges = new ArrayList<>(512);
        log.info("device srcId:" + device.getSrcId());
        //根据设备pid查询下面的BMS
        List<DeviceRespVO> bmsList = deviceService.getListByDeviceTypeAndPid(stationId, device.getSrcId(), DeviceTypeConstant.BMS);
        //从elec_meter_value取值
        //正常只有一个bms,先取一个,后面再循环
        if (!bmsList.isEmpty()) {
            DeviceRespVO bmsDevice = bmsList.get(0);
            Integer bmsSrcId = bmsDevice.getSrcId();
            //分别查询充电量放电量
            ElecMeterReq elecMeterReq = new ElecMeterReq();
            elecMeterReq.setStationId(stationId);
            elecMeterReq.setSrcId(bmsSrcId);
            elecMeterReq.setType(8);
            elecMeterReq.setBeginTime(beginTime);
            elecMeterReq.setEndTime(endTime);
            //充电量
            List<ElecMeterValue> chargeList = elecMeterValueService.selectListByStationAndSrcId(elecMeterReq);
            Map<String, List<ElecMeterValue>> chargeMap = chargeList.stream().collect(Collectors.groupingBy(ElecMeterValue::getDay));

            elecMeterReq = new ElecMeterReq();
            elecMeterReq.setStationId(stationId);
            elecMeterReq.setSrcId(bmsSrcId);
            elecMeterReq.setType(9);
            elecMeterReq.setBeginTime(beginTime);
            elecMeterReq.setEndTime(endTime);
            List<ElecMeterValue> disChargeList = elecMeterValueService.selectListByStationAndSrcId(elecMeterReq);
            //9
            Map<String, List<ElecMeterValue>> disChargeMap = disChargeList.stream().collect(Collectors.groupingBy(ElecMeterValue::getDay));

            List<String> betweenDates = DateNewUtil.getBetweenDates(beginTime, endTime,true);
            //遍历这个数组,如果map 中有这个日期的, 把值弄过来
            for (String betweenDate : betweenDates) {
                ChargeDischarge target = new ChargeDischarge();
                target.setDate(betweenDate);
                if (chargeMap.containsKey(betweenDate)) {
                    List<ElecMeterValue> charList = chargeMap.get(betweenDate);
                    BigDecimal big = BigDecimal.ZERO;
                    //合计
                    for (ElecMeterValue elecMeterValue : charList) {
                        BigDecimal digital = elecMeterValue.getDigital() == null ? BigDecimal.ZERO : elecMeterValue.getDigital();
                        big = big.add(digital);
                    }
                    //保留精度
                    target.setCharge(big);
                }
                //放电
                if (disChargeMap.containsKey(betweenDate)) {
                    List<ElecMeterValue> disCharList = disChargeMap.get(betweenDate);
                    //合计
                    BigDecimal big = BigDecimal.ZERO;
                    for (ElecMeterValue elecMeterValue : disCharList) {
                        BigDecimal digital = elecMeterValue.getDigital() == null ? BigDecimal.ZERO : elecMeterValue.getDigital();
                        big = big.add(digital);
                    }
                    target.setDisCharge(big);
                }
                discharges.add(target);
            }
        }

        //日充/放电量
        BigDecimal chargePower = BigDecimal.ZERO;
        BigDecimal dischargePower = BigDecimal.ZERO;
        //遍历计算累计值
        for (DeviceRespVO deviceRespVO : bmsList) {
            //拼接rediskey
            String redisKey = deviceRespVO.getDeviceType() + ":" + deviceRespVO.getStationId() + ":" + deviceRespVO.getSrcId();
            if (redisService.hasKey(redisKey)) {
                //获取缓存中的值
                DeviceTransfer chargeDeviceTransfer = (DeviceTransfer) redisService.hget(redisKey,DataCollectConstant.BMS_POINT.dailyCharge);
                DeviceTransfer dischargeDeviceTransfer = (DeviceTransfer) redisService.hget(redisKey,DataCollectConstant.BMS_POINT.dailyDischarge);

                chargePower = chargeDeviceTransfer == null ? chargePower : chargeDeviceTransfer.getValue().add(chargePower);
                dischargePower = dischargeDeviceTransfer == null ? dischargePower : dischargeDeviceTransfer.getValue().add(dischargePower);
            }
        }

        //给当日的充放电量赋值
        ChargeDischarge chargeDischarge = discharges.get(discharges.size() - 1);
        BigDecimal chargePowerBig = chargePower;
        if (chargePowerBig != null) {
            String result = String.format("%.3f", chargePowerBig);
            chargePowerBig = new BigDecimal(result);
        }
        BigDecimal disChargePowerBig = dischargePower;
        if (disChargePowerBig != null) {
            String result = String.format("%.3f", disChargePowerBig);
            disChargePowerBig = new BigDecimal(result);
        }
        chargeDischarge.setCharge(chargePowerBig);
        chargeDischarge.setDisCharge(disChargePowerBig);
        //移除集合中当日的对象,在进行添加
        discharges.remove(discharges.size() - 1);
        discharges.add(chargeDischarge);
        return discharges;
    }


    @Override
    public List<PointData> getAuxPower(Integer stationId, Integer srcId) {
        //查电站
        Station station = stationService.selectById(stationId);
        List<PointData> retlist = new ArrayList<>();
        if (station == null) {
            return retlist;
        }
        Date now = new Date();
        String endTime = DateUtil.format(now, CommonConstant.DATE);
        DateTime beginDateTime = DateUtil.offsetDay(now, -1);
        String beginTime = DateUtil.format(beginDateTime, CommonConstant.DATE);
        List<DateTime> dateTimeList = DateUtil.rangeToList(beginDateTime, new Date(), DateField.MINUTE, 5);
        //查设备下的电表
        //根据电站id和srcId查询 拿到col的部分数据
        //查间隔下的电表
        List<DeviceRespVO> elecMeterList = deviceService.getListByDeviceTypeAndPid(stationId, srcId, DeviceTypeConstant.ELE_METER);
        List<PointData> reList = new ArrayList<>();
        if (elecMeterList.isEmpty()) {
            for (int i = 0; i < dateTimeList.size(); i++) {
                PointData pointData = new PointData();
                DateTime dateTime = dateTimeList.get(i);
                String format = DateUtil.format(dateTime, CommonConstant.DATE);
                pointData.setDate(format);
                pointData.setDigital(null);
                reList.add(pointData);
            }
            return retlist;
        }
        DeviceRespVO deviceRespVO1 = elecMeterList.get(0);
        //Device device = deviceService.selectByStationIdAndSrcId(stationId, srcId);
        List<DeviceRespVO> list = new ArrayList<>();
        DeviceRespVO deviceRespVO = new DeviceRespVO();
        deviceRespVO.setSrcId(deviceRespVO1.getSrcId());
        deviceRespVO.setDeviceType(deviceRespVO1.getDeviceType());
        deviceRespVO.setStationId(deviceRespVO1.getStationId());
        list.add(deviceRespVO);
        //查询devicecol数据（总有功（映射字段是outputPower）, 总无功(PCS交流母线总无功功率  YC0034  映射字段是reactivePowerPCS)）
        DeviceColData outputPowerData = stationHomeService.getDeviceColData(list, DeviceTypeConstant.ACTIVE_POWER);
        //直接组查询超级表的入参
        TdBaseTimeQuery tdBaseQuery = new TdBaseTimeQuery();
        tdBaseQuery.setBeginTime(beginTime);
        tdBaseQuery.setEndTime(endTime);
        tdBaseQuery.setMap(outputPowerData.getMap());
        tdBaseQuery.setTime("5m");
        if (outputPowerData != null || !outputPowerData.getDeviceIdList().isEmpty()) {
            List<PointCurveSrcCol> deviceIdList = outputPowerData.getDeviceIdList();
            tdBaseQuery.setSrcId(deviceIdList.get(0).getSrcId());
            if (deviceIdList != null || !deviceIdList.isEmpty()) {
                List<String> cols = deviceIdList.get(0).getCols();
                if (!cols.isEmpty()) {
                    tdBaseQuery.setCol(cols.get(0));
                }
            }
        }

        tdBaseQuery.setStationId(stationId);
        tdBaseQuery.setGroupId(station.getGroupId());
        //数据查询
        DataResult<List<PointData>> pscData = feignClient.getPointData(tdBaseQuery);
        if (pscData.isSuccess() && !pscData.getData().isEmpty()) {
            List<PointData> data = pscData.getData();

            for (int i = 0; i < dateTimeList.size(); i++) {
                PointData pointData = new PointData();
                DateTime dateTime = dateTimeList.get(i);
                String format = DateUtil.format(dateTime, CommonConstant.DATE);
                pointData.setDate(format);
                if (data.get(i) != null) {
                    Double digital = data.get(i).getDigital();
                    pointData.setDigital(digital);
                }
                reList.add(pointData);
            }
        } else {
            for (int i = 0; i < dateTimeList.size(); i++) {
                PointData pointData = new PointData();
                DateTime dateTime = dateTimeList.get(i);
                String format = DateUtil.format(dateTime, CommonConstant.DATE);
                pointData.setDate(format);
                pointData.setDigital(null);
                reList.add(pointData);
            }
        }
        return reList;
    }
}
