package com.njcn.device.pq.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.common.pojo.enums.common.ServerEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.EnumUtils;
import com.njcn.device.biz.pojo.dto.*;
import com.njcn.device.biz.pojo.param.DeptGetLineParam;
import com.njcn.device.pq.mapper.LineMapper;
import com.njcn.device.pq.service.CommTerminalService;
import com.njcn.device.pq.service.DeptLineService;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.dto.DeptDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * pqs
 *
 * @author cdf
 * @date 2023/5/10
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class CommTerminalServiceImpl implements CommTerminalService {

    private final String commTerminal = "commTerminal#";

    private final DeptLineService deptLineService;

    private final DeptFeignClient deptFeignClient;

    private final RedisUtil redisUtil;

    private final LineMapper lineMapper;





    /**
     * 基础获取单位信息
     * @author cdf
     * @date 2023/5/10
     */
    @Override
    public List<DeptGetBase> getDeptChildrenByParent(DeptGetLineParam deptGetLineParam) {
        /*List<DeptGetBase> redisResult = (List<DeptGetBase>) redisUtil.getObjectByKey(commTerminal + deptGetLineParam.getDeptId());
        if (CollectionUtil.isNotEmpty(redisResult)) {
            return redisResult;
        }*/
        List<DeptGetBase> result = new ArrayList<>();
        List<DeptDTO> deptDTOList = deptFeignClient.getDeptDescendantIndexes(deptGetLineParam.getDeptId(), Stream.of(0, 1).collect(Collectors.toList())).getData();
        deptDTOList.forEach(it -> {
            DeptGetBase deptGetBase = new DeptGetBase();
            deptGetBase.setUnitId(it.getId());
            deptGetBase.setUnitName(it.getName());
            List<String> deptChildren = deptDTOList.stream().filter(deptDTO -> deptDTO.getPids().contains(it.getId())).map(DeptDTO::getId).collect(Collectors.toList());
            deptChildren.add(it.getId());
            deptGetBase.setUnitChildrenList(deptChildren);
            result.add(deptGetBase);
        });
        redisUtil.saveByKey(commTerminal + deptGetLineParam.getDeptId(),result);
        return result;
    }


    @Override
    public List<DeptGetChildrenMoreDTO> deptGetLine(DeptGetLineParam deptGetLineParam) {
        List<DeptGetChildrenMoreDTO> result = new ArrayList<>();
        List<DeptGetBase> temDept = getDeptChildrenByParent(deptGetLineParam);
        Map<String, List<LineDevGetDTO>> map = deptLineService.lineDevGet(filterDataTypeNew(deptGetLineParam.getServerName()),1);
        temDept.forEach(item -> {
            DeptGetChildrenMoreDTO deptGetChildrenMoreDTO = new DeptGetChildrenMoreDTO();
            deptGetChildrenMoreDTO.setUnitId(item.getUnitId());
            deptGetChildrenMoreDTO.setUnitName(item.getUnitName());
            deptGetChildrenMoreDTO.setUnitChildrenList(item.getUnitChildrenList());
            List<String> deptIds = item.getUnitChildrenList();
            if (CollectionUtil.isNotEmpty(deptIds)) {
                List<LineDevGetDTO> lineList = new ArrayList<>();
                deptIds.forEach(i -> {
                    if (map.containsKey(i)) {
                        lineList.addAll(map.get(i));
                    }
                });
                deptGetChildrenMoreDTO.setLineBaseList(lineList);
            }
            result.add(deptGetChildrenMoreDTO);
        });
        return result;
    }


    @Override
    public List<DeptGetSubStationDTO> deptSubStation(DeptGetLineParam deptGetLineParam) {
        List<DeptGetSubStationDTO> result = new ArrayList<>();
        List<DeptGetBase> temDept = getDeptChildrenByParent(deptGetLineParam);
        Map<String, List<String>> map = deptLineService.orgSubStationGet(filterDataTypeNew(deptGetLineParam.getServerName()));
        temDept.forEach(item -> {
            DeptGetSubStationDTO deptGetSubStationDTO = new DeptGetSubStationDTO();
            deptGetSubStationDTO.setUnitId(item.getUnitId());
            deptGetSubStationDTO.setUnitName(item.getUnitName());
            deptGetSubStationDTO.setUnitChildrenList(item.getUnitChildrenList());
            List<String> deptIds = item.getUnitChildrenList();
            if (CollectionUtil.isNotEmpty(deptIds)) {
                List<String> lineList = new ArrayList<>();
                deptIds.forEach(i -> {
                    if (map.containsKey(i)) {
                        lineList.addAll(map.get(i));
                    }
                });
                deptGetSubStationDTO.setStationIds(lineList);
            }
            result.add(deptGetSubStationDTO);
        });
        return result;
    }

    @Override
    public List<DeptGetBusBarDTO> deptBusBar(DeptGetLineParam deptGetLineParam) {
        List<DeptGetBusBarDTO> result = new ArrayList<>();
        List<DeptGetBase> temDept = getDeptChildrenByParent(deptGetLineParam);
        Map<String, List<LineDevGetDTO>> map = deptLineService.lineDevGet(filterDataTypeNew(deptGetLineParam.getServerName()),2);
        temDept.forEach(item -> {
            DeptGetBusBarDTO deptGetBusBarDTO = new DeptGetBusBarDTO();
            deptGetBusBarDTO.setUnitId(item.getUnitId());
            deptGetBusBarDTO.setUnitName(item.getUnitName());
            deptGetBusBarDTO.setUnitChildrenList(item.getUnitChildrenList());
            List<String> deptIds = item.getUnitChildrenList();
            if (CollectionUtil.isNotEmpty(deptIds)) {
                List<String> lineList = new ArrayList<>();
                deptIds.forEach(i -> {
                    if (map.containsKey(i)) {
                        lineList.addAll(map.get(i).stream().map(LineDevGetDTO::getPointId).collect(Collectors.toList()));
                    }
                });
                deptGetBusBarDTO.setBusBarIds(lineList);
            }
            result.add(deptGetBusBarDTO);
        });
        return result;
    }

    @Override
    public List<DeptGetDeviceDTO> deptGetDevice(DeptGetLineParam deptGetLineParam,Integer type) {
        List<DeptGetDeviceDTO> result = new ArrayList<>();
        List<DeptGetBase> temDept = getDeptChildrenByParent(deptGetLineParam);
        Map<String, List<LineDevGetDTO>> map = deptLineService.lineDevGet(filterDataTypeNew(deptGetLineParam.getServerName()),3);
        temDept.forEach(item -> {
            DeptGetDeviceDTO deptGetDeviceDTO = new DeptGetDeviceDTO();
            deptGetDeviceDTO.setUnitId(item.getUnitId());
            deptGetDeviceDTO.setUnitName(item.getUnitName());
            deptGetDeviceDTO.setUnitChildrenList(item.getUnitChildrenList());
            List<String> deptIds = item.getUnitChildrenList();
            if (CollectionUtil.isNotEmpty(deptIds)) {
                List<LineDevGetDTO> devGetDTOList = new ArrayList<>();
                deptIds.forEach(i -> {
                    if (map.containsKey(i)) {
                        devGetDTOList.addAll(map.get(i));
                    }
                });
                deptGetDeviceDTO.setDeviceList(devGetDTOList);
            }
            result.add(deptGetDeviceDTO);
        });
        return result;
    }

    @Override
    public LineDevGetBandDTO substationGetLine(String substationId) {
        LineDevGetBandDTO lineDevGetBandDTO = new LineDevGetBandDTO();
        List<LineDevGetDTO> subList = lineMapper.getLineBySubStation(substationId);
        lineDevGetBandDTO.setZwList(subList);
        return lineDevGetBandDTO;
    }





    private List<Integer> filterDataTypeNew(String serverName) {
        List<Integer> devType = new ArrayList<>();
        devType.add(2);
        ServerEnum serverEnum = EnumUtils.getServerEnumByName(serverName);
        switch (serverEnum) {
            case EVENT:
                devType.add(0);
                break;
            case HARMONIC:
                devType.add(1);
                break;
            default:
                devType.add(0);
                devType.add(1);
                break;
        }
        return devType;
    }












    /*-------------------------------------------------------------------------------------*/

    /**
     * @author cdf
     * @date 2023/5/10
     */
    @Override
    public List<DeptGetChildrenDTO> deptGetLineList(DeptGetLineParam deptGetLineParam) {
        List<DeptGetChildrenDTO> all = new ArrayList<>();
        List<DeptDTO> deptDTOList = deptFeignClient.getDeptDescendantIndexes(deptGetLineParam.getDeptId(), Stream.of(0, 1).collect(Collectors.toList())).getData();
        getAllChildren(deptGetLineParam.getDeptId(), deptDTOList, all);
        Map<String, List<String>> map = deptLineService.getLineByDeptRelation(filterDataType(deptGetLineParam.getServerName()));
        all.forEach(item -> {
            List<String> itemDeptChildren = item.getDeptChildren();
            if (CollectionUtil.isNotEmpty(itemDeptChildren)) {
                List<String> lineIds = new ArrayList<>();
                itemDeptChildren.forEach(i -> {
                    if (map.containsKey(i)) {
                        lineIds.addAll(map.get(i));
                    }
                });
                item.setLineIds(lineIds);
            }
        });
        return all;
    }

    /**
     * 筛选数据类型
     */
    private Integer filterDataType(String serverName) {
        ServerEnum serverEnum = EnumUtils.getServerEnumByName(serverName);
        switch (serverEnum) {
            case EVENT:
                return 0;
            case HARMONIC:
                return 1;
            default:
                throw new BusinessException(CommonResponseEnum.INVALID_PARAMETER);
        }

    }


    /**
     * 获取指定部门所有子孙部门id
     *
     * @author cdf
     * @date 2023/4/24
     */
    private void getAllChildren(String deptId, List<DeptDTO> deptAllList, List<DeptGetChildrenDTO> res) {
        deptAllList.stream().filter(item -> item.getPid().equals(deptId)).forEach(it -> {
            List<String> deptChildren = deptAllList.stream().filter(deptDTO -> deptDTO.getPids().contains(it.getId())).map(DeptDTO::getId).collect(Collectors.toList());
            deptChildren.add(it.getId());
            DeptGetChildrenDTO generalDeviceDTO = new DeptGetChildrenDTO();
            generalDeviceDTO.setDeptId(it.getId());
            generalDeviceDTO.setDeptName(it.getName());
            generalDeviceDTO.setDeptChildren(deptChildren);
            res.add(generalDeviceDTO);
            getAllChildren(it.getId(), deptAllList, res);
        });
    }

}
