package com.njcn.product.terminal.mysqlTerminal.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.utils.PubUtils;
import com.njcn.product.system.dict.mapper.DictDataMapper;
import com.njcn.product.system.other.mapper.AreaMapper;
import com.njcn.product.terminal.mysqlTerminal.mapper.*;
import com.njcn.product.terminal.mysqlTerminal.pojo.dto.GeneralDeviceDTO;
import com.njcn.product.terminal.mysqlTerminal.pojo.dto.LedgerTreeDTO;
import com.njcn.product.terminal.mysqlTerminal.pojo.enums.LineBaseEnum;
import com.njcn.product.terminal.mysqlTerminal.pojo.enums.StatisticsEnum;
import com.njcn.product.terminal.mysqlTerminal.pojo.param.DeviceInfoParam;
import com.njcn.product.terminal.mysqlTerminal.pojo.param.UserReportParam;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.Device;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.Line;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.LineDetail;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.UserReportPO;
import com.njcn.product.terminal.mysqlTerminal.pojo.vo.LineDataVO;
import com.njcn.product.terminal.mysqlTerminal.pojo.vo.LineDetailDataVO;
import com.njcn.product.terminal.mysqlTerminal.pojo.vo.TerminalTree;
import com.njcn.product.terminal.mysqlTerminal.pojo.vo.UserLedgerVO;
import com.njcn.product.terminal.mysqlTerminal.service.CommGeneralService;
import com.njcn.product.terminal.mysqlTerminal.service.LineService;
import com.njcn.product.terminal.mysqlTerminal.service.UserReportPOService;
import com.njcn.product.terminal.utils.TerminalUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

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


/**
 * 监测点类
 *
 * @author denghuajun
 * @date 2022/2/23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LineServiceImpl extends ServiceImpl<LineMapper, Line> implements LineService {

    private final DeviceMapper deviceMapper;

    private final TreeMapper treeMapper;
    private final CommGeneralService commGeneralService;
    private final UserReportPOService userReportPOService;
    private final DictDataMapper dictDataMapper;
    private final LineDetailMapper lineDetailMapper;
    private final AreaMapper areaMapper;
    private final VoltageMapper voltageMapper;
    private final UserReportPOMapper userReportPOMapper;

    @Override
    public List<LedgerTreeDTO> getTree() {

        List<Device> deviceList = deviceMapper.selectList(new LambdaQueryWrapper<Device>().eq(Device::getRunFlag,0).eq(Device::getDevModel,1));
        List<Line> devList = this.baseMapper.selectList(new LambdaQueryWrapper<Line>().in(Line::getId,deviceList.stream().map(Device::getId).collect(Collectors.toList())));

        List<Line> ledgerList = this.baseMapper.selectList(new LambdaQueryWrapper<Line>().in(Line::getLevel, Stream.of(LineBaseEnum.GD_LEVEL.getCode(),LineBaseEnum.SUB_LEVEL.getCode(),LineBaseEnum.SUB_V_LEVEL.getCode(),LineBaseEnum.LINE_LEVEL.getCode()).collect(Collectors.toList())));
        List<Line> monitorList = ledgerList.stream().filter(it->Objects.equals(it.getLevel(),LineBaseEnum.LINE_LEVEL.getCode())).collect(Collectors.toList());
        List<Line> busBarList = ledgerList.stream().filter(it->Objects.equals(it.getLevel(),LineBaseEnum.SUB_V_LEVEL.getCode())).collect(Collectors.toList());
        Map<String,Line> busBarMap = busBarList.stream().collect(Collectors.toMap(Line::getId, Function.identity()));
        List<Line> stationList = ledgerList.stream().filter(it->Objects.equals(it.getLevel(),LineBaseEnum.SUB_LEVEL.getCode())).collect(Collectors.toList());
        List<Line> gdList = ledgerList.stream().filter(it->Objects.equals(it.getLevel(),LineBaseEnum.GD_LEVEL.getCode())).collect(Collectors.toList());



        List<LedgerTreeDTO> lineDtoList = monitorList.stream().map(it->{
            LedgerTreeDTO oracleLedgerTreeDTO = new LedgerTreeDTO();
            oracleLedgerTreeDTO.setId(it.getId());
            String busName = busBarMap.get(it.getPid()).getName();
            oracleLedgerTreeDTO.setName(busName+"_"+it.getName());
            oracleLedgerTreeDTO.setPid(it.getPids().split(StrUtil.COMMA)[LineBaseEnum.DEVICE_LEVEL.getCode()]);
            oracleLedgerTreeDTO.setLevel(4);
            return oracleLedgerTreeDTO;
        }).collect(Collectors.toList());

        List<LedgerTreeDTO> devDtoList = devList.stream().map(it->{
            LedgerTreeDTO oracleLedgerTreeDTO = new LedgerTreeDTO();
            oracleLedgerTreeDTO.setId(it.getId());
            oracleLedgerTreeDTO.setName(it.getName());
            oracleLedgerTreeDTO.setPid(it.getPid());
            oracleLedgerTreeDTO.setLevel(3);
            oracleLedgerTreeDTO.setChildren(lineDtoList.stream().filter(line-> Objects.equals(it.getId(),line.getPid())).collect(Collectors.toList()));
            return oracleLedgerTreeDTO;
        }).collect(Collectors.toList());
        List<LedgerTreeDTO> stationDtoList = stationList.stream().map(it->{
            LedgerTreeDTO oracleLedgerTreeDTO = new LedgerTreeDTO();
            oracleLedgerTreeDTO.setId(it.getId());
            oracleLedgerTreeDTO.setName(it.getName());
            oracleLedgerTreeDTO.setPid(it.getPid());
            oracleLedgerTreeDTO.setLevel(2);
            oracleLedgerTreeDTO.setChildren(devDtoList.stream().filter(dev->Objects.equals(it.getId(),dev.getPid())).collect(Collectors.toList()));
            return oracleLedgerTreeDTO;
        }).collect(Collectors.toList());
        List<LedgerTreeDTO> gdDtoList = gdList.stream().map(it->{
            LedgerTreeDTO oracleLedgerTreeDTO = new LedgerTreeDTO();
            oracleLedgerTreeDTO.setId(it.getId());
            oracleLedgerTreeDTO.setName(it.getName());
            oracleLedgerTreeDTO.setPid("0");
            oracleLedgerTreeDTO.setLevel(1);
            oracleLedgerTreeDTO.setChildren(stationDtoList.stream().filter(sub->Objects.equals(it.getId(),sub.getPid())).collect(Collectors.toList()));
            return oracleLedgerTreeDTO;
        }).collect(Collectors.toList());
        return gdDtoList;
    }




    /**
     * 5层树排除设备 母线监测点合并
     *
     * @author cdf
     * @date 2022/1/13
     */
    @Override
    public List<TerminalTree> getTerminalTreeForFive(DeviceInfoParam deviceInfoParam) {
        //deviceInfoParam.setDeptIndex(RequestUtil.getDeptIndex());
        // 获取所有数据
        List<GeneralDeviceDTO> generalDeviceDTOList = commGeneralService.getDeviceInfo(deviceInfoParam, Stream.of(0).collect(Collectors.toList()), Stream.of(1).collect(Collectors.toList()));
        // 判断所有数据集合状态
        if (CollectionUtil.isNotEmpty(generalDeviceDTOList)) {
            // 创建集合
            List<TerminalTree> taiZhang = new ArrayList<>();
            // 获取用户
            UserReportParam userReportParam = new UserReportParam();
            List<UserLedgerVO> userReportPOList = userReportPOService.selectUserList(userReportParam);
            userReportPOList = userReportPOList.stream().filter(it -> StrUtil.isNotBlank(it.getStationId())).collect(Collectors.toList());
            Map<String, UserLedgerVO> userMap = userReportPOList.stream().collect(Collectors.toMap(UserLedgerVO::getId, Function.identity()));

            // 遍历集合
            for (GeneralDeviceDTO generalDeviceDTO : generalDeviceDTOList) {
                // 创建实体类
                TerminalTree terminalTree = new TerminalTree();
                // 判断监测点索引集合状态
                if (CollectionUtils.isEmpty(generalDeviceDTO.getLineIndexes())) {
                    continue;
                }
                // 通过供电公司索引查询省会
                List<TerminalTree> proList = treeMapper.getProvinceList(generalDeviceDTO.getGdIndexes());
                // 通过供电公司索引查询供电公司信息
                List<TerminalTree> gdList = treeMapper.getGdList(generalDeviceDTO.getGdIndexes());
                // 通过供电站索引查询供电站信息
                List<TerminalTree> subList = treeMapper.getSubList(generalDeviceDTO.getSubIndexes());
                // 通过监测点索引查询监测点信息
                List<TerminalTree> lineList = treeMapper.getLineList(generalDeviceDTO.getLineIndexes());

                List<TerminalTree> userLineList = lineList.stream().filter(it->StrUtil.isNotBlank(it.getObjId())).collect(Collectors.toList());
                List<TerminalTree> otherLineList = lineList.stream().filter(it->StrUtil.isBlank(it.getObjId())).collect(Collectors.toList());

                Map<String,List<TerminalTree>> temMap = new HashMap<>();
                if(CollUtil.isNotEmpty(userLineList)) {
                    Map<String, List<TerminalTree>> objMap = userLineList.stream().collect(Collectors.groupingBy(TerminalTree::getObjId));
                    List<TerminalTree> temList = new ArrayList<>();
                    objMap.forEach((objId, monitorList) -> {
                        UserLedgerVO userLedgerVO = userMap.get(objId);
                        TerminalTree tree = new TerminalTree();
                        tree.setLevel(LineBaseEnum.USER_LEVEL.getCode());
                        tree.setPid(userLedgerVO.getStationId());
                        tree.setId(userLedgerVO.getId());
                        tree.setChildren(monitorList);
                        int devSize = (int) monitorList.stream().map(x -> {
                            // 获取父id字符串，通过 逗号 分割 成一个数组
                            String[] pid = x.getPids().split(StrUtil.COMMA);
                            return pid[LineBaseEnum.DEVICE_LEVEL.getCode()];
                        }).distinct().count();
                        tree.setName(userLedgerVO.getProjectName());
                        //特殊处理，用户层级下面的装置数量临时存到pids字段。
                        tree.setPids(String.valueOf(devSize));
                        temList.add(tree);
                    });
                    temMap = temList.stream().collect(Collectors.groupingBy(TerminalTree::getPid));
                }



                //处理变电站
                dealChildrenData(subList, otherLineList, temMap,true);

                //监测点前面加序号,后面不需要删除下面两行就行
                //Integer[] arr = {1};
                //subList.forEach(item->item.getChildren().forEach(it->it.setName((arr[0]++ +"_"+it.getName()))));
                //处理供电公司
                dealChildrenData(gdList, subList, null,false);

                if (deviceInfoParam.getStatisticalType().getCode().equalsIgnoreCase(StatisticsEnum.POWER_NETWORK.getCode())) {
                    terminalTree.setChildren(gdList);
                } else {
                    //还需要额外处理省会
                    dealChildrenData(proList, gdList, null,false);
                    terminalTree.setChildren(proList);
                }
                terminalTree.setId(generalDeviceDTO.getIndex());
                terminalTree.setName(generalDeviceDTO.getName());
                terminalTree.setLevel(0);
                taiZhang.add(terminalTree);
            }
            return taiZhang;
        } else {
            return new ArrayList<>();
        }
    }


    @Override
    public LineDetailDataVO getLineDetailData(String id) {
        if (StringUtils.isEmpty(id)) {
            return new LineDetailDataVO();
        } else {
            //根据id查询当前信息的pids
            List<String> pids = Arrays.asList(this.baseMapper.selectById(id).getPids().split(","));
            List<String> list = new ArrayList(pids);
            list.add(id);
            List<LineDataVO> lineDataVOList = this.baseMapper.getLineDetail(list);
            LineDetailDataVO lineDetailDataVO = new LineDetailDataVO();
            String areaId = "", devId = "", voId = "";
            for (LineDataVO lineDataVO : lineDataVOList) {
                switch (lineDataVO.getLevel()) {
                    case 1:
                        areaId = lineDataVO.getName();
                        break;
                    case 2:
                        lineDetailDataVO.setGdName(lineDataVO.getName());
                        break;
                    case 3:
                        lineDetailDataVO.setBdName(lineDataVO.getName());
                        break;
                    case 4:
                        devId = lineDataVO.getId();
                        lineDetailDataVO.setDevName(lineDataVO.getName());
                        break;
                    case 5:
                        voId = lineDataVO.getId();
                        break;
                    case 6:
                        lineDetailDataVO.setLineName(lineDataVO.getName());
                        break;
                    default:
                        break;
                }
            }
            lineDetailDataVO.setAreaName(areaMapper.selectById(areaId).getName());
            lineDetailDataVO.setScale(dictDataMapper.selectById(voltageMapper.selectById(voId).getScale()).getName());
            LineDetail lineDetail = lineDetailMapper.selectById(id);
            Device device = deviceMapper.selectById(devId);
            lineDetailDataVO.setManufacturer(dictDataMapper.selectById(device.getManufacturer()).getName());
            lineDetailDataVO.setComFlag(TerminalUtils.comFlag(device.getComFlag()));
            lineDetailDataVO.setRunFlag(TerminalUtils.lineRunFlag(lineDetail.getRunFlag()));
            lineDetailDataVO.setIp(device.getIp());
            lineDetailDataVO.setLoginTime(device.getLoginTime());
            lineDetailDataVO.setDevId(device.getId());
            lineDetailDataVO.setBusinessType(dictDataMapper.selectById(lineDetail.getBusinessType()).getName());
            lineDetailDataVO.setLoadType(dictDataMapper.selectById(lineDetail.getLoadType()).getName());
            UserReportPO userReportPO = userReportPOMapper.selectById(lineDetail.getObjId());
            if(Objects.nonNull(userReportPO)){
                lineDetailDataVO.setObjName(userReportPO.getProjectName());
            }else {
                lineDetailDataVO.setObjName("/");
            }
            lineDetailDataVO.setId(lineDetail.getNum());
            lineDetailDataVO.setPtType(TerminalUtils.ptType(lineDetail.getPtType()));
            lineDetailDataVO.setPt(lineDetail.getPt1() + "/" + lineDetail.getPt2());
            lineDetailDataVO.setCt(lineDetail.getCt1() + "/" + lineDetail.getCt2());
            lineDetailDataVO.setDealCapacity(lineDetail.getDealCapacity());
            lineDetailDataVO.setDevCapacity(lineDetail.getDevCapacity());
            lineDetailDataVO.setShortCapacity(lineDetail.getShortCapacity());
            lineDetailDataVO.setStandardCapacity(lineDetail.getStandardCapacity());
            lineDetailDataVO.setTimeInterval(lineDetail.getTimeInterval());
            lineDetailDataVO.setOwner(lineDetail.getOwner());
            lineDetailDataVO.setOwnerDuty(lineDetail.getOwnerDuty());
            lineDetailDataVO.setOwnerTel(lineDetail.getOwnerTel());
            lineDetailDataVO.setWiringDiagram(lineDetail.getWiringDiagram());
            lineDetailDataVO.setPtPhaseType(lineDetail.getPtPhaseType());
            lineDetailDataVO.setUpdateTime(device.getUpdateTime());
            return lineDetailDataVO;
        }

    }

    /**
     * 处理变电站
     *
     * @param targetData
     * @param childrenData
     * @param isLine
     */
    private void dealChildrenData(List<TerminalTree> targetData, List<TerminalTree> childrenData,Map<String,List<TerminalTree>> userLineMap, boolean isLine) {
        // 创建一个map集合，用于封装对象
        Map<String, List<TerminalTree>> groupLine;
        if (isLine) {
            // 通过stream流分组
            groupLine = childrenData.stream().collect(Collectors.groupingBy(terminalTree -> {
                // 获取父id字符串，通过 逗号 分割 成一个数组
                String[] pid = terminalTree.getPids().split(StrUtil.COMMA);
                return pid[LineBaseEnum.SUB_LEVEL.getCode()];
            }));
        } else {
            groupLine = childrenData.stream().collect(Collectors.groupingBy(TerminalTree::getPid));
        }
        //变电站
        targetData.forEach(terminalTree -> {
            List<TerminalTree> terminalTrees = new ArrayList<>();
            if(groupLine.containsKey(terminalTree.getId())) {
                terminalTrees.addAll(groupLine.get(terminalTree.getId()).stream().sorted(Comparator.comparing(TerminalTree::getSort)).collect(Collectors.toList()));
            }
            if (isLine) {
                //变电站集合
                int size = (int) terminalTrees.stream().map(x -> {
                    // 获取父id字符串，通过 逗号 分割 成一个数组
                    String[] pid = x.getPids().split(StrUtil.COMMA);
                    return pid[LineBaseEnum.DEVICE_LEVEL.getCode()];
                }).distinct().count();

                int devSize = 0;
                if(userLineMap.containsKey(terminalTree.getId())){
                    List<TerminalTree> userList = userLineMap.get(terminalTree.getId());
                    devSize= (int) userList.stream().mapToDouble(it->Integer.parseInt(it.getPids())).sum();
                    terminalTrees.addAll(userList);
                }
                int sumDev = size+devSize;
                terminalTree.setName(terminalTree.getName() + "（" +sumDev+ "台装置）");
                terminalTree.setChildren(terminalTrees);
            } else {
                terminalTree.setChildren(terminalTrees);
            }
        });
    }



}
