package com.njcn.harmonic.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.njcn.common.config.GeneralInfo;
import com.njcn.device.api.GeneralDeviceInfoClient;
import com.njcn.device.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pojo.param.DeviceInfoParam;
import com.njcn.harmonic.constant.Param;
import com.njcn.harmonic.mapper.OnlineRateDataMapper;
import com.njcn.harmonic.pojo.dto.PublicDTO;
import com.njcn.harmonic.pojo.vo.OnlineRateCensusVO;
import com.njcn.harmonic.pojo.vo.OnlineRateVO;
import com.njcn.harmonic.service.OnlineRateDataService;
import com.njcn.influxdb.utils.InfluxDbUtils;
import lombok.AllArgsConstructor;
import org.influxdb.dto.QueryResult;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

/**
 * 类的介绍：
 *
 * @author xuyang
 * @version 1.0.0
 * @createTime 2021/12/31 9:50
 */
@Service
@AllArgsConstructor
public class OnlineRateDataServiceImpl implements OnlineRateDataService {

    private final OnlineRateDataMapper onlineRateDataMapper;

    private final InfluxDbUtils influxDbUtils;

    private final GeneralDeviceInfoClient generalDeviceInfoClient;

    private final GeneralInfo generalInfo;

    @Override
    public List<OnlineRateVO> getOnlineRateData(DeviceInfoParam.BusinessParam onlineRateParam) {
        List<OnlineRateVO> onlineRateList = new ArrayList<>();

        //按照条件获取运行终端综合信息
        List<GeneralDeviceDTO> deviceDTOList = generalDeviceInfoClient.getPracticalRunDeviceInfo(new DeviceInfoParam(onlineRateParam.getStatisticalType(), onlineRateParam.getDeptIndex(), generalInfo.getMicroServiceName(), null, onlineRateParam.getManufacturer(), null)).getData();
        if (!CollectionUtils.isEmpty(deviceDTOList)){
            for (GeneralDeviceDTO generalDeviceDTO : deviceDTOList) {
                if (CollectionUtils.isEmpty(generalDeviceDTO.getDeviceIndexes())){
                    continue;
                }
                OnlineRateVO onlineRateVO = new OnlineRateVO();
                onlineRateVO.setId(generalDeviceDTO.getIndex());
                onlineRateVO.setName(generalDeviceDTO.getName());
                List<String> deviceIndexes = generalDeviceDTO.getDeviceIndexes();
                //查找在线率
                List<PublicDTO> condition = getCondition(deviceIndexes, onlineRateParam.getSearchBeginTime(), onlineRateParam.getSearchEndTime());
                onlineRateVO.setOnlineRateData(condition.stream().mapToDouble(PublicDTO::getData).average().orElse(3.14159));
                //组装表格树
                List<OnlineRateVO> treeList = getTreeData(deviceIndexes, onlineRateParam);
                onlineRateVO.setChildren(treeList);
                onlineRateList.add(onlineRateVO);
            }
        }

        return onlineRateList;
    }

    @Override
    public OnlineRateCensusVO getOnlineRateDataCensus(DeviceInfoParam.CompareBusinessParam onlineRateCensusParam) {
        OnlineRateCensusVO onlineRateCensusVO = new OnlineRateCensusVO();
        onlineRateCensusParam.setServerName(generalInfo.getMicroServiceName());
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceInfoClient.getPracticalRunDeviceInfo(onlineRateCensusParam).getData();
        List<String> type = new ArrayList<>();
        List<Double> single = new ArrayList<>(), ratio = new ArrayList<>();
        if (!CollectionUtils.isEmpty(generalDeviceDTOList)) {
            for (GeneralDeviceDTO generalDeviceDTO: generalDeviceDTOList){
                List<String> deviceIndexes = generalDeviceDTO.getDeviceIndexes();
                if (CollectionUtils.isEmpty(deviceIndexes)) {
                    continue;
                }
                type.add(generalDeviceDTO.getName());
                //根据终端索引集查询在线率
                List<PublicDTO> onlineRateList = getCondition(deviceIndexes, onlineRateCensusParam.getSearchBeginTime(), onlineRateCensusParam.getSearchEndTime());
                single.add(onlineRateList.stream().mapToDouble(PublicDTO::getData).average().orElse(3.14159));
                //如果存在需要比较的时间，再获取对应数据
                if(StrUtil.isNotBlank(onlineRateCensusParam.getPeriodBeginTime()) && StrUtil.isNotBlank(onlineRateCensusParam.getPeriodEndTime())){
                    List<PublicDTO> compareData = getCondition(deviceIndexes, onlineRateCensusParam.getPeriodBeginTime(), onlineRateCensusParam.getPeriodEndTime());
                    ratio.add(compareData.stream().mapToDouble(PublicDTO::getData).average().orElse(3.14159));
                }
            }
        }
        onlineRateCensusVO.setType(type);
        onlineRateCensusVO.setSingle(single);
        onlineRateCensusVO.setRatio(ratio);

        // List<OnlineRateVO> list = new ArrayList<>();
        // List<OnlineRateVO> periodList = new ArrayList<>();
        // OnlineRateCensusVO onlineRateCensusVO = new OnlineRateCensusVO();
        // OnlineRateParam onlineRateParam = new OnlineRateParam();
        // BeanUtil.copyProperties(onlineRateCensusParam,onlineRateParam);
        // List<String> type = new ArrayList<>();
        // List<Double> single = new ArrayList<>();
        // List<Double> ratio = new ArrayList<>();
        // if (Objects.equals(onlineRateCensusParam.getStatisticalType(),0)){
        //     list = getOnlineRateData(onlineRateParam).get(0).getChildren();
        // } else {
        //     list = getOnlineRateData(onlineRateParam);
        // }
        // if (!CollectionUtils.isEmpty(list)){
        //     list.forEach(onlineRateVO -> {
        //         type.add(onlineRateVO.getName());
        //         single.add(onlineRateVO.getOnlineRateData());
        //         onlineRateCensusVO.setType(type);
        //         onlineRateCensusVO.setSingle(single);
        //     });
        // }
        // if (StringUtils.isNotBlank(onlineRateCensusParam.getPeriodBeginTime()) &&
        //         StringUtils.isNotBlank(onlineRateCensusParam.getPeriodEndTime())){
        //     onlineRateParam.setSearchBeginTime(onlineRateCensusParam.getPeriodBeginTime());
        //     onlineRateParam.setSearchEndTime(onlineRateCensusParam.getPeriodEndTime());
        //     if (Objects.equals(onlineRateCensusParam.getStatisticalType(),0)){
        //         periodList = getOnlineRateData(onlineRateParam).get(0).getChildren();
        //     } else {
        //         periodList = getOnlineRateData(onlineRateParam);
        //     }
        //     if (!CollectionUtils.isEmpty(periodList)) {
        //         periodList.forEach(onlineRateVO -> {
        //             ratio.add(onlineRateVO.getOnlineRateData());
        //             onlineRateCensusVO.setRatio(ratio);
        //         });
        //     }
        // }
        return onlineRateCensusVO;
    }

    /**
     * 获取每层树数据
     */
    public List<OnlineRateVO> getTreeData(List<String> deviceIndexes, DeviceInfoParam.BusinessParam onlineRateParam) {
        //终端集合
        List<OnlineRateVO> deviceList = onlineRateDataMapper.getOnlineRateData(deviceIndexes);
        //变电站集合
        List<OnlineRateVO> substationList = onlineRateDataMapper.getLineInfoByList(deviceList.stream().map(OnlineRateVO::getPid).distinct().collect(Collectors.toList()));
        //供电公司集合
        List<OnlineRateVO> powerCompanyList = onlineRateDataMapper.getLineInfoByList(substationList.stream().map(OnlineRateVO::getPid).distinct().collect(Collectors.toList()));

        //查询终端的在线率
        List<PublicDTO> onlineRateList = getCondition(deviceIndexes, onlineRateParam.getSearchBeginTime(), onlineRateParam.getSearchEndTime());
        //根据终端集合组装终端的在线率
        if (!CollectionUtils.isEmpty(deviceList)) {
            deviceList.stream().map(list1 -> onlineRateList.stream().filter(list2 -> Objects.equals(list1.getId(), list2.getId())).findAny().map(m -> {
                list1.setOnlineRateData(m.getData());
                return list1;
            })).collect(Collectors.toList());
        }
        substationList.stream().peek(item -> item.setChildren(getChildCategoryList(item, deviceList))).collect(Collectors.toList());
        powerCompanyList.stream().peek(item -> item.setChildren(getChildCategoryList(item, substationList))).collect(Collectors.toList());
        setFatherOnlineRate(substationList);
        setFatherOnlineRate(powerCompanyList);
        return powerCompanyList;
    }

    /**
     * 组装树
     */
    private List<OnlineRateVO> getChildCategoryList(OnlineRateVO item, List<OnlineRateVO> all) {
        return all.stream().filter(allItem -> allItem.getPid().equals(item.getId())).collect(Collectors.toList());
    }

    /**
     * influxDB相关操作
     * 查询终端的在线率
     * 前端要求: 返回百分比数据
     */
    private List<PublicDTO> getCondition(List<String> deviceIndexes, String startTime, String endTime) {
        List<PublicDTO> publicDTOList = new ArrayList<>();
        //组装sql语句
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(Param.TIME + " >= '").append(startTime).append(Param.START_TIME).append("' and ").append(Param.TIME).append(" <= '").append(endTime).append(Param.END_TIME).append("' and (");
        for (int i = 0; i < deviceIndexes.size(); i++) {
            if (deviceIndexes.size() - i != 1) {
                stringBuilder.append(Param.DEV_INDEX + "='").append(deviceIndexes.get(i)).append("' or ");
            } else {
                stringBuilder.append(Param.DEV_INDEX + "='").append(deviceIndexes.get(i)).append("')");
            }
        }
        //sql语句
        String sql = "SELECT (SUM(" + Param.ONLINEMIN + ")/(SUM(" + Param.OFFLINEMIN + ")+SUM(" + Param.ONLINEMIN + ")))*100 AS onlineRate FROM pqs_onlinerate WHERE " + stringBuilder + " group by " + Param.DEV_INDEX;
        //结果集
        QueryResult result = influxDbUtils.query(sql);
        //处理结果集
        List<QueryResult.Series> list = result.getResults().get(0).getSeries();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(po -> {
                PublicDTO publicDTO = new PublicDTO();
                List<List<Object>> valueList = po.getValues();
                String index = po.getTags().get(Param.DEV_INDEX);
                if (!CollectionUtils.isEmpty(valueList)) {
                    for (List<Object> value : valueList) {
                        //终端在线率 保留两位小数
                        Double onlineRate = value.get(1) == null ? null : BigDecimal.valueOf(Double.parseDouble(value.get(1).toString())).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        publicDTO.setId(index);
                        publicDTO.setData(onlineRate);
                    }
                }
                publicDTOList.add(publicDTO);
            });
        }
        return publicDTOList;
    }

    /**
     * 父级组装
     */
    private void setFatherData(Map<String, List<String>> map, List<OnlineRateVO> list, DeviceInfoParam.BusinessParam onlineRateParam) {
        for (String key : map.keySet()) {
            if (!CollectionUtils.isEmpty(map.get(key))) {
                List<OnlineRateVO> onlineRateVOList = getTreeData(map.get(key), onlineRateParam);
                //拼接父级
                OnlineRateVO onlineRateVO = new OnlineRateVO();
                onlineRateVO.setId("0");
                onlineRateVO.setName(key);
                onlineRateVO.setLevel(0);
                if (CollectionUtil.isNotEmpty(onlineRateVOList)) {
                    onlineRateVO.setChildren(onlineRateVOList);
                }
                list.add(onlineRateVO);
                setTopOnlineRate(list);
            }
        }
    }


    /**
     * 计算父级终端在线率
     */
    private void setFatherOnlineRate(List<OnlineRateVO> list) {
        list.forEach(item -> {
            List<OnlineRateVO> children = item.getChildren();
            List<OnlineRateVO> tempList = children.stream().filter(s -> !Objects.equals(s.getOnlineRateData(), 3.14159)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(tempList)) {
                item.setOnlineRateData(tempList.stream().mapToDouble(OnlineRateVO::getOnlineRateData).sum() / children.size());
            } else {
                item.setOnlineRateData(3.14159);
            }
        });
    }

    //变电站
    private void setSubstationIntegrity(List<OnlineRateVO> list) {
        list.forEach(item -> {
            List<OnlineRateVO> children = item.getChildren();
            List<OnlineRateVO> result = new ArrayList<>(children);
            double aver = result.stream().mapToDouble(OnlineRateVO::getOnlineRateData).average().orElseThrow(IllegalStateException::new);
            item.setOnlineRateData(BigDecimal.valueOf(aver).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        });
    }

    //供电公司
    private void setPowerCompanyIntegrity(List<OnlineRateVO> list) {
        list.forEach(item -> {
            List<OnlineRateVO> result = new ArrayList<>();
            List<OnlineRateVO> children = item.getChildren();
            children.forEach(item2 -> {
                List<OnlineRateVO> children2 = item2.getChildren();
                result.addAll(children2);
            });
            double aver = result.stream().mapToDouble(OnlineRateVO::getOnlineRateData).average().orElseThrow(IllegalStateException::new);
            item.setOnlineRateData(BigDecimal.valueOf(aver).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        });
    }

    //省级
    private void setAreaIntegrity(List<OnlineRateVO> list) {
        list.forEach(item -> {
            List<OnlineRateVO> result = new ArrayList<>();
            List<OnlineRateVO> children = item.getChildren();
            children.forEach(item2 -> {
                List<OnlineRateVO> children2 = item2.getChildren();
                children2.forEach(item3 -> {
                    List<OnlineRateVO> children3 = item3.getChildren();
                    result.addAll(children3);
                });
            });
            double aver = result.stream().mapToDouble(OnlineRateVO::getOnlineRateData).average().orElseThrow(IllegalStateException::new);
            item.setOnlineRateData(BigDecimal.valueOf(aver).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        });
    }

    private void setTopOnlineRate(List<OnlineRateVO> list) {
        list.forEach(item -> {
            List<OnlineRateVO> result = new ArrayList<>();
            List<OnlineRateVO> children = item.getChildren();
            children.forEach(item2 -> {
                List<OnlineRateVO> children2 = item2.getChildren();
                children2.forEach(item3 -> {
                    List<OnlineRateVO> children3 = item3.getChildren();
                    children3.forEach(item4 -> {
                        List<OnlineRateVO> children4 = item4.getChildren();
                        result.addAll(children4);
                    });
                });
            });
            double aver = result.stream().mapToDouble(OnlineRateVO::getOnlineRateData).average().orElseThrow(IllegalStateException::new);
            item.setOnlineRateData(BigDecimal.valueOf(aver).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        });
    }


}
