package com.njcn.harmonic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.dto.*;
import com.njcn.device.biz.pojo.param.DeptGetLineParam;
import com.njcn.device.pq.api.LineIntegrityClient;
import com.njcn.device.pq.pojo.po.RStatIntegrityD;
import com.njcn.device.pq.pojo.vo.GridDiagramVO;
import com.njcn.harmonic.mapper.RMpTargetWarnDMapper;
import com.njcn.harmonic.pojo.param.StatSubstationBizBaseParam;
import com.njcn.harmonic.pojo.po.RMpTargetWarnDPO;
import com.njcn.harmonic.service.IRMpTargetWarnDService;
import com.njcn.harmonic.service.IRStatLimitTargetDService;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wr
 * @since 2024-04-19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RMpTargetWarnDServiceImpl extends ServiceImpl<RMpTargetWarnDMapper, RMpTargetWarnDPO> implements IRMpTargetWarnDService {

    private final DeptFeignClient deptFeignClient;
    private final DicDataFeignClient dicDataFeignClient;
    private final CommTerminalGeneralClient commTerminalGeneralClient;
    private final IRStatLimitTargetDService targetDService;
    private final LineIntegrityClient lineIntegrityClient;
    @Override
    public GridDiagramVO getSubLineGiveAnAlarm(StatSubstationBizBaseParam param) {
        //获取电压等级
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE_STAND.getCode()).getData();

        List<DictData> v = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.PANORAMIC_VOLTAGE.getCode()).getData();
        List<String> voltageIds;
        //获取电压等级550 220 110 35
        if(CollUtil.isNotEmpty(v)){
            List<String> vName = v.stream().map(DictData::getName).collect(Collectors.toList());
            voltageIds = dictDataList.stream().filter(item -> vName.contains(item.getName())).sorted(Comparator.comparing(DictData::getSort).reversed()).map(DictData::getId).collect(Collectors.toList());
        }else{
            voltageIds = dictDataList.stream().filter(item -> Objects.equals(DicDataEnum.DY_500KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_220KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_110KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_35KV.getCode(), item.getCode())).sorted(Comparator.comparing(DictData::getSort).reversed()).map(DictData::getId).collect(Collectors.toList());
        }


        GridDiagramVO gridDiagramVO = new GridDiagramVO();
        List<GridDiagramVO.LineStatistics> info = new ArrayList<>();
        List<GridDiagramVO.LineStatistics> gwInfo = new ArrayList<>();

        //获取部门数据关系
        List<Dept> data = deptFeignClient.getDirectSonSelf(param.getId()).getData();
        DeptGetLineParam deptGetLineParam = new DeptGetLineParam();
        deptGetLineParam.setDeptId(param.getId());
        deptGetLineParam.setMonitorStateRunning(false);
        List<DeptGetSubStationDTO.Info> deptGetChildrenMoreDTOS = commTerminalGeneralClient.deptGetSubStationInfo(deptGetLineParam).getData();

        List<String> lineIDS = deptGetChildrenMoreDTOS.stream()
                .flatMap(x -> x.getStationIds().stream().flatMap(l -> l.getUnitChildrenList().stream()))
                .distinct()
                .collect(Collectors.toList());
        //根据r_stat_limit_target_d来判断是否告警allTime flicker_overtime

        List<String> integrityList =new ArrayList<>();
        //根据r_stat_limit_target_d来判断是否告警allTime flicker_overtime
        List<String> linesTarget=new ArrayList<>();
        if(CollUtil.isNotEmpty(lineIDS)){
            StatSubstationBizBaseParam baseParam=new StatSubstationBizBaseParam();
            baseParam.setIds(lineIDS);
            baseParam.setStartTime(DateUtil.beginOfDay(DateUtil.parse(param.getStartTime())).toString());
            baseParam.setEndTime(DateUtil.endOfDay(DateUtil.parse(param.getEndTime())).toString());
            linesTarget.addAll(targetDService.getLinesTarget(baseParam));
            List<RStatIntegrityD> integrityDS = lineIntegrityClient.getIntegrityByLineIds(lineIDS,
                    DateUtil.beginOfDay(DateUtil.parse(param.getStartTime())).toString(),
                    DateUtil.endOfDay(DateUtil.parse(param.getEndTime())).toString()).getData();
            integrityList.addAll(integrityDS.stream().filter(x->0==x.getIntegrityData()).map(RStatIntegrityD::getLineIndex).collect(Collectors.toList()));
        }


        Map<String, DeptGetSubStationDTO.Info> deptLineMap = deptGetChildrenMoreDTOS.stream().collect(Collectors.toMap(DeptGetSubStationDTO.Info::getUnitId, Function.identity()));
        GridDiagramVO.LineStatistics lineStatistics;
        GridDiagramVO.LineStatistics gwLineStatistics;
        for (Dept datum : data) {
            if (deptLineMap.containsKey(datum.getId())) {
                lineStatistics = new GridDiagramVO.LineStatistics();
                lineStatistics.setOrgId(datum.getId());
                lineStatistics.setOrgName(datum.getName());
                gwLineStatistics = new GridDiagramVO.LineStatistics();
                gwLineStatistics.setOrgId(datum.getId());
                gwLineStatistics.setOrgName(datum.getName());
                List<SubGetBase> subBaseList = deptLineMap.get(datum.getId()).getStationIds();
                List<GridDiagramVO.StatisticsData> statisticsData = new ArrayList<>();
                List<GridDiagramVO.StatisticsData> gwStatisticsData = new ArrayList<>();
                getSubStationStatisticsData(statisticsData, gwStatisticsData, subBaseList, voltageIds, linesTarget,integrityList);
                lineStatistics.setData(statisticsData);
                gwLineStatistics.setData(gwStatisticsData);

                info.add(lineStatistics);
                gwInfo.add(gwLineStatistics);
            }
        }
        gridDiagramVO.setInfo(info);
        gridDiagramVO.setGwInfo(gwInfo);
        return gridDiagramVO;
    }


    @Override
    public GridDiagramVO getAreaObjAlarm(StatSubstationBizBaseParam param) {
        //获取电压等级
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE_STAND.getCode()).getData();

        List<DictData> v = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.PANORAMIC_VOLTAGE.getCode()).getData();
        List<String> voltageIds;
        //获取电压等级550 220 110 35
        if(CollUtil.isNotEmpty(v)){
            List<String> vName = v.stream().map(DictData::getName).collect(Collectors.toList());
            voltageIds = dictDataList.stream().filter(item -> vName.contains(item.getName())).sorted(Comparator.comparing(DictData::getSort).reversed()).map(DictData::getId).collect(Collectors.toList());
        }else{
            voltageIds = dictDataList.stream().filter(item -> Objects.equals(DicDataEnum.DY_500KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_220KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_110KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_35KV.getCode(), item.getCode())).sorted(Comparator.comparing(DictData::getSort).reversed()).map(DictData::getId).collect(Collectors.toList());
        }
        GridDiagramVO gridDiagramVO = new GridDiagramVO();
        List<GridDiagramVO.LineStatistics> info = new ArrayList<>();
        List<GridDiagramVO.LineStatistics> gwInfo = new ArrayList<>();

        //获取部门数据关系
        List<Dept> data = deptFeignClient.getDirectSonSelf(param.getId()).getData();
        DeptGetLineParam deptGetLineParam = new DeptGetLineParam();
        deptGetLineParam.setDeptId(param.getId());
        deptGetLineParam.setMonitorStateRunning(false);
        List<DeptGetChildrenMoreDTO> deptGetChildrenMoreDTOS = commTerminalGeneralClient.deptGetLine(deptGetLineParam).getData();

        Map<String,DeptGetChildrenMoreDTO> listMap = deptGetChildrenMoreDTOS.stream().collect(Collectors.toMap(DeptGetChildrenMoreDTO::getUnitId,Function.identity()));

        GridDiagramVO.LineStatistics lineStatistics;
        GridDiagramVO.LineStatistics gwLineStatistics;
        for (Dept datum : data) {
            if (listMap.containsKey(datum.getId())) {
                lineStatistics = new GridDiagramVO.LineStatistics();
                lineStatistics.setOrgId(datum.getId());
                lineStatistics.setOrgName(datum.getName());
                gwLineStatistics = new GridDiagramVO.LineStatistics();
                gwLineStatistics.setOrgId(datum.getId());
                gwLineStatistics.setOrgName(datum.getName());
                List<LineDevGetDTO> baseList = listMap.get(datum.getId()).getLineBaseList().stream().filter(it->StrUtil.isNotBlank(it.getObjId())).collect(Collectors.toList());
                Map<String,List<LineDevGetDTO>> voltageMonitorMap = baseList.stream().collect(Collectors.groupingBy(LineDevGetDTO::getVoltageLevel));
                List<GridDiagramVO.StatisticsData> statisticsData = new ArrayList<>();
                List<GridDiagramVO.StatisticsData> gwStatisticsData = new ArrayList<>();

                List<String> idsList = new ArrayList<>();
                int allNum = 0;
                for(String voltage:voltageIds){
                    GridDiagramVO.StatisticsData voltageItem = new GridDiagramVO.StatisticsData();
                    voltageItem.setColumnName(voltage);
                    if(voltageMonitorMap.containsKey(voltage)){
                       List<String> ids = voltageMonitorMap.get(voltage).stream().map(LineDevGetDTO::getObjId).distinct().collect(Collectors.toList());
                        voltageItem.setNumOne((long)ids.size());
                        allNum+=ids.size();
                        idsList.addAll(ids);
                        voltageItem.setNumOneList(ids);
                    }else {
                        voltageItem.setNumOne(0L);
                        voltageItem.setNumOneList(new ArrayList<>());
                    }
                    statisticsData.add(voltageItem);
                }
                GridDiagramVO.StatisticsData dataSum = new GridDiagramVO.StatisticsData();
                dataSum.setNumOneList(idsList);
                dataSum.setNumOne((long)allNum);
                statisticsData.add(dataSum);
                lineStatistics.setData(statisticsData);
                gwLineStatistics.setData(gwStatisticsData);

                info.add(lineStatistics);
                gwInfo.add(gwLineStatistics);
            }
        }
        gridDiagramVO.setInfo(info);
        gridDiagramVO.setGwInfo(gwInfo);
        return gridDiagramVO;
    }

    private void getSubStationStatisticsData(List<GridDiagramVO.StatisticsData> statisticsData,
                                             List<GridDiagramVO.StatisticsData> gwStatisticsData,
                                             List<SubGetBase> subBaseList,
                                             List<String> voltageIds,
                                             List<String> list,
                                             List<String> integrityList
    ) {
        GridDiagramVO.StatisticsData data;
        for (String voltageId : voltageIds) {
            for (int i = 0; i < 2; i++) {
                data = new GridDiagramVO.StatisticsData();
                data.setColumnName(voltageId);
                int finalI = i;
                long count = subBaseList.stream()
                        .filter(x -> getIsUpToGrid(finalI, x, voltageId))
                        .map(SubGetBase::getId)
                        .distinct()
                        .count();
                data.setNumOne(count);
                data.setNumOneList(subBaseList.stream()
                        .filter(x -> getIsUpToGrid(finalI, x, voltageId))
                        .flatMap(x -> x.getUnitChildrenList().stream()).distinct().collect(Collectors.toList()));

                AtomicLong num = new AtomicLong();
                List<String> alarm = new ArrayList<>();
                subBaseList.stream().filter(x -> getIsUpToGrid(finalI, x, voltageId)).forEach(x -> {
                    List<String> line = new ArrayList<>();
                    //0：全部 1：国网
                    if (finalI == 0) {
                        line.addAll(x.getUnitChildrenList());
                    } else {
                        line.addAll(x.getGwUnitChildrenList());
                    }
                    List<String> collect=new ArrayList<>();
                    collect.addAll(list.stream().filter(d -> line.contains(d)).collect(Collectors.toList()));
                    collect.addAll(integrityList.stream().filter(d -> line.contains(d)).collect(Collectors.toList()));

                    if (CollUtil.isNotEmpty(collect)) {
                        num.getAndIncrement();
                        alarm.addAll(collect);
                    }

                });
                data.setNumTwo(num.get());
                data.setNumTwoList(alarm.stream().distinct().collect(Collectors.toList()));
                if (i == 0) {
                    statisticsData.add(data);
                } else {
                    gwStatisticsData.add(data);
                }
            }
        }
        //总数信息
        data = new GridDiagramVO.StatisticsData();
        data.setNumOne(subBaseList.stream()
                .map(SubGetBase::getId)
                .distinct()
                .count());
        data.setNumOneList(subBaseList.stream()
                .flatMap(x -> x.getUnitChildrenList().stream()).distinct().collect(Collectors.toList()));
        AtomicLong num = new AtomicLong();
        List<String> alarm = new ArrayList<>();
        subBaseList.stream().forEach(x -> {
            List<String> line = x.getUnitChildrenList();
            List<String> alarmList=new ArrayList<>();
            alarmList.addAll(list.stream().filter(d -> line.contains(d)).collect(Collectors.toList()));
            alarmList.addAll(integrityList.stream().filter(d -> line.contains(d)).collect(Collectors.toList()));
            if (CollUtil.isNotEmpty(alarmList)) {
                num.getAndIncrement();
                alarm.addAll(alarmList.stream().distinct().collect(Collectors.toList()));
            }
        });
        data.setNumTwo(num.get());
        data.setNumTwoList(alarm);
        statisticsData.add(data);
        //国网监测点
        data = new GridDiagramVO.StatisticsData();
        data.setNumOne(subBaseList.stream()
                .filter(x -> 1 == x.getIsUpToGrid())
                .map(SubGetBase::getId)
                .distinct()
                .count());
        data.setNumOneList(subBaseList.stream()
                .filter(x -> 1 == x.getIsUpToGrid())
                .flatMap(x -> x.getUnitChildrenList().stream()).distinct().collect(Collectors.toList()));
        AtomicLong gwNum = new AtomicLong();
        List<String> gwAlarm = new ArrayList<>();
        subBaseList.stream().filter(x -> 1 == x.getIsUpToGrid()).forEach(x -> {
            List<String> line = x.getGwUnitChildrenList();
            List<String> alarmList=new ArrayList<>();
            alarmList.addAll(list.stream().filter(d -> line.contains(d)).collect(Collectors.toList()));
            alarmList.addAll(integrityList.stream().filter(d -> line.contains(d)).collect(Collectors.toList()));
            if (CollUtil.isNotEmpty(alarmList)) {
                gwNum.getAndIncrement();
                gwAlarm.addAll(alarmList.stream().distinct().collect(Collectors.toList()));
            }
        });
        data.setNumTwo(gwNum.get());
        data.setNumTwoList(gwAlarm);
        gwStatisticsData.add(data);
    }

    private Boolean getIsUpToGrid(Integer type, SubGetBase subGetBase, String voltageId) {
        //0：全部 1：国网上送监测点
        if (type == 0) {
            return voltageId.equals(subGetBase.getVoltageLevel());
        } else {
            return voltageId.equals(subGetBase.getVoltageLevel()) && 1 == subGetBase.getIsUpToGrid();
        }
    }
}
