package com.njcn.harmonic.service.impl;

import com.njcn.common.config.GeneralInfo;
import com.njcn.device.api.GeneralDeviceInfoClient;
import com.njcn.device.enums.LineBaseEnum;
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.THDistortionMapper;
import com.njcn.harmonic.pojo.dto.PublicDTO;
import com.njcn.harmonic.pojo.vo.THDistortionCensusVO;
import com.njcn.harmonic.pojo.vo.THDistortionVO;
import com.njcn.harmonic.service.THDistortionService;
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: chenchao
 * @date: 2022/03/11 10:09
 * @Description: <描述>
 */
@Service
@AllArgsConstructor
public class THDistortionServiceImpl implements THDistortionService {

    private final GeneralInfo generalInfo;

    private final GeneralDeviceInfoClient generalDeviceInfoClient;

    private final THDistortionMapper thDistortionMapper;

    private final InfluxDbUtils influxDbUtils;

    @Override
    public List<THDistortionVO> getTHDistortionData(DeviceInfoParam.BusinessParam thDistortionParam) {
        List<THDistortionVO> thDistortionVOS = new ArrayList<>();
        List<String> lineList = new ArrayList<>();

        //按照条件获取实际运行终端综合信息
        List<GeneralDeviceDTO> deviceList = generalDeviceInfoClient.getPracticalRunDeviceInfo(new DeviceInfoParam(thDistortionParam.getStatisticalType(), thDistortionParam.getDeptIndex(), generalInfo.getMicroServiceName(), thDistortionParam.getScale(), thDistortionParam.getManufacturer(), thDistortionParam.getLoadType())).getData();
        //组装监测点Top层集合
        for (GeneralDeviceDTO generalDeviceDTO : deviceList) {
            if (CollectionUtils.isEmpty(generalDeviceDTO.getDeviceIndexes())) {
                continue;
            }
            THDistortionVO thDistortionVO = new THDistortionVO();
            thDistortionVO.setId(generalDeviceDTO.getIndex());
            thDistortionVO.setName(generalDeviceDTO.getName());
            if (!CollectionUtils.isEmpty(generalDeviceDTO.getLineIndexes())){
                List<String> lineIndexes = generalDeviceDTO.getLineIndexes();
                List<THDistortionVO> monitorList = thDistortionMapper.getLineData(lineIndexes);
                // setLineData(monitorList,thDistortionVO);
                //查找畸变率
                List<PublicDTO> condition = getCondition(lineIndexes, thDistortionParam.getSearchBeginTime(), thDistortionParam.getSearchEndTime());
                thDistortionVO.setDistortion(condition.stream().mapToDouble(PublicDTO::getData).average().orElse(3.14159));
                //组装父级数据树
                List<THDistortionVO> treeList = getTreeData(lineIndexes, thDistortionParam);
                thDistortionVO.setChildren(treeList);
            }
            thDistortionVOS.add(thDistortionVO);
        }

        return thDistortionVOS;
    }

    @Override
    public THDistortionCensusVO getTHDistortionCensus(DeviceInfoParam.BusinessParam thDistortionCensusParam) {
        THDistortionCensusVO distortionCensusVO = new THDistortionCensusVO();
        thDistortionCensusParam.setServerName(generalInfo.getMicroServiceName());
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceInfoClient.getPracticalRunDeviceInfo(thDistortionCensusParam).getData();
        List<String> type = new ArrayList<>();
        List<Double> single = new ArrayList<>();
        if (!CollectionUtils.isEmpty(generalDeviceDTOList)) {
            for (GeneralDeviceDTO generalDeviceDTO : generalDeviceDTOList) {
                List<String> lineIndexes = generalDeviceDTO.getLineIndexes();
                if (CollectionUtils.isEmpty(lineIndexes)) {
                    continue;
                }
                type.add(generalDeviceDTO.getName());
                List<PublicDTO> condition = getCondition(lineIndexes, thDistortionCensusParam.getSearchBeginTime(), thDistortionCensusParam.getSearchEndTime());
                single.add(condition.stream().mapToDouble(PublicDTO::getData).average().orElse(3.14159));
            }
            distortionCensusVO.setType(type);
            distortionCensusVO.setSingle(single);
        }
        return distortionCensusVO;
    }


    /**
     * 计算父级畸变率
     */
    private void setFatherDistortion(List<THDistortionVO> list) {
        list.forEach(thDistortionVO -> {
            List<THDistortionVO> children = thDistortionVO.getChildren();
            List<THDistortionVO> tempList = children.stream().filter(child -> !Objects.equals(child.getDistortion(), 3.14159)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(tempList)) {
                thDistortionVO.setDistortion(tempList.stream().mapToDouble(THDistortionVO::getDistortion).average().orElse(3.14159));
            } else {
                thDistortionVO.setDistortion(3.14159);
            }
        });
    }

    /**
     * 组装树层级
     */
    private List<THDistortionVO> getChildCategoryList(THDistortionVO item, List<THDistortionVO> child) {
        return child.stream().filter(allItem -> allItem.getPid().equals(item.getId())).collect(Collectors.toList());
    }
    private void setChildesList(List<THDistortionVO> item, List<THDistortionVO> childes) {
        //groupLine变电站索引和监测点集合
        Map<String, List<THDistortionVO>> groupLine;
        groupLine = childes.stream().collect(Collectors.groupingBy(thDistortionVO -> {
            String[] pid = thDistortionVO.getPidS().split(",");
            return pid[LineBaseEnum.SUB_LEVEL.getCode()];
        }));
        item.stream().peek(thDistortionVO -> {
            if (!CollectionUtils.isEmpty(groupLine.get(thDistortionVO.getId()))) {
                thDistortionVO.setChildren(groupLine.get(thDistortionVO.getId()));
            }
        }).collect(Collectors.toList());
    }

    /**
     * 获取父级每层数据
     */
    private List<THDistortionVO> getTreeData(List<String> lineIndexes, DeviceInfoParam.BusinessParam thDistortionParam) {
        //监测点集合
        List<THDistortionVO> monitorList = thDistortionMapper.getLineData(lineIndexes);
        //母线集合
        List<THDistortionVO> busBarList = thDistortionMapper.getLineInfoByList(monitorList.stream().map(THDistortionVO::getPid).distinct().collect(Collectors.toList()));
        //终端集合
        List<THDistortionVO> deviceList = thDistortionMapper.getLineInfoByList(busBarList.stream().map(THDistortionVO::getPid).distinct().collect(Collectors.toList()));
        //变电站集合
        List<THDistortionVO> substationList = thDistortionMapper.getLineInfoByList(deviceList.stream().map(THDistortionVO::getPid).distinct().collect(Collectors.toList()));
        //供电公司集合
        List<THDistortionVO> powerCompanyList = thDistortionMapper.getLineInfoByList(substationList.stream().map(THDistortionVO::getPid).distinct().collect(Collectors.toList()));

        //查询监测点谐波畸变率
        List<PublicDTO> condition = getCondition(lineIndexes, thDistortionParam.getSearchBeginTime(), thDistortionParam.getSearchEndTime());
        if (!CollectionUtils.isEmpty(monitorList)) {
            //根据监测点集合组装谐波畸变率
            monitorList.stream().map(list1 -> condition.stream().filter(list2 -> Objects.equals(list1.getId(), list2.getId())).findAny().map(m -> {
                list1.setDistortion(m.getData());
                return list1;
            })).collect(Collectors.toList());

            // busBarList.stream().peek(item -> item.setChildren(getChildCategoryList(item, monitorList))).collect(Collectors.toList());
            // deviceList.stream().peek(item -> item.setChildren(getChildCategoryList(item, busBarList))).collect(Collectors.toList());
            // substationList.stream().peek(item -> item.setChildren(getChildesList(item, monitorList))).collect(Collectors.toList());
            setChildesList(substationList,monitorList);
            setFatherDistortion(substationList);
            powerCompanyList.stream().peek(item -> item.setChildren(getChildCategoryList(item, substationList))).collect(Collectors.toList());
            setFatherDistortion(powerCompanyList);

        }
        return powerCompanyList;
    }


    /**
     * influxDB查询畸变率
     * @param lineIndexes
     * @param startTime
     * @param endTime
     */
    private List<PublicDTO> getCondition(List<String> lineIndexes, String startTime, String endTime) {
        List<PublicDTO> publicDTOList = new ArrayList<>();
        //组装sql语句
        StringBuilder string = new StringBuilder();
        string.append(Param.QualityFlag + "='1' and (" + Param.PHASIC_TYPE + "='" + Param.PHASIC_TYPEA + "' or " + Param.PHASIC_TYPE + "='" + Param.PHASIC_TYPEB + "' or " + Param.PHASIC_TYPE + "='" + Param.PHASIC_TYPEC + "') and "+ Param.VALUETYPE + "='AVG' and ");
        StringBuilder timeId = new StringBuilder();
        timeId.append(Param.TIME + " >= '" + startTime + Param.START_TIME + "' and " + Param.TIME + " <= '" + endTime + Param.END_TIME + "' and (");
        for (int i = 0; i < lineIndexes.size(); i++) {
            if (lineIndexes.size() - i != 1) {
                timeId.append(Param.LINE_ID + "='").append(lineIndexes.get(i)).append("' or ");
            } else {
                timeId.append(Param.LINE_ID + "='").append(lineIndexes.get(i)).append("')");
            }
        }
        // String a = "SELECT MEAN(V_THD) AS distortion FROM Data_V WHERE QualityFlag='1' and (phasic_type='A' or phasic_type='B' or phasic_type='C')and value_type='AVG' and time >= '2022-03-20 00:00:00' and time <= '2022-03-21 23:59:59' and  (lineid ='1e3b8531483b2a8cbee6747f1f641cf9') group by lineid;";
        //sql语句
        String sql = "SELECT MEAN(" + Param.V_THD + ")*100 AS distortion FROM Data_V WHERE " + string + timeId + " group by " + Param.LINE_ID;
        //结果集
        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.LINE_ID);
                if (!CollectionUtils.isEmpty(valueList)){
                    for (List<Object> value : valueList) {
                        //谐波畸变率 保留两位小数
                        Double distortion = 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(distortion);
                    }
                }
                publicDTOList.add(publicDTO);
            });
        }
        return publicDTOList;
    }


}
