package com.njcn.harmonic.service.impl;

import com.njcn.common.config.GeneralInfo;
import com.njcn.device.api.GeneralDeviceInfoClient;
import com.njcn.device.api.LineFeignClient;
import com.njcn.device.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pojo.dto.PollutionLineDTO;
import com.njcn.device.pojo.dto.PollutionParamDTO;
import com.njcn.device.pojo.dto.PollutionSubstationDTO;
import com.njcn.harmonic.constant.Param;
import com.njcn.harmonic.pojo.dto.PublicDTO;
import com.njcn.harmonic.pojo.param.HarmonicPublicParam;
import com.njcn.harmonic.pojo.vo.PollutionVO;
import com.njcn.harmonic.service.IPollutionService;
import com.njcn.influxdb.utils.InfluxDbUtils;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.web.utils.RequestUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.influxdb.dto.QueryResult;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

/**
 * 类的介绍：
 *
 * @author xuyang
 * @version 1.0.0
 * @createTime 2022/2/21 16:43
 */
@Service
@AllArgsConstructor
public class PollutionServiceImpl implements IPollutionService {

    private final GeneralDeviceInfoClient generalDeviceInfoClient;

    private final InfluxDbUtils influxDbUtils;

    private final GeneralInfo generalInfo;

    private final LineFeignClient lineFeignClient;

    @Override
    public List<PollutionVO> getDeptSubstationRelations(HarmonicPublicParam harmonicPublicParam) {
        harmonicPublicParam.setServerName(generalInfo.getMicroServiceName());
        List<PollutionVO> list = new ArrayList<>();
        List<String> lineList = new ArrayList<>();
        List<PollutionLineDTO> lineInfo = new ArrayList<>();
        PollutionParamDTO paramDTO = new PollutionParamDTO();
        if (StringUtils.isBlank(RequestUtil.getDeptIndex())){
            return list;
        }
        List<GeneralDeviceDTO> deviceList = generalDeviceInfoClient.getPracticalRunDeviceInfo(harmonicPublicParam).getData();
        deviceList.forEach(dept->{
            lineList.addAll(dept.getLineIndexes());
        });
        if (!CollectionUtils.isEmpty(lineList)){
            paramDTO.setLineList(lineList);
            lineInfo = lineFeignClient.getLineInfo(paramDTO).getData();
            List<PublicDTO> lineData = getLineDate(lineList,harmonicPublicParam.getSearchBeginTime(),harmonicPublicParam.getSearchEndTime(),harmonicPublicParam.getStatisticalType().getCode());
            if (!CollectionUtils.isEmpty(lineData)){
                lineInfo.stream().map(list1->lineData.stream().filter(list2-> Objects.equals(list1.getId(),list2.getId())).findAny().map(m->{
                    list1.setData(m.getData());
                    return list1;
                })).collect(Collectors.toList());
            }
        }
        Map<String,List<PollutionLineDTO>> map = lineInfo.stream().collect(Collectors.groupingBy(PollutionLineDTO::getSubstationId));
        deviceList.forEach(dept->{
            List<PollutionVO> childrenList = new ArrayList<>();
            PollutionVO pollutionVO = new PollutionVO();
            pollutionVO.setId(dept.getIndex());
            pollutionVO.setName(dept.getName());
            if (!CollectionUtils.isEmpty(dept.getSubIndexes())){
                dept.getSubIndexes().forEach(sub->{
                    List<PollutionLineDTO> l1 = map.get(sub);
                    PollutionVO children = new PollutionVO();
                    children.setId(sub);
                    children.setPid(dept.getIndex());
                    children.setName(l1.get(0).getSubstation());
                    children.setData(l1.stream().max(Comparator.comparing(PollutionLineDTO::getData)).get().getData());
                    childrenList.add(children);
                });
            }
            if (!CollectionUtils.isEmpty(childrenList)){
                pollutionVO.setChildren(childrenList.stream().sorted(Comparator.comparing(PollutionVO::getData).reversed()).collect(Collectors.toList()));
                pollutionVO.setData(childrenList.stream().max(Comparator.comparing(PollutionVO::getData)).get().getData());
            }
            list.add(pollutionVO);
        });
        if (!CollectionUtils.isEmpty(list)){
            return list.stream().sorted(Comparator.comparing(PollutionVO::getData).reversed().thenComparing(PollutionVO::getName)).collect(Collectors.toList());
        }
        return list;
    }

    @Override
    public List<PollutionSubstationDTO> getSubstationInfoById(HarmonicPublicParam deptParam) {
        deptParam.setServerName(generalInfo.getMicroServiceName());
        List<PollutionSubstationDTO> list = new ArrayList<>();
        List<GeneralDeviceDTO> sub = generalDeviceInfoClient.getPracticalRunDeviceInfoAsSubstation(deptParam).getData();
        sub.forEach(item->{
            PollutionSubstationDTO pollutionSubstationDTO = lineFeignClient.getSubstationInfo(item.getIndex()).getData();
            if (!CollectionUtils.isEmpty(item.getLineIndexes())){
                List<PublicDTO> lineData = getLineDate(item.getLineIndexes(),deptParam.getSearchBeginTime(),deptParam.getSearchEndTime(),deptParam.getStatisticalType().getCode());
                if (!CollectionUtils.isEmpty(lineData)){
                    pollutionSubstationDTO.setData(lineData.stream().max(Comparator.comparing(PublicDTO::getData)).get().getData());
                }
            }
            list.add(pollutionSubstationDTO);
        });
        if (!CollectionUtils.isEmpty(list)){
            return list.stream().sorted(Comparator.comparing(PollutionSubstationDTO::getData).reversed().thenComparing(PollutionSubstationDTO::getName)).collect(Collectors.toList());
        }
        return list;
    }

    @Override
    public List<PollutionLineDTO> getLineInfoById(HarmonicPublicParam harmonicPublicParam) {
        harmonicPublicParam.setServerName(generalInfo.getMicroServiceName());
        List<PollutionLineDTO> list = new ArrayList<>();
        List<String> line = new ArrayList<>();
        PollutionParamDTO paramDTO = new PollutionParamDTO();
        if (StringUtils.isBlank(RequestUtil.getDeptIndex())){
            return list;
        }
        List<GeneralDeviceDTO> sub = generalDeviceInfoClient.getPracticalRunDeviceInfoAsSubstation(harmonicPublicParam).getData();
        sub.forEach(item->{
            if (Objects.equals(harmonicPublicParam.getId(),item.getIndex())){
                if (!CollectionUtils.isEmpty(item.getLineIndexes())){
                    line.addAll(item.getLineIndexes());
                }
            }
        });
        if (!CollectionUtils.isEmpty(line)){
            paramDTO.setLineList(line);
            list = lineFeignClient.getLineInfo(paramDTO).getData();
            List<PublicDTO> lineData = getLineDate(line, harmonicPublicParam.getSearchBeginTime(), harmonicPublicParam.getSearchEndTime(), harmonicPublicParam.getStatisticalType().getCode());
            if (!CollectionUtils.isEmpty(lineData)){
                list.stream().map(list1->lineData.stream().filter(list2-> Objects.equals(list1.getId(),list2.getId())).findAny().map(m->{
                    list1.setData(m.getData());
                    return list1;
                })).collect(Collectors.toList());
            }
        } else {
            return list;
        }
        return list.stream().sorted(Comparator.comparing(PollutionLineDTO::getData).reversed().thenComparing(PollutionLineDTO::getName)).collect(Collectors.toList());
    }

    @Override
    public List<PollutionLineDTO> getLineRank(HarmonicPublicParam harmonicPublicParam) {
        harmonicPublicParam.setServerName(generalInfo.getMicroServiceName());
        List<PollutionLineDTO> list = new ArrayList<>();
        List<String> lineList = new ArrayList<>();
        PollutionParamDTO paramDTO = new PollutionParamDTO();
        if (StringUtils.isBlank(RequestUtil.getDeptIndex())){
            return list;
        }
        List<GeneralDeviceDTO> deviceList = generalDeviceInfoClient.getPracticalRunDeviceInfo(harmonicPublicParam).getData();
        deviceList.forEach(item->{
            if (!CollectionUtils.isEmpty(item.getLineIndexes())){
                lineList.addAll(item.getLineIndexes());
            }
        });
        if (!CollectionUtils.isEmpty(lineList)){
            paramDTO.setLineList(lineList);
            list = lineFeignClient.getLineInfo(paramDTO).getData();
            List<PublicDTO> result = getLineDate(lineList, harmonicPublicParam.getSearchBeginTime(), harmonicPublicParam.getSearchEndTime(), harmonicPublicParam.getStatisticalType().getCode());
            if (!CollectionUtils.isEmpty(result)){
                list.stream().map(list1->result.stream().filter(list2-> Objects.equals(list1.getId(),list2.getId())).findAny().map(m->{
                    list1.setData(m.getData());
                    return list1;
                })).collect(Collectors.toList());
            }
        }
        list.sort((item1,item2)->item2.getData().compareTo(item1.getData()));
        if (list.size() > Param.UP_LIMIT){
            return list.subList(Param.DOWN_LIMIT,Param.UP_LIMIT);
        }
        return list;
    }


    /**
     * 功能描述:根据监测点id查询influxDB污染指数
     * @param line        监测点集合
     *        startTime   开始时间
     *        endTime     结束时间
     *        type        指标参数
     * @return
     * @author xy
     * @date 2022/2/21 20:08
     */
    private List<PublicDTO> getLineDate(List<String> line, String startTime, String endTime, String type){
        List<PublicDTO> result = new ArrayList<>();
        String quota = "";
        if (Objects.equals(type, DicDataEnum.XBDY_ENUM.getCode())){
            quota = "harmonic_v";
        } else if (Objects.equals(type, DicDataEnum.XBDL_ENUM.getCode())){
            quota = "harmonic_i";
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(Param.TIME).append(" >= '").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<line.size();i++){
            if (line.size() - i != 1){
                stringBuilder.append(Param.LINE_ID).append("='").append(line.get(i)).append("' or ");
            } else {
                stringBuilder.append(Param.LINE_ID).append("='").append(line.get(i)).append("')");
            }
        }
        stringBuilder.append(" group by line_id order by time desc limit 1 tz('Asia/Shanghai')");
        String sql = "SELECT line_id,"+quota+" FROM harmonic_pollution where " + stringBuilder;
        QueryResult sqlResult = influxDbUtils.query(sql);
        List<QueryResult.Series> list = sqlResult.getResults().get(0).getSeries();
        if (!CollectionUtils.isEmpty(list)){
            list.forEach(po->{
                String index = po.getTags().get(Param.LINE_ID);
                List<List<Object>> valueList = po.getValues();
                if (!CollectionUtils.isEmpty(valueList)){
                    for (List<Object> value : valueList) {
                        PublicDTO publicDTO = new PublicDTO();
                        Double data = value.get(2) == null ? 0.0 : BigDecimal.valueOf(Double.parseDouble(value.get(2).toString())).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        publicDTO.setId(index);
                        publicDTO.setData(data);
                        result.add(publicDTO);
                    }
                }
            });
        }
        return result;
    }
}
