package com.njcn.csharmonic.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.njcn.access.api.CsLineLatestDataFeignClient;
import com.njcn.access.pojo.po.CsLineLatestData;
import com.njcn.csdevice.api.*;
import com.njcn.csdevice.param.IcdBzParam;
import com.njcn.csdevice.pojo.dto.DevDetailDTO;
import com.njcn.csdevice.pojo.po.CsEquipmentDeliveryPO;
import com.njcn.csdevice.pojo.po.CsLinePO;
import com.njcn.csdevice.pojo.po.RStatIntegrityD;
import com.njcn.csdevice.pojo.po.RStatOnlineRateD;
import com.njcn.csharmonic.pojo.param.StatisticsDataParam;
import com.njcn.csharmonic.pojo.vo.DataVo;
import com.njcn.csharmonic.pojo.vo.HalfMonthReportVO;
import com.njcn.csharmonic.service.IStatisticsDataDataService;
import com.njcn.influx.pojo.dto.StatisticalDataDTO;
import com.njcn.influx.service.CommonService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author xy
 */
@Service
@RequiredArgsConstructor
public class StatisticsDataDataServiceImpl implements IStatisticsDataDataService {

    private final EquipmentFeignClient equipmentFeignClient;
    private final CsLineFeignClient csLineFeignClient;
    private final CommonService commonService;
    private final IntegrityFeignClient integrityFeignClient;
    private final OnlineRateFeignClient onlineRateFeignClient;
    private final CsLineLatestDataFeignClient csLineLatestDataFeignClient;
    private final CsLedgerFeignClient csLedgerFeignClient;

    @Override
    public List<DataVo> getLineIntegrity(StatisticsDataParam param) {
        List<DataVo> result = new ArrayList<>();
        //获取库中正常的所有装置
        List<CsEquipmentDeliveryPO> devList = equipmentFeignClient.getAll().getData();
        if (CollectionUtil.isNotEmpty(devList)) {
            Map<String, CsEquipmentDeliveryPO> devMap = devList.stream().collect(Collectors.toMap(CsEquipmentDeliveryPO::getId, Function.identity()));
            //获取所有监测点
            List<String> devIdList = devList.stream().map(CsEquipmentDeliveryPO::getId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(devIdList)) {
                List<CsLinePO> csLinePOList = csLineFeignClient.getLinesByDevList(devIdList).getData();
                csLinePOList.forEach(item->{
                    //应收数据
                    int dueCount = 1440 / item.getLineInterval();
                    DataVo vo = new DataVo();
                    StatisticalDataDTO statisticalDataDTO;
                    Integer process = devMap.get(item.getDeviceId()).getProcess();
                    //治理监测点
                    if (item.getClDid() == 0) {
                        statisticalDataDTO = commonService.getCounts(item.getLineId(),"apf_data","Apf_Freq","frequency","T","AVG",item.getClDid().toString(),process.toString(),param.getStartTime(),param.getEndTime());
                    }
                    //电能质量监测点
                    else {
                        statisticalDataDTO = commonService.getCounts(item.getLineId(),"data_v","freq","frequency","T","AVG",item.getClDid().toString(),process.toString(),param.getStartTime(),param.getEndTime());
                    }
                    vo.setDevId(item.getDeviceId());
                    vo.setDevName(devMap.get(item.getDeviceId()).getName());
                    vo.setLineId(item.getLineId());
                    vo.setLineName(item.getName());
                    vo.setLineIntegrity(
                            statisticalDataDTO == null || statisticalDataDTO.getFrequency() == null
                                    ? 0 : Integer.parseInt(statisticalDataDTO.getFrequency()) / dueCount * 100.0
                    );
                    result.add(vo);
                });
            }
        }
        return result;
    }

    @Override
    public List<DataVo> getDevOnlineRate(StatisticsDataParam param) {
        return Collections.emptyList();
    }

    @Override
    public List<HalfMonthReportVO> getHalfMonthReport(StatisticsDataParam param) {
        List<HalfMonthReportVO> result = new ArrayList<>();
        //获取装置
        List<CsEquipmentDeliveryPO> equipmentDeliveryList = equipmentFeignClient.getAll().getData();
        if (CollectionUtil.isNotEmpty(equipmentDeliveryList)) {
            Map<String, CsEquipmentDeliveryPO> map = equipmentDeliveryList.stream().collect(Collectors.toMap(CsEquipmentDeliveryPO::getId, Function.identity()));
            List<CsEquipmentDeliveryPO> processList = Objects.isNull(param.getProcess())
                    ? equipmentDeliveryList
                    : equipmentDeliveryList.stream()
                    .filter(item -> Objects.equals(item.getProcess(), param.getProcess()))
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(processList)) {
                //获取监测点集合
                List<String> devList = processList.stream().map(CsEquipmentDeliveryPO::getId).collect(Collectors.toList());
                if (CollectionUtil.isEmpty(devList)) {
                    return result;
                }
                List<CsLinePO> csLineList = csLineFeignClient.getLinesByDevList(devList).getData();
                if (CollectionUtil.isNotEmpty(csLineList)) {
                    Map<String,List<CsLinePO>> devMap = csLineList.stream().collect(Collectors.groupingBy(CsLinePO::getDeviceId));
                    List<String> lineList = csLineList.stream().map(CsLinePO::getLineId).distinct().collect(Collectors.toList());
                    List<String> deviceList = csLineList.stream().map(CsLinePO::getDeviceId).distinct().collect(Collectors.toList());
                    //获取监测点数据完整性
                    IcdBzParam param1 = new IcdBzParam();
                    param1.setLineList(lineList);
                    param1.setStartTime(param.getStartTime());
                    param1.setEndTime(param.getEndTime());
                    List<RStatIntegrityD> list1 = integrityFeignClient.list(param1).getData();
                    //获取终端在线率
                    IcdBzParam param2 = new IcdBzParam();
                    param2.setLineList(deviceList);
                    param2.setStartTime(param.getStartTime());
                    param2.setEndTime(param.getEndTime());
                    List<RStatOnlineRateD> list2 = onlineRateFeignClient.list(param2).getData();
                    //获取监测点最新数据时间
                    List<CsLineLatestData> list3 = csLineLatestDataFeignClient.listData().getData();
                    equipmentDeliveryList.forEach(dev->{
                        List<CsLinePO> list = devMap.get(dev.getId());
                        if (CollectionUtil.isNotEmpty(list)) {
                            list.forEach(line->{
                                DevDetailDTO dto = csLedgerFeignClient.queryDevDetail(dev.getId()).getData();
                                HalfMonthReportVO vo = new HalfMonthReportVO();
                                vo.setEngineeringName(dto.getEngineeringName());
                                vo.setProjectName(dto.getProjectName());
                                vo.setDevName(dev.getName());
                                vo.setDevType(dev.getDevModel());
                                vo.setMac(dev.getMac());
                                vo.setOperationalTime(dev.getCreateTime());
                                vo.setOperationalStatus(dev.getUsageStatus() == 0 ? "停运" : "在运");
                                if (Objects.equals(line.getName(),"治理监测点")) {
                                    int moduleNumber = Objects.isNull(map.get(dev.getId()).getModuleNumber()) ? 0 : map.get(dev.getId()).getModuleNumber();
                                    vo.setLineName(line.getName() + "(" + moduleNumber + "模块)");
                                } else {
                                    vo.setLineName(line.getName());
                                }
                                vo.setCommunicationStatus(dev.getRunStatus() == 1 ? "离线" : "在线");
                                vo.setLatestTime(LocalDateTime.now());
                                vo.setProcess(dev.getProcess());

                                List<RStatIntegrityD> l1 = list1.stream().filter(item -> item.getLineIndex().equals(line.getLineId())).collect(Collectors.toList());
                                if (CollectionUtil.isNotEmpty(l1)) {
                                    double ratio = BigDecimal.valueOf(
                                            l1.stream().mapToDouble(RStatIntegrityD::getRealTime).sum() * 100.0
                                    ).divide(
                                            BigDecimal.valueOf(l1.stream().mapToDouble(RStatIntegrityD::getDueTime).sum()),
                                            2, RoundingMode.HALF_UP
                                    ).doubleValue();
                                    vo.setIntegrity(Math.min(ratio,100.0));
                                } else {
                                    vo.setIntegrity(0.0);
                                }

                                List<RStatOnlineRateD> l2 = list2.stream().filter(item -> item.getDevIndex().equals(dev.getId())).collect(Collectors.toList());
                                if (CollectionUtil.isNotEmpty(l2)) {
                                    int onlineMin = l2.stream().mapToInt(RStatOnlineRateD::getOnlineMin).sum();
                                    double ratio = new BigDecimal(onlineMin * 100.0 / (1440 * l2.size())).setScale(2,RoundingMode.HALF_UP).doubleValue();
                                    vo.setOnlineRate(Math.min(ratio,100.0));
                                } else {
                                    vo.setOnlineRate(0.0);
                                }
                                //获取最新数据时间
                                List<CsLineLatestData> l3 = list3.stream().filter(item -> item.getLineId().equals(line.getLineId())).collect(Collectors.toList());
                                vo.setLatestTime(CollectionUtil.isNotEmpty(l3) ? l3.get(0).getTimeId() : null);
                                result.add(vo);
                            });
                        }
                    });
                }
            }
        }
        return result;
    }

}
