package com.njcn.device.pms.service.distribution.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.pojo.param.StatisticsBizBaseParam;
import com.njcn.device.pms.mapper.distribution.PwMonitorMapper;
import com.njcn.device.pms.pojo.dto.PwPmsMonitorDTO;
import com.njcn.device.pms.pojo.param.PwPmsMonitorParam;
import com.njcn.device.pms.service.distribution.IPwMonitorService;
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.dto.DeptDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 配网监测点信息
 *
 * @author yzh
 * @date 2022/10/28
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class IPwMonitorServiceImpl implements IPwMonitorService {

    private final DeptFeignClient deptFeignClient;

    private final PwMonitorMapper pwMonitorMapper;

    private final DicDataFeignClient dicDataFeignClient;

    /**
     * 获取配网所有监测点信息
     *
     * @param pwPmsMonitorParam 参数条件
     * @return 配网所有监测点信息
     */
    @Override
    public List<PwPmsMonitorDTO> getPwMonitorList(PwPmsMonitorParam pwPmsMonitorParam) {
        //定义待返回终端信息
        List<PwPmsMonitorDTO> pwPmsMonitorDTOS = new ArrayList<>();
        List<DeptDTO> deptInfos = deptFeignClient.getDeptDescendantIndexes(pwPmsMonitorParam.getOrgId(), Stream.of(0, 1).collect(Collectors.toList())).getData();
        // 过滤出传入id的子单位id
        List<DeptDTO> directDeptInfos = deptInfos.stream()
                .filter(deptDTO -> deptDTO.getPid().equals(pwPmsMonitorParam.getOrgId()))
                .collect(Collectors.toList());

        if (CollectionUtil.isEmpty(directDeptInfos)) {
            //没有直接子部门，获取当前部门所有信息
            List<DeptDTO> dept = deptInfos.stream()
                    .filter(deptDTO -> deptDTO.getId().equals(pwPmsMonitorParam.getOrgId()))
                    .collect(Collectors.toList());
            //获取monitor详细数据
            pwPmsMonitorDTOS = pwMonitorMapper.getPwMonitorDataList(Collections.singletonList(dept.get(0).getCode()),pwPmsMonitorParam.getMonitorTag(), pwPmsMonitorParam);

            if (CollUtil.isEmpty(pwPmsMonitorDTOS)) {
                PwPmsMonitorDTO pwPmsMonitorDTO = new PwPmsMonitorDTO();
                pwPmsMonitorDTO.setOrgId(dept.get(0).getCode());
                pwPmsMonitorDTO.setOrgName(dept.get(0).getArea());
                pwPmsMonitorDTOS.add(pwPmsMonitorDTO);
            }
        } else {
            // 遍历子单位id
            for (DeptDTO deptDTO : directDeptInfos) {
                // 与全部单位id比较，取出上级为子单位id的集合
                List<DeptDTO> descendantDeptDTO = deptInfos.stream()
                        .filter(d -> d.getPids().contains(deptDTO.getId()))
                        .collect(Collectors.toList());
                //形成需要查询监测点的部门索引
                List<String> deptIdList = descendantDeptDTO.stream()
                        .map(DeptDTO::getCode)
                        .distinct()
                        .collect(Collectors.toList());
                deptIdList.add(deptDTO.getCode());
                List<PwPmsMonitorDTO> pwMonitorDataList = pwMonitorMapper.getPwMonitorDataList(deptIdList,pwPmsMonitorParam.getMonitorTag(), pwPmsMonitorParam);
                pwPmsMonitorDTOS.addAll(pwMonitorDataList);
            }
        }
        return pwPmsMonitorDTOS;
    }

    @Override
    public List<PwPmsMonitorDTO> getPwNewMonitorList(PwPmsMonitorParam pwPmsMonitorParam) {
        List<DeptDTO> deptInfos = deptFeignClient.getDeptDescendantIndexes(pwPmsMonitorParam.getOrgId(), Stream.of(0, 1).collect(Collectors.toList())).getData();
        List<String> orgCodeList= deptInfos.stream().map(DeptDTO::getCode).collect(Collectors.toList());
        List<PwPmsMonitorDTO> pwPmsMonitorDTOS = pwMonitorMapper.getPwMonitorDataNewList(orgCodeList,pwPmsMonitorParam.getIds(),pwPmsMonitorParam.getMonitorTag(), pwPmsMonitorParam);
        List<String> ids = pwPmsMonitorDTOS.stream().map(PwPmsMonitorDTO::getMonitorId).collect(Collectors.toList());
        List<List<String>> pendingIds = ListUtils.partition(ids, 50000);
        List<PwPmsMonitorDTO> pwMonitorName=new ArrayList<>();
        for (List<String> pendingId : pendingIds) {
             pwMonitorName.addAll(pwMonitorMapper.getPwMonitorName(pendingId, pwPmsMonitorParam.getMonitorName()));
        }
        Map<String, PwPmsMonitorDTO> monitorMap = pwPmsMonitorDTOS.stream().collect(Collectors.toMap(PwPmsMonitorDTO::getMonitorId, Function.identity()));
        pwMonitorName.stream().forEach(x->{
            if(monitorMap.containsKey(x.getMonitorId())){
                BeanUtil.copyProperties(x,monitorMap.get(x.getMonitorId()));
            }
        });
        return pwMonitorName;
    }

    @Override
    public List<PwPmsMonitorDTO> getPwPhotovoltaicMonitorList(PwPmsMonitorParam pwPmsMonitorParam) {
        //定义待返回终端信息
        List<DeptDTO> deptInfos = deptFeignClient.getDepSonDetailByDeptId(pwPmsMonitorParam.getOrgId()).getData();
        // 过滤出传入id的子单位id
        List<String> deptIdList = deptInfos.stream()
                .map(DeptDTO::getCode)
                .distinct()
                .collect(Collectors.toList());
        //获取分布式光伏字典id
        DictData data = dicDataFeignClient.getDicDataByCode(DicDataEnum.DISTRIBUTED_PHOTOVOLTAICS.getCode()).getData();
        pwPmsMonitorParam.setMonitorTag(Arrays.asList(data.getId()));
        //获取monitor详细数据
        return pwMonitorMapper.getPwPhotovoltaicMonitorList(deptIdList, pwPmsMonitorParam);

    }

    @Override
    public List<PwPmsMonitorDTO> getPwSubsetMonitorList(PwPmsMonitorParam pwPmsMonitorParam) {
        //定义待返回终端信息
        List<PwPmsMonitorDTO> pwPmsMonitorDTOS = new ArrayList<>();
        List<DeptDTO> deptInfos = deptFeignClient.getDeptDescendantIndexes(pwPmsMonitorParam.getOrgId(), Stream.of(0, 1).collect(Collectors.toList())).getData();
        // 过滤出传入id的子单位id
        List<DeptDTO> directDeptInfos = deptInfos.stream()
                .filter(deptDTO -> deptDTO.getPid().equals(pwPmsMonitorParam.getOrgId()))
                .collect(Collectors.toList());

        if (CollectionUtil.isEmpty(directDeptInfos)) {
            //没有直接子部门，获取当前部门所有信息
            List<DeptDTO> dept = deptInfos.stream()
                    .filter(deptDTO -> deptDTO.getId().equals(pwPmsMonitorParam.getOrgId()))
                    .collect(Collectors.toList());
            //获取monitor详细数据
            pwPmsMonitorDTOS = pwMonitorMapper.getPwMonitorDataList(Collections.singletonList(dept.get(0).getCode()),pwPmsMonitorParam.getMonitorTag(), pwPmsMonitorParam);
            if (CollUtil.isEmpty(pwPmsMonitorDTOS)) {
                PwPmsMonitorDTO pwPmsMonitorDTO = new PwPmsMonitorDTO();
                pwPmsMonitorDTO.setOrgId(dept.get(0).getCode());
                pwPmsMonitorDTO.setOrgName(dept.get(0).getArea());
                pwPmsMonitorDTOS.add(pwPmsMonitorDTO);
            }
        } else {
            // 遍历子单位id
            List<String> deptCodes = directDeptInfos.stream().map(DeptDTO::getCode).collect(Collectors.toList());
            List<PwPmsMonitorDTO> pwMonitorDataList = pwMonitorMapper.getPwMonitorDataList(deptCodes,pwPmsMonitorParam.getMonitorTag(), pwPmsMonitorParam);
            pwPmsMonitorDTOS.addAll(pwMonitorDataList);
        }
        return pwPmsMonitorDTOS;
    }

    @Override
    public List<List<Integer>> getCompositeIndicators(StatisticsBizBaseParam param) {
        List<List<Integer>> info=new ArrayList<>(2);
        List<DictData> monitorType = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.LINE_SORT.getCode()).getData();
        Map<String, DictData> dictDataMap = monitorType.stream()
                .collect(Collectors.toMap(DictData::getId, Function.identity()));
        PwPmsMonitorParam pwPmsMonitorParam = new PwPmsMonitorParam();
        DictData data = dicDataFeignClient.getDicDataByCode(DicDataEnum.DISTRIBUTED_PHOTOVOLTAICS.getCode()).getData();
        if(ObjectUtil.isNull(data)){
            throw new BusinessException(CommonResponseEnum.NO_DATA, "分布式光伏字典,为空");
        }
        pwPmsMonitorParam.setMonitorTag(Arrays.asList(data.getId()));
        pwPmsMonitorParam.setOrgId(param.getId()); //单位id
        List<PwPmsMonitorDTO> pwMonitorList = this.getPwNewMonitorList(pwPmsMonitorParam);
        Map<String, List<PwPmsMonitorDTO>> collect = pwMonitorList.stream().collect(Collectors.groupingBy(PwPmsMonitorDTO::getMonitorSort));
        //初始化对象
        List<Integer> monitorList=new ArrayList<>(3);
        monitorList.add(0);
        monitorList.add(0);
        monitorList.add(0);
        List<Integer> terminalList= BeanUtil.copyToList(monitorList,Integer.class);
        collect.forEach((key,value)->{
            if (dictDataMap.containsKey(key)) {
                DictData dictData = dictDataMap.get(key);
                //一类监测点
                if(DicDataEnum.ONE_LINE.getCode().equals(dictData.getCode())){
                    monitorList.set(0,value.size());
                    terminalList.set(0,value.stream().map(PwPmsMonitorDTO::getTerminalId).distinct().collect(Collectors.toList()).size());
                }
                //二类监测点
                if(DicDataEnum.TWO_LINE.getCode().equals(dictData.getCode())){
                    monitorList.set(1,value.size());
                    terminalList.set(1,value.stream().map(PwPmsMonitorDTO::getTerminalId).distinct().collect(Collectors.toList()).size());
                }
                //三类监测点
                if(DicDataEnum.THREE_LINE.getCode().equals(dictData.getCode())){
                    monitorList.set(2,value.size());
                    terminalList.set(2,value.stream().map(PwPmsMonitorDTO::getTerminalId).distinct().collect(Collectors.toList()).size());
                }
            }
        });
        info.add(monitorList);
        info.add(terminalList);
        return info;
    }
}

