package com.ho.business.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.Station;
import com.ho.business.entity.YcValue;
import com.ho.business.service.DeviceService;
import com.ho.business.service.LargeScreenService;
import com.ho.business.service.StationService;
import com.ho.business.service.YcValueService;
import com.ho.business.vo.DeviceTransfer;
import com.ho.business.vo.resp.DeviceRespVO;
import com.ho.business.vo.resp.cockpit.ConditionMonitoringRespVO;
import com.ho.business.vo.resp.cockpit.RevenueRespVO;
import com.ho.business.vo.resp.largescreen.GroupDataResp;
import com.ho.business.vo.resp.largescreen.MainDateResp;
import com.ho.business.vo.resp.largescreen.MonthlyStatisticResp;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.entity.SimpleUser;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.common.tools.service.RedisService;
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.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description 大屏展示实现类
 * Author yule
 * Date 2023/3/21 10:58
 */
@Service
public class LargeScreenServiceImpl implements LargeScreenService {

    @Autowired
    StationService stationService;

    @Autowired
    DeviceService deviceService;

    @Autowired
    RedisService redisService;

    @Autowired
    YcValueService ycValueService;

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

    @Value("${largeScreen.income}")
    BigDecimal income;


    /**
     * 获取集团数据
     *
     * @param user 登录用户(缓存信息)
     * @return
     */
    @Override
    public GroupDataResp getGroupData(SimpleUser user) {
        if (CommonConstant.ZERO.equals(user.getGroupId())) {
            throw new BusinessException(BaseResponseCode.COCKPIT_NOT_SEE);
        }
        //根据登录人集团查询集团下所有电站
        List<Station> stations = getStations(user);

        //创建返回对象
        GroupDataResp groupDataResp = new GroupDataResp();
        if (stations == null || stations.isEmpty()) {
            return groupDataResp;
        }
        //当前时间
        Date date = new Date();
        //装机容量
        BigDecimal capacity = BigDecimal.ZERO;
        //装机功率
        BigDecimal capacityPower = BigDecimal.ZERO;

        //遍历电站集合进行累加
        for (Station station : stations) {
            //装机容量进行累加
            BigDecimal capacityStation = station.getCapacity();
            if (capacityStation != null) {
                capacity = capacity.add(capacityStation);
            }
            //额定功率进行累加
            BigDecimal ratePower = station.getRatePower();
            if (ratePower != null) {
                capacityPower = capacityPower.add(ratePower);
            }
        }
        groupDataResp.setCapacity(capacity);
        groupDataResp.setCapacityPower(capacityPower);

        //查询到该集团下的所有设备
        List<DeviceRespVO> deviceRespVOS = deviceService.selectByGroup(user.getGroupId());
        //找出pcs设备
        deviceRespVOS = deviceRespVOS.stream().filter(s -> {
            return DeviceTypeConstant.PCS.equals(s.getDeviceType());
        }).collect(Collectors.toList());

        //累计充电与放电赋值
        setTotalPower(deviceRespVOS, groupDataResp);

        //年充电量、年放电量、当日充电量和当日放电量赋值
        setCapacity(stations, groupDataResp);
        //年综合效率 = 年储能放电量/年储能充电量
        BigDecimal yearProductiveness = BigDecimal.ZERO;
        yearProductiveness = !groupDataResp.getYearChargingCapacity().equals(BigDecimal.ZERO)
                ? groupDataResp.getYearDischargingCapacity().divide(groupDataResp.getYearChargingCapacity(), 4, BigDecimal.ROUND_HALF_UP)
                : yearProductiveness;
        groupDataResp.setYearProductiveness(yearProductiveness.multiply(new BigDecimal("100")));
        return groupDataResp;
    }

    /**
     * 获取站点检测数据
     *
     * @param user
     * @return
     */
    @Override
    public ConditionMonitoringRespVO getConditionMonitoring(SimpleUser user) {
        //分组id为0不能看驾驶舱
        if (CommonConstant.ZERO.equals(user.getGroupId())) {
            throw new BusinessException(BaseResponseCode.COCKPIT_NOT_SEE);
        }
        List<Station> stations = getStations(user);
        //创建返回值
        ConditionMonitoringRespVO vo = new ConditionMonitoringRespVO();
        if (stations == null || stations.isEmpty()) {
            return vo;
        }
        //获取到电站id集合
        List<Integer> stationIds = stations.stream().map(s -> {
            return s.getId();
        }).collect(Collectors.toList());

        //离线设备数
        Integer offlineDevice = 0;
        //查询集团下的全部设备
        List<DeviceRespVO> deviceRespVOS = deviceService.selectByGroup(user.getGroupId());
        for (DeviceRespVO deviceRespVO : deviceRespVOS) {
            String inverterRedisKey = deviceRespVO.getDeviceType() + ":" + deviceRespVO.getStationId() + ":" + deviceRespVO.getSrcId();
            if (redisService.hasKey(inverterRedisKey)) {
                Map<Object, Object> map = redisService.hgetall(inverterRedisKey);
                Date updateTime = (Date) map.get("updateTime");
                if (updateTime != null) {
                    long between = DateUtil.between(updateTime, new Date(), DateUnit.MINUTE);
                    //如果时间差值为5 ,则设备的离线个数+1
                    if (between > minute) {
                        offlineDevice++;
                    }
                }
            } else {
                offlineDevice++;
            }
        }
        vo.setTotalStation(stations.size());
        vo.setDeviceCount(deviceRespVOS.size());
        vo.setOfflineDevice(offlineDevice);
        //在线设备 = 设备总数 - 离线设备
        Integer onlineDevice = deviceRespVOS.size() - offlineDevice;
        vo.setOnlineDevice(onlineDevice);
        //设备在线率 = 在线设备 / 设备总数
        BigDecimal onlineDeviceRate = deviceRespVOS.size() != 0
                ? new BigDecimal(onlineDevice).divide(new BigDecimal(deviceRespVOS.size()), 2, BigDecimal.ROUND_HALF_UP)
                : BigDecimal.ZERO;
        vo.setOnlineDeviceRate(onlineDeviceRate.multiply(new BigDecimal("100")));
        return vo;
    }

    /**
     * 获取当年的每月充放电量统计图
     *
     * @param user
     * @return
     */
    @Override
    public List<MonthlyStatisticResp> getMonthlyStatistics(SimpleUser user) {
        //查询集团下的电站
        List<Station> stations = getStations(user);
        //创建当前日期
        Date date = new Date();
        String dateFormat = DateUtil.format(date, CommonConstant.DATE_YMD);
        List<YcValue> ycValueList = new ArrayList<>();
        for (Station station : stations) {
            //查询冻结值数据
            List<YcValue> ycValues = ycValueService.selectByType(station.getId(),
                    DateUtil.format(DateUtil.beginOfYear(date), CommonConstant.DATE_YMD)
                    , dateFormat);
            ycValueList.addAll(ycValues);
        }
        //根据月份进行分组
        Map<String, List<YcValue>> map = ycValueList.stream().map(s -> {
            //把时间切割当月
            s.setDay(s.getDay().substring(0, 7));
            return s;
        }).collect(Collectors.groupingBy(YcValue::getDay));
        //创建返回值集合
        List<MonthlyStatisticResp> list = new ArrayList<>();
        //遍历集合进行累加
        map.forEach((k, v) -> {
            MonthlyStatisticResp monthlyStatisticResp = new MonthlyStatisticResp();
            BigDecimal chargeDigital = BigDecimal.ZERO;
            BigDecimal disChargeDigital = BigDecimal.ZERO;
            monthlyStatisticResp.setDate(k);
            for (YcValue ycValue : v) {
                BigDecimal digital = ycValue.getDigital();
                if (CommonConstant.YC_VAULE_TYPE.CHARGE.equals(ycValue.getType())) {
                    chargeDigital = digital != null ? chargeDigital.add(digital) : chargeDigital;
                }
                if (CommonConstant.YC_VAULE_TYPE.DISCHARGE.equals(ycValue.getType())) {
                    disChargeDigital = digital != null ? disChargeDigital.add(digital) : disChargeDigital;
                }
            }
            monthlyStatisticResp.setChargeDigital(chargeDigital);
            monthlyStatisticResp.setDisChargeDigital(disChargeDigital);
            list.add(monthlyStatisticResp);
        });
        return list;
    }

    /**
     * 获取主要数据展示
     *
     * @param user 登录用户(缓存信息)
     * @return
     */
    @Override
    public MainDateResp getMainDate(SimpleUser user) {
        List<Station> stations = getStations(user);
        //找出最早的电站的创建时间
        Date createTime = null;
        for (Station station : stations) {
            Date stationCreateTime = station.getCreateTime();
            if (createTime == null) {
                createTime = stationCreateTime;
            } else {
                //比较两个时间大小(前 - 后)
                int compare = DateUtil.compare(createTime, stationCreateTime);
                if (compare > 0) {
                    createTime = stationCreateTime;
                }
            }
        }
        //安全运行天数(今天时间 - 创建时间)
        Long safeOperationDays = 0L;
        if (createTime == null) {
            safeOperationDays = 0L;
        } else {
            safeOperationDays = DateUtil.between(createTime, new Date(), DateUnit.DAY);
        }
        //创建返回值对象
        MainDateResp mainDateResp = new MainDateResp();
        mainDateResp.setSafeOperationDays(safeOperationDays.intValue());

        //查询到该集团下的所有设备
        List<DeviceRespVO> deviceRespVOS = deviceService.selectByGroup(user.getGroupId());
        //找出pcs设备
        deviceRespVOS = deviceRespVOS.stream().filter(s -> {
            return DeviceTypeConstant.PCS.equals(s.getDeviceType());
        }).collect(Collectors.toList());
        //查询累计放电量
        GroupDataResp groupDataResp = setTotalPower(deviceRespVOS, new GroupDataResp());
        if (groupDataResp.getTotalChargingCapacity() != null) {
            mainDateResp.setIncomeTotal(groupDataResp.getTotalDischargingCapacity().multiply(income));
        }
        return mainDateResp;
    }

    /**
     * 获取站年收益排行
     *
     * @param user 登录用户(缓存信息)
     * @return
     */
    @Override
    public List<RevenueRespVO> getYearIncomeRevenue(SimpleUser user) {
        //创建返回值集合
        List<RevenueRespVO> list = new ArrayList<>();
        //获取集团下的所有电站
        List<Station> stations = getStations(user);
        Date date = new Date();
        String dateFormat = DateUtil.format(date, CommonConstant.DATE_YMD);
        //创建一个冻结值的集合
        List<YcValue> ycValueList = new ArrayList<>();
        for (Station station : stations) {
            //查询冻结值数据
            List<YcValue> ycValues = ycValueService.selectByType(station.getId(),
                    DateUtil.format(DateUtil.beginOfYear(date), CommonConstant.DATE_YMD)
                    , dateFormat);
            ycValueList.addAll(ycValues);
        }
        //根据电站进行分组数据进行分组
        Map<Integer, List<YcValue>> map = ycValueList.stream().collect(Collectors.groupingBy(YcValue::getStationId));

        for (Station station : stations) {
            RevenueRespVO revenueRespVO = new RevenueRespVO();
            revenueRespVO.setStationName(station.getName());
            revenueRespVO.setStationId(station.getId());
            List<YcValue> ycValues = map.get(station.getId());
            BigDecimal totalDischargingCapacity = BigDecimal.ZERO;
            if (ycValues != null) {
                for (YcValue ycValue : ycValues) {
                    //判断是否为充电类型
                    if (CommonConstant.YC_VAULE_TYPE.DISCHARGE.equals(ycValue.getType())) {
                        totalDischargingCapacity = ycValue.getDigital() != null
                                ? totalDischargingCapacity.add(ycValue.getDigital())
                                : totalDischargingCapacity;
                    }
                }
            }
            revenueRespVO.setTotalProfit(totalDischargingCapacity.multiply(income).divide(new BigDecimal("10000"), 4, BigDecimal.ROUND_HALF_UP));
            list.add(revenueRespVO);
        }
        //根据收益排序
        list = list.stream().sorted((s1, s2) -> {
            BigDecimal totalProfit1 = s1.getTotalProfit();
            BigDecimal totalProfit2 = s2.getTotalProfit();
            return -totalProfit1.subtract(totalProfit2)
                    .multiply(new BigDecimal("100"))
                    .intValue();
        }).collect(Collectors.toList());
        return list;
    }

    /**
     * 通过登录人查询到集团下所有电站
     *
     * @param user
     * @return 集团下所有电站
     */
    private List<Station> getStations(SimpleUser user) {
        if (CommonConstant.ZERO.equals(user.getGroupId())) {
            throw new BusinessException(BaseResponseCode.COCKPIT_NOT_SEE);
        }
        //根据分组id查询到该集团所有电站
        List<Station> stations = stationService.selectByGroupId(user.getGroupId());
        return stations;
    }

    /**
     * 根据电站给年充电量和年放电量,日充和日放赋值
     *
     * @param stations 电站集合
     * @param resp     集团数据对象
     * @return
     */
    private GroupDataResp setCapacity(List<Station> stations, GroupDataResp resp) {
        Date date = new Date();
        String dateFormat = DateUtil.format(date, CommonConstant.DATE_YMD);
        //创建一个冻结值的集合
        List<YcValue> ycValueList = new ArrayList<>();
        for (Station station : stations) {
            //查询冻结值数据
            List<YcValue> ycValues = ycValueService.selectByType(station.getId(),
                    DateUtil.format(DateUtil.beginOfYear(date), CommonConstant.DATE_YMD)
                    , dateFormat);
            ycValueList.addAll(ycValues);
        }
        //对充电与放电数据进行分组
        Map<Integer, List<YcValue>> map = ycValueList.stream().collect(Collectors.groupingBy(YcValue::getType));

        //累加计算年储能充电量
        BigDecimal yearChargingCapacity = BigDecimal.ZERO;
        //当日储能充电量
        BigDecimal dailyChargingCapacity = BigDecimal.ZERO;
        List<YcValue> chargeList = map.get(CommonConstant.YC_VAULE_TYPE.CHARGE);
        if (chargeList != null) {
            for (YcValue ycValue : chargeList) {
                BigDecimal digital = ycValue.getDigital();
                yearChargingCapacity = digital != null ? yearChargingCapacity.add(digital) : yearChargingCapacity;
                if (ycValue.getDay() != null) {
                    if (dateFormat.equals(ycValue.getDay())) {
                        dailyChargingCapacity = digital != null ? dailyChargingCapacity.add(digital) : dailyChargingCapacity;
                    }
                }
            }
        }
        //年储能放电量
        BigDecimal yearDischargingCapacity = BigDecimal.ZERO;
        //当日储能放电量
        BigDecimal dailyDisChargingCapacity = BigDecimal.ZERO;
        List<YcValue> dischargeList = map.get(CommonConstant.YC_VAULE_TYPE.DISCHARGE);
        if (dischargeList != null) {
            for (YcValue ycValue : dischargeList) {
                BigDecimal digital = ycValue.getDigital();
                yearDischargingCapacity = digital != null ? yearDischargingCapacity.add(digital) : yearDischargingCapacity;
                if (ycValue.getDay() != null) {
                    if (dateFormat.equals(ycValue.getDay())) {
                        dailyDisChargingCapacity = digital != null ? dailyDisChargingCapacity.add(digital) : dailyDisChargingCapacity;
                    }
                }
            }
        }
        resp.setYearChargingCapacity(yearChargingCapacity);
        resp.setYearDischargingCapacity(yearDischargingCapacity);
        resp.setDailyChargingCapacity(dailyChargingCapacity);
        resp.setDailyDischargingCapacity(dailyDisChargingCapacity);
        return resp;
    }

    /**
     * 根据设备集合给累计充电与放电赋值
     *
     * @param deviceRespVOS 设备集合
     * @param groupDataResp 集团数据对象
     * @return
     */
    private GroupDataResp setTotalPower(List<DeviceRespVO> deviceRespVOS, GroupDataResp groupDataResp) {
        //累计充电量
        BigDecimal totalChargingCapacity = BigDecimal.ZERO;
        //累计放电量
        BigDecimal totalDischargingCapacity = BigDecimal.ZERO;
        //遍历计算累计充电量与放电量
        for (DeviceRespVO deviceRespVO : deviceRespVOS) {
            //拼接缓存key
            String redisKey = RedisKeyConstant.PCS + deviceRespVO.getStationId() + ":" + deviceRespVO.getSrcId();
            //判断缓存是否存在
            if (redisService.hasKey(redisKey)) {
                Map<Object, Object> dataMap = redisService.hgetall(redisKey);
                //获取PCS交流累计充电电量低
                BigDecimal pcsAcAccumulatedChargeLow = BigDecimal.ZERO;
                if (dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_CHARGE_LOW) != null) {
                    //pcsAcAccumulatedChargeLow = new BigDecimal((Integer) dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_CHARGE_LOW));
                    DeviceTransfer deviceTransfer = (DeviceTransfer)dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_CHARGE_LOW);
                    if(deviceTransfer!=null){
                        pcsAcAccumulatedChargeLow =deviceTransfer.getValue();
                    }

                }

                //获取PCS交流累计充电电量高
                BigDecimal pcsAcAccumulatedChargeHigh = BigDecimal.ZERO;
                if (dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_CHARGE_HIGH) != null) {
                    //pcsAcAccumulatedChargeHigh = new BigDecimal((Integer) dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_CHARGE_HIGH));
                    DeviceTransfer deviceTransfer = (DeviceTransfer)dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_CHARGE_HIGH);
                    if(deviceTransfer!=null){
                        pcsAcAccumulatedChargeHigh =deviceTransfer.getValue();
                    }
                }
                //获取PCS交流累计放电电量低
                BigDecimal pcsAcAccumulatedDischargeLow = BigDecimal.ZERO;
                if (dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_DISCHARGE_LOW) != null) {
                    //pcsAcAccumulatedDischargeLow = new BigDecimal((Integer) dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_DISCHARGE_LOW));
                    DeviceTransfer deviceTransfer = (DeviceTransfer)dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_DISCHARGE_LOW);
                    if(deviceTransfer!=null){
                        pcsAcAccumulatedDischargeLow =deviceTransfer.getValue();
                    }
                }
                //获取PCS交流累计放电电量高
                BigDecimal pcsAcAccumulatedDischargeHign = BigDecimal.ZERO;
                if (dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_DISCHARGE_HIGN) != null) {
                    //pcsAcAccumulatedDischargeHign = new BigDecimal((Integer) dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_DISCHARGE_HIGN));
                    DeviceTransfer deviceTransfer = (DeviceTransfer)dataMap.get(DeviceTypeConstant.PCS_DEVICE_TYPE.PCS_AC_ACCUMULATED_DISCHARGE_HIGN);
                    if(deviceTransfer!=null){
                        pcsAcAccumulatedDischargeHign =deviceTransfer.getValue();
                    }
                }
                //累计充电量 = 获取PCS交流累计充电电量低 + 获取PCS交流累计充电电量高
                totalChargingCapacity = pcsAcAccumulatedChargeLow != null ? totalChargingCapacity.add(pcsAcAccumulatedChargeLow) : totalChargingCapacity;
                totalChargingCapacity = pcsAcAccumulatedChargeHigh != null ? totalChargingCapacity.add(pcsAcAccumulatedChargeHigh) : totalChargingCapacity;
                //累计放电量 = 获取PCS交流累计放电电量低 + 获取PCS交流累计放电电量高
                totalDischargingCapacity = pcsAcAccumulatedDischargeLow != null ? totalDischargingCapacity.add(pcsAcAccumulatedDischargeLow) : totalDischargingCapacity;
                totalDischargingCapacity = pcsAcAccumulatedDischargeHign != null ? totalDischargingCapacity.add(pcsAcAccumulatedDischargeHign) : totalDischargingCapacity;
            }
        }
        groupDataResp.setTotalChargingCapacity(totalChargingCapacity);
        groupDataResp.setTotalDischargingCapacity(totalDischargingCapacity);
        return groupDataResp;
    }
}
